commit c2d7588391b0010f2b911102b0939b2a91510751
Author: [huawei.guo] <[huawei.guo@vhall.com]>
Date: Mon Dec 2 16:59:30 2024 +0800
init ui
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..5b1a804
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# 告诉EditorConfig插件,这是根文件,不用继续往上查找
+root = true
+
+# 匹配全部文件
+[*]
+# 缩进风格,可选space、tab
+indent_style = space
+# 缩进的空格数
+indent_size = 2
+# 设置字符集
+charset = utf-8
+# 结尾换行符,可选lf、cr、crlf
+end_of_line = lf
+# 在文件结尾插入新行
+trim_trailing_whitespace = true
+# 删除一行中的前后空格
+insert_final_newline = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000..14e1335
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,35 @@
+# 页面标题
+VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
+
+# 开发环境配置
+VITE_APP_ENV = 'development'
+
+# 开发环境
+VITE_APP_BASE_API = '/dev-api'
+
+# 应用访问路径 例如使用前缀 /admin/
+VITE_APP_CONTEXT_PATH = '/'
+
+# 监控地址
+VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
+
+# SnailJob 控制台地址
+VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
+
+VITE_APP_PORT = 80
+
+# 接口加密功能开关(如需关闭 后端也必须对应关闭)
+VITE_APP_ENCRYPT = true
+# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
+
+# 客户端id
+VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
+
+# websocket 开关 默认使用sse推送
+VITE_APP_WEBSOCKET = false
+
+# sse 开关
+VITE_APP_SSE = true
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..1109bc6
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,38 @@
+# 页面标题
+VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
+
+# 生产环境配置
+VITE_APP_ENV = 'production'
+
+# 应用访问路径 例如使用前缀 /admin/
+VITE_APP_CONTEXT_PATH = '/'
+
+# 监控地址
+VITE_APP_MONITOR_ADMIN = '/admin/applications'
+
+# SnailJob 控制台地址
+VITE_APP_SNAILJOB_ADMIN = '/snail-job'
+
+# 生产环境
+VITE_APP_BASE_API = '/prod-api'
+
+# 是否在打包时开启压缩,支持 gzip 和 brotli
+VITE_BUILD_COMPRESS = gzip
+
+VITE_APP_PORT = 80
+
+# 接口加密功能开关(如需关闭 后端也必须对应关闭)
+VITE_APP_ENCRYPT = true
+# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
+VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
+
+# 客户端id
+VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
+
+# websocket 开关 默认使用sse推送
+VITE_APP_WEBSOCKET = false
+
+# sse 开关
+VITE_APP_SSE = true
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..e74db40
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,17 @@
+*.sh
+node_modules
+*.md
+*.woff
+*.ttf
+.vscode
+.idea
+dist
+/public
+/docs
+.husky
+.local
+/bin
+.eslintrc.cjs
+prettier.config.js
+src/assets
+tailwind.config.js
diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
new file mode 100644
index 0000000..a6661b6
--- /dev/null
+++ b/.eslintrc-auto-import.json
@@ -0,0 +1,312 @@
+{
+ "globals": {
+ "ComponentInternalInstance": true,
+ "TransferKey": true,
+ "ElFormRules": true,
+ "CheckboxValueType": true,
+ "PropType": true,
+ "DateModelType": true,
+ "UploadFile": true,
+ "ElFormInstance": true,
+ "ElTableInstance": true,
+ "ElTreeInstance": true,
+ "ElTreeSelectInstance": true,
+ "ElSelectInstance": true,
+ "ElUploadInstance": true,
+ "ElCardInstance": true,
+ "ElDialogInstance": true,
+ "ElInputInstance": true,
+ "ElInputNumberInstance": true,
+ "ElRadioInstance": true,
+ "ElRadioGroupInstance": true,
+ "ElRadioButtonInstance": true,
+ "ElCheckboxInstance": true,
+ "ElCheckboxGroupInstance": true,
+ "ElSwitchInstance": true,
+ "ElDatePickerInstance": true,
+ "ElTimePickerInstance": true,
+ "ElTimeSelectInstance": true,
+ "ElScrollbarInstance": true,
+ "ElCascaderInstance": true,
+ "ElColorPickerInstance": true,
+ "ElRateInstance": true,
+ "ElSliderInstance": true,
+ "useRouter": true,
+ "useRoute": true,
+ "EffectScope": true,
+ "ElTable": true,
+ "ElSelect": true,
+ "ElUpload": true,
+ "ElForm": true,
+ "ElTree": true,
+ "ElMessage": true,
+ "ElMessageBox": true,
+ "asyncComputed": true,
+ "autoResetRef": true,
+ "computed": true,
+ "computedAsync": true,
+ "computedEager": true,
+ "computedInject": true,
+ "computedWithControl": true,
+ "controlledComputed": true,
+ "controlledRef": true,
+ "createApp": true,
+ "createEventHook": true,
+ "createGlobalState": true,
+ "createInjectionState": true,
+ "createReactiveFn": true,
+ "createSharedComposable": true,
+ "createUnrefFn": true,
+ "customRef": true,
+ "debouncedRef": true,
+ "debouncedWatch": true,
+ "defineAsyncComponent": true,
+ "defineComponent": true,
+ "eagerComputed": true,
+ "effectScope": true,
+ "extendRef": true,
+ "getCurrentInstance": true,
+ "getCurrentScope": true,
+ "h": true,
+ "ignorableWatch": true,
+ "inject": true,
+ "isDefined": true,
+ "isProxy": true,
+ "isReactive": true,
+ "isReadonly": true,
+ "isRef": true,
+ "makeDestructurable": true,
+ "markRaw": true,
+ "nextTick": true,
+ "onActivated": true,
+ "onBeforeMount": true,
+ "onBeforeUnmount": true,
+ "onBeforeUpdate": true,
+ "onClickOutside": true,
+ "onDeactivated": true,
+ "onErrorCaptured": true,
+ "onKeyStroke": true,
+ "onLongPress": true,
+ "onMounted": true,
+ "onRenderTracked": true,
+ "onRenderTriggered": true,
+ "onScopeDispose": true,
+ "onServerPrefetch": true,
+ "onStartTyping": true,
+ "onUnmounted": true,
+ "onUpdated": true,
+ "pausableWatch": true,
+ "provide": true,
+ "reactify": true,
+ "reactifyObject": true,
+ "reactive": true,
+ "reactiveComputed": true,
+ "reactiveOmit": true,
+ "reactivePick": true,
+ "readonly": true,
+ "ref": true,
+ "refAutoReset": true,
+ "refDebounced": true,
+ "refDefault": true,
+ "refThrottled": true,
+ "refWithControl": true,
+ "resolveComponent": true,
+ "resolveDirective": true,
+ "resolveRef": true,
+ "resolveUnref": true,
+ "shallowReactive": true,
+ "shallowReadonly": true,
+ "shallowRef": true,
+ "syncRef": true,
+ "syncRefs": true,
+ "templateRef": true,
+ "throttledRef": true,
+ "throttledWatch": true,
+ "toRaw": true,
+ "toReactive": true,
+ "toRef": true,
+ "toRefs": true,
+ "triggerRef": true,
+ "tryOnBeforeMount": true,
+ "tryOnBeforeUnmount": true,
+ "tryOnMounted": true,
+ "tryOnScopeDispose": true,
+ "tryOnUnmounted": true,
+ "unref": true,
+ "unrefElement": true,
+ "until": true,
+ "useActiveElement": true,
+ "useArrayEvery": true,
+ "useArrayFilter": true,
+ "useArrayFind": true,
+ "useArrayFindIndex": true,
+ "useArrayFindLast": true,
+ "useArrayJoin": true,
+ "useArrayMap": true,
+ "useArrayReduce": true,
+ "useArraySome": true,
+ "useArrayUnique": true,
+ "useAsyncQueue": true,
+ "useAsyncState": true,
+ "useAttrs": true,
+ "useBase64": true,
+ "useBattery": true,
+ "useBluetooth": true,
+ "useBreakpoints": true,
+ "useBroadcastChannel": true,
+ "useBrowserLocation": true,
+ "useCached": true,
+ "useClipboard": true,
+ "useCloned": true,
+ "useColorMode": true,
+ "useConfirmDialog": true,
+ "useCounter": true,
+ "useCssModule": true,
+ "useCssVar": true,
+ "useCssVars": true,
+ "useCurrentElement": true,
+ "useCycleList": true,
+ "useDark": true,
+ "useDateFormat": true,
+ "useDebounce": true,
+ "useDebounceFn": true,
+ "useDebouncedRefHistory": true,
+ "useDeviceMotion": true,
+ "useDeviceOrientation": true,
+ "useDevicePixelRatio": true,
+ "useDevicesList": true,
+ "useDisplayMedia": true,
+ "useDocumentVisibility": true,
+ "useDraggable": true,
+ "useDropZone": true,
+ "useElementBounding": true,
+ "useElementByPoint": true,
+ "useElementHover": true,
+ "useElementSize": true,
+ "useElementVisibility": true,
+ "useEventBus": true,
+ "useEventListener": true,
+ "useEventSource": true,
+ "useEyeDropper": true,
+ "useFavicon": true,
+ "useFetch": true,
+ "useFileDialog": true,
+ "useFileSystemAccess": true,
+ "useFocus": true,
+ "useFocusWithin": true,
+ "useFps": true,
+ "useFullscreen": true,
+ "useGamepad": true,
+ "useGeolocation": true,
+ "useIdle": true,
+ "useImage": true,
+ "useInfiniteScroll": true,
+ "useIntersectionObserver": true,
+ "useInterval": true,
+ "useIntervalFn": true,
+ "useKeyModifier": true,
+ "useLastChanged": true,
+ "useLocalStorage": true,
+ "useMagicKeys": true,
+ "useManualRefHistory": true,
+ "useMediaControls": true,
+ "useMediaQuery": true,
+ "useMemoize": true,
+ "useMemory": true,
+ "useMounted": true,
+ "useMouse": true,
+ "useMouseInElement": true,
+ "useMousePressed": true,
+ "useMutationObserver": true,
+ "useNavigatorLanguage": true,
+ "useNetwork": true,
+ "useNow": true,
+ "useObjectUrl": true,
+ "useOffsetPagination": true,
+ "useOnline": true,
+ "usePageLeave": true,
+ "useParallax": true,
+ "usePermission": true,
+ "usePointer": true,
+ "usePointerLock": true,
+ "usePointerSwipe": true,
+ "usePreferredColorScheme": true,
+ "usePreferredContrast": true,
+ "usePreferredDark": true,
+ "usePreferredLanguages": true,
+ "usePreferredReducedMotion": true,
+ "usePrevious": true,
+ "useRafFn": true,
+ "useRefHistory": true,
+ "useResizeObserver": true,
+ "useScreenOrientation": true,
+ "useScreenSafeArea": true,
+ "useScriptTag": true,
+ "useScroll": true,
+ "useScrollLock": true,
+ "useSessionStorage": true,
+ "useShare": true,
+ "useSlots": true,
+ "useSorted": true,
+ "useSpeechRecognition": true,
+ "useSpeechSynthesis": true,
+ "useStepper": true,
+ "useStorage": true,
+ "useStorageAsync": true,
+ "useStyleTag": true,
+ "useSupported": true,
+ "useSwipe": true,
+ "useTemplateRefsList": true,
+ "useTextDirection": true,
+ "useTextSelection": true,
+ "useTextareaAutosize": true,
+ "useThrottle": true,
+ "useThrottleFn": true,
+ "useThrottledRefHistory": true,
+ "useTimeAgo": true,
+ "useTimeout": true,
+ "useTimeoutFn": true,
+ "useTimeoutPoll": true,
+ "useTimestamp": true,
+ "useTitle": true,
+ "useToNumber": true,
+ "useToString": true,
+ "useToggle": true,
+ "useTransition": true,
+ "useUrlSearchParams": true,
+ "useUserMedia": true,
+ "useVModel": true,
+ "useVModels": true,
+ "useVibrate": true,
+ "useVirtualList": true,
+ "useWakeLock": true,
+ "useWebNotification": true,
+ "useWebSocket": true,
+ "useWebWorker": true,
+ "useWebWorkerFn": true,
+ "useWindowFocus": true,
+ "useWindowScroll": true,
+ "useWindowSize": true,
+ "watch": true,
+ "watchArray": true,
+ "watchAtMost": true,
+ "watchDebounced": true,
+ "watchEffect": true,
+ "watchIgnorable": true,
+ "watchOnce": true,
+ "watchPausable": true,
+ "watchPostEffect": true,
+ "watchSyncEffect": true,
+ "watchThrottled": true,
+ "watchTriggerable": true,
+ "watchWithFilter": true,
+ "whenever": true,
+ "ImportOption": true,
+ "TreeType": true,
+ "FieldOption": true,
+ "PageData": true,
+ "storeToRefs": true,
+ "DictDataOption": true,
+ "UploadOption": true
+ }
+}
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..6042c39
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,51 @@
+module.exports = {
+ env: {
+ browser: true,
+ node: true,
+ es6: true
+ },
+ parser: 'vue-eslint-parser',
+ extends: [
+ 'plugin:vue/vue3-recommended',
+ './.eslintrc-auto-import.json',
+ 'plugin:@typescript-eslint/recommended',
+ 'prettier',
+ 'plugin:prettier/recommended'
+ ],
+ parserOptions: {
+ ecmaVersion: '2020',
+ sourceType: 'module',
+ project: './tsconfig.*?.json',
+ parser: '@typescript-eslint/parser'
+ },
+ plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'],
+ rules: {
+ '@typescript-eslint/no-empty-function': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/no-unused-vars': 'off',
+ '@typescript-eslint/no-this-alias': 'off',
+
+ // vue
+ 'vue/multi-word-component-names': 'off',
+ 'vue/valid-define-props': 'off',
+ 'vue/no-v-model-argument': 'off',
+ 'prefer-rest-params': 'off',
+ // prettier
+ 'prettier/prettier': 'error',
+ '@typescript-eslint/ban-types': [
+ 'error',
+ {
+ // 关闭空类型检查 {}
+ extendDefaults: true,
+ types: {
+ '{}': false,
+ Function: false
+ }
+ }
+ ]
+ },
+ globals: {
+ DialogOption: 'readonly',
+ OptionType: 'readonly'
+ }
+};
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1fd56f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+.DS_Store
+.history
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+**/*.log
+
+tests/**/coverage/
+tests/e2e/reports
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.local
+
+package-lock.json
+yarn.lock
+pnpm-lock.yaml
+
+# 编译生成的文件
+auto-imports.d.ts
+components.d.ts
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..d251d2e
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,9 @@
+/dist/*
+.local
+.output.js
+/node_modules/**
+
+**/*.svg
+**/*.sh
+
+/public/*
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..6ca3ce5
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,20 @@
+{
+ "printWidth": 150,
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "quoteProps": "preserve",
+ "jsxSingleQuote": false,
+ "bracketSameLine": false,
+ "trailingComma": "none",
+ "bracketSpacing": true,
+ "embeddedLanguageFormatting": "auto",
+ "arrowParens": "always",
+ "requirePragma": false,
+ "insertPragma": false,
+ "proseWrap": "preserve",
+ "htmlWhitespaceSensitivity": "css",
+ "vueIndentScriptAndStyle": false,
+ "endOfLine": "auto"
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..32b3071
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2019 RuoYi-Vue-Plus
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..010adb9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+## 平台简介
+
+- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
+- 成员项目: 基于 vben(ant-design-vue) 的前端项目 [ruoyi-plus-vben](https://gitee.com/dapppp/ruoyi-plus-vben)
+- 配套后端代码仓库地址
+- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
+- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
+
+## 前端运行
+
+```bash
+# 克隆项目
+git clone https://gitee.com/JavaLionLi/plus-ui.git
+
+# 安装依赖
+npm install --registry=https://registry.npmmirror.com
+
+# 启动服务
+npm run dev
+
+# 构建生产环境
+npm run build:prod
+
+# 前端访问地址 http://localhost:80
+```
+
+## 本框架与RuoYi的业务差异
+
+| 业务 | 功能说明 | 本框架 | RuoYi |
+| ------------ | ------------------------------------------------------------- | ------ | ----------------------------- |
+| 租户管理 | 系统内租户的管理 如:租户套餐、过期时间、用户数量、企业信息等 | 支持 | 无 |
+| 租户套餐管理 | 系统内租户所能使用的套餐管理 如:套餐内所包含的菜单等 | 支持 | 无 |
+| 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
+| 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
+| 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
+| 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等 | 支持 | 支持 |
+| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | 支持 | 支持 |
+| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | 支持 | 支持 |
+| 参数管理 | 对系统动态配置常用参数 | 支持 | 支持 |
+| 通知公告 | 系统通知公告信息发布维护 | 支持 | 支持 |
+| 操作日志 | 系统正常操作日志记录和查询 系统异常信息日志记录和查询 | 支持 | 支持 |
+| 登录日志 | 系统登录日志记录查询包含登录异常 | 支持 | 支持 |
+| 文件管理 | 系统文件展示、上传、下载、删除等管理 | 支持 | 无 |
+| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理 | 支持 | 无 |
+| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作 | 支持 | 支持 |
+| 定时任务 | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等 | 支持 | 仅支持任务与日志管理 |
+| 代码生成 | 多数据源前后端代码的生成(java、html、xml、sql)支持CRUD下载 | 支持 | 仅支持单数据源 |
+| 系统接口 | 根据业务代码自动生成相关的api接口文档 | 支持 | 支持 |
+| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等 | 支持 | 仅支持单机CPU、内存、磁盘监控 |
+| 缓存监控 | 对系统的缓存信息查询,命令统计等。 | 支持 | 支持 |
+| 在线构建器 | 拖动表单元素生成相应的HTML代码。 | 支持 | 支持 |
+| 使用案例 | 系统的一些功能案例 | 支持 | 不支持 |
+
+## 演示图例
+
+| | |
+| ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
+| ![输入图片说明](https://foruda.gitee.com/images/1680077524361362822/270bb429_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680077619939771291/989bf9b6_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680077681751513929/1c27c5bd_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680077721559267315/74d63e23_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680077765638904515/1b75d4a6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078026375951297/eded7a4b_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078237104531207/0eb1b6a7_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078254306078709/5931e22f_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078287971528493/0b9af60a_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078308138770249/8d3b6696_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078352553634393/db5ef880_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078378238393374/601e4357_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078414983206024/2aae27c1_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078446738419874/ecce7d59_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078475971341775/149e8634_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078491666717143/3fadece7_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078558863188826/fb8ced2a_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078574561685461/ae68a0b2_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078594932772013/9d8bfec6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078626493093532/fcfe4ff6_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078643608812515/0295bd4f_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078685196286463/d7612c81_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078703877318597/56fce0bc_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078716586545643/b6dbd68f_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078734103217688/eb1e6aa6_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078759131415480/73c525d8_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078779416197879/75e3ed02_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078802329118061/77e10915_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078893627848351/34a1c342_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078928175016986/f126ec4a_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078941718318363/b68a0f72_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680078963175518631/3bb769a1_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680078982294090567/b31c343d_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079000642440444/77ca82a9_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680079020995074177/03b7d52e_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079039367822173/76811806_1766278.png '屏幕截图') |
+| ![输入图片说明](https://foruda.gitee.com/images/1680079274333484664/4dfdc7c0_1766278.png '屏幕截图') | ![输入图片说明](https://foruda.gitee.com/images/1680079290467458224/d6715fcf_1766278.png '屏幕截图') |
diff --git a/bin/build.bat b/bin/build.bat
new file mode 100644
index 0000000..ecbb454
--- /dev/null
+++ b/bin/build.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [Ϣ] Weḅdistļ
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+yarn build:prod
+
+pause
\ No newline at end of file
diff --git a/bin/package.bat b/bin/package.bat
new file mode 100644
index 0000000..f5b24e0
--- /dev/null
+++ b/bin/package.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [Ϣ] װWeḅnode_modulesļ
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+yarn --registry=https://registry.npmmirror.com
+
+pause
\ No newline at end of file
diff --git a/bin/run-web.bat b/bin/run-web.bat
new file mode 100644
index 0000000..d2fe397
--- /dev/null
+++ b/bin/run-web.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [Ϣ] ʹ Vite Web ̡
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+yarn dev
+
+pause
\ No newline at end of file
diff --git a/html/ie.html b/html/ie.html
new file mode 100644
index 0000000..4d2773d
--- /dev/null
+++ b/html/ie.html
@@ -0,0 +1,242 @@
+
+
+
+
+ 请升级您的浏览器
+
+
+
+
+
+
+ 请升级您的浏览器,以便我们更好的为您提供服务!
+ 您正在使用 Internet Explorer 的早期版本(IE11以下版本或使用该内核的浏览器)。这意味着在升级浏览器前,您将无法访问此网站。
+
+ 请注意:微软公司对Windows XP 及 Internet Explorer 早期版本的支持已经结束
+
+ 自 2016 年 1 月 12 日起,Microsoft 不再为 IE 11
+ 以下版本提供相应支持和更新。没有关键的浏览器安全更新,您的电脑可能易受有害病毒、间谍软件和其他恶意软件的攻击,它们可以窃取或损害您的业务数据和信息。请参阅
+ 微软对 Internet Explorer 早期版本的支持将于 2016 年 1 月 12 日结束的说明
+ 。
+
+
+ 您可以选择更先进的浏览器
+ 推荐使用以下浏览器的最新版本。如果您的电脑已有以下浏览器的最新版本则直接使用该浏览器访问即可。
+
+
+
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..aa1c86d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+ RuoYi-Vue-Plus多租户管理系统
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e67d60f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,91 @@
+{
+ "name": "ruoyi-vue-plus",
+ "version": "5.2.3",
+ "description": "RuoYi-Vue-Plus多租户管理系统",
+ "author": "LionLi",
+ "license": "MIT",
+ "type": "module",
+ "scripts": {
+ "dev": "vite serve --mode development",
+ "build:prod": "vite build --mode production",
+ "build:dev": "vite build --mode development",
+ "preview": "vite preview",
+ "lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ",
+ "prettier": "prettier --write ."
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://gitee.com/JavaLionLi/plus-ui.git"
+ },
+ "dependencies": {
+ "@element-plus/icons-vue": "2.3.1",
+ "@highlightjs/vue-plugin": "2.1.0",
+ "@vueup/vue-quill": "1.2.0",
+ "@vueuse/core": "10.9.0",
+ "animate.css": "4.1.1",
+ "await-to-js": "3.0.0",
+ "axios": "1.6.8",
+ "bpmn-js": "16.4.0",
+ "crypto-js": "4.2.0",
+ "diagram-js": "12.3.0",
+ "didi": "9.0.2",
+ "echarts": "5.5.0",
+ "element-plus": "2.7.8",
+ "file-saver": "2.0.5",
+ "fuse.js": "7.0.0",
+ "highlight.js": "11.9.0",
+ "image-conversion": "^2.1.1",
+ "js-cookie": "3.0.5",
+ "jsencrypt": "3.3.2",
+ "nprogress": "0.2.0",
+ "pinia": "2.1.7",
+ "screenfull": "6.0.2",
+ "vue": "3.4.34",
+ "vue-cropper": "1.1.1",
+ "vue-i18n": "9.10.2",
+ "vue-router": "4.3.2",
+ "vue-types": "5.1.1",
+ "vxe-table": "4.5.22"
+ },
+ "devDependencies": {
+ "@iconify/json": "2.2.201",
+ "@intlify/unplugin-vue-i18n": "3.0.1",
+ "@types/crypto-js": "4.2.2",
+ "@types/file-saver": "2.0.7",
+ "@types/js-cookie": "3.0.6",
+ "@types/node": "18.18.2",
+ "@types/nprogress": "0.2.3",
+ "@typescript-eslint/eslint-plugin": "7.3.1",
+ "@typescript-eslint/parser": "7.3.1",
+ "@unocss/preset-attributify": "0.58.6",
+ "@unocss/preset-icons": "0.58.6",
+ "@unocss/preset-uno": "0.58.6",
+ "@vitejs/plugin-vue": "5.0.4",
+ "@vue/compiler-sfc": "3.4.23",
+ "autoprefixer": "10.4.18",
+ "eslint": "8.57.0",
+ "eslint-config-prettier": "9.1.0",
+ "eslint-define-config": "2.1.0",
+ "eslint-plugin-prettier": "5.1.3",
+ "eslint-plugin-promise": "6.1.1",
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-import": "2.29.1",
+ "eslint-plugin-vue": "9.23.0",
+ "fast-glob": "3.3.2",
+ "postcss": "8.4.36",
+ "prettier": "3.2.5",
+ "sass": "1.72.0",
+ "typescript": "5.4.5",
+ "unocss": "0.58.6",
+ "unplugin-auto-import": "0.17.5",
+ "unplugin-icons": "0.18.5",
+ "unplugin-vue-components": "0.26.0",
+ "unplugin-vue-setup-extend-plus": "1.0.1",
+ "vite": "5.2.12",
+ "vite-plugin-compression": "0.5.1",
+ "vite-plugin-svg-icons": "2.0.1",
+ "vitest": "1.5.0",
+ "vue-eslint-parser": "9.4.2",
+ "vue-tsc": "2.0.13"
+ }
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..3f919d8
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..66dbed6
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/animate.ts b/src/animate.ts
new file mode 100644
index 0000000..7a23df8
--- /dev/null
+++ b/src/animate.ts
@@ -0,0 +1,48 @@
+// 前缀
+const animatePrefix = 'animate__animated ';
+// 开启随机动画 随机动画值
+const animateList: string[] = [
+ animatePrefix + 'animate__pulse',
+ animatePrefix + 'animate__rubberBand',
+ animatePrefix + 'animate__bounceIn',
+ animatePrefix + 'animate__bounceInLeft',
+ animatePrefix + 'animate__fadeIn',
+ animatePrefix + 'animate__fadeInLeft',
+ animatePrefix + 'animate__fadeInDown',
+ animatePrefix + 'animate__fadeInUp',
+ animatePrefix + 'animate__flipInX',
+ animatePrefix + 'animate__lightSpeedInLeft',
+ animatePrefix + 'animate__rotateInDownLeft',
+ animatePrefix + 'animate__rollIn',
+ animatePrefix + 'animate__rotateInDownLeft',
+ animatePrefix + 'animate__zoomIn',
+ animatePrefix + 'animate__zoomInDown',
+ animatePrefix + 'animate__slideInLeft',
+ animatePrefix + 'animate__lightSpeedIn'
+];
+// 关闭随机动画后的默认效果
+const defaultAnimate = animatePrefix + 'animate__fadeIn';
+// 搜索隐藏显示动画
+const searchAnimate = {
+ enter: '',
+ leave: ''
+};
+
+// 菜单搜索动画
+const menuSearchAnimate = {
+ enter: animatePrefix + 'animate__fadeIn',
+ leave: animatePrefix + 'animate__fadeOut'
+};
+// logo动画
+const logoAnimate = {
+ enter: animatePrefix + 'animate__fadeIn',
+ leave: animatePrefix + 'animate__fadeOut'
+};
+
+export default {
+ animateList,
+ defaultAnimate,
+ searchAnimate,
+ menuSearchAnimate,
+ logoAnimate
+};
diff --git a/src/api/demo/demo/index.ts b/src/api/demo/demo/index.ts
new file mode 100644
index 0000000..7441720
--- /dev/null
+++ b/src/api/demo/demo/index.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DemoVO, DemoForm, DemoQuery } from '@/api/demo/demo/types';
+
+/**
+ * 查询测试单列表
+ * @param query
+ * @returns {*}
+ */
+export const listDemo = (query?: DemoQuery): AxiosPromise => {
+ return request({
+ url: '/demo/demo/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询测试单详细
+ * @param id
+ */
+export const getDemo = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/demo/demo/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增测试单
+ * @param data
+ */
+export const addDemo = (data: DemoForm) => {
+ return request({
+ url: '/demo/demo',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改测试单
+ * @param data
+ */
+export const updateDemo = (data: DemoForm) => {
+ return request({
+ url: '/demo/demo',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除测试单
+ * @param id
+ */
+export const delDemo = (id: string | number | Array) => {
+ return request({
+ url: '/demo/demo/' + id,
+ method: 'delete'
+ });
+};
diff --git a/src/api/demo/demo/types.ts b/src/api/demo/demo/types.ts
new file mode 100644
index 0000000..ea51d32
--- /dev/null
+++ b/src/api/demo/demo/types.ts
@@ -0,0 +1,90 @@
+export interface DemoVO {
+ /**
+ * 主键
+ */
+ id: string | number;
+
+ /**
+ * 部门id
+ */
+ deptId: string | number;
+
+ /**
+ * 用户id
+ */
+ userId: string | number;
+
+ /**
+ * 排序号
+ */
+ orderNum: number;
+
+ /**
+ * key键
+ */
+ testKey: string;
+
+ /**
+ * 值
+ */
+ value: string;
+}
+
+export interface DemoForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: string | number;
+
+ /**
+ * 部门id
+ */
+ deptId?: string | number;
+
+ /**
+ * 用户id
+ */
+ userId?: string | number;
+
+ /**
+ * 排序号
+ */
+ orderNum?: number;
+
+ /**
+ * key键
+ */
+ testKey?: string;
+
+ /**
+ * 值
+ */
+ value?: string;
+}
+
+export interface DemoQuery extends PageQuery {
+ /**
+ * 部门id
+ */
+ deptId?: string | number;
+
+ /**
+ * 用户id
+ */
+ userId?: string | number;
+
+ /**
+ * 排序号
+ */
+ orderNum?: number;
+
+ /**
+ * key键
+ */
+ testKey?: string;
+
+ /**
+ * 值
+ */
+ value?: string;
+}
diff --git a/src/api/demo/tree/index.ts b/src/api/demo/tree/index.ts
new file mode 100644
index 0000000..562deb6
--- /dev/null
+++ b/src/api/demo/tree/index.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { TreeVO, TreeForm, TreeQuery } from '@/api/demo/tree/types';
+
+/**
+ * 查询测试树列表
+ * @param query
+ * @returns {*}
+ */
+export const listTree = (query?: TreeQuery): AxiosPromise => {
+ return request({
+ url: '/demo/tree/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询测试树详细
+ * @param id
+ */
+export const getTree = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/demo/tree/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增测试树
+ * @param data
+ */
+export const addTree = (data: TreeForm) => {
+ return request({
+ url: '/demo/tree',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改测试树
+ * @param data
+ */
+export const updateTree = (data: TreeForm) => {
+ return request({
+ url: '/demo/tree',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除测试树
+ * @param id
+ */
+export const delTree = (id: string | number | Array) => {
+ return request({
+ url: '/demo/tree/' + id,
+ method: 'delete'
+ });
+};
diff --git a/src/api/demo/tree/types.ts b/src/api/demo/tree/types.ts
new file mode 100644
index 0000000..e164d8b
--- /dev/null
+++ b/src/api/demo/tree/types.ts
@@ -0,0 +1,80 @@
+export interface TreeVO {
+ /**
+ * 主键
+ */
+ id: string | number;
+
+ /**
+ * 父id
+ */
+ parentId: string | number;
+
+ /**
+ * 部门id
+ */
+ deptId: string | number;
+
+ /**
+ * 用户id
+ */
+ userId: string | number;
+
+ /**
+ * 值
+ */
+ treeName: string;
+
+ /**
+ * 子对象
+ */
+ children: TreeVO[];
+}
+
+export interface TreeForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: string | number;
+
+ /**
+ * 父id
+ */
+ parentId?: string | number;
+
+ /**
+ * 部门id
+ */
+ deptId?: string | number;
+
+ /**
+ * 用户id
+ */
+ userId?: string | number;
+
+ /**
+ * 值
+ */
+ treeName?: string;
+}
+
+export interface TreeQuery {
+ /**
+ * 父id
+ */
+ parentId?: string | number;
+
+ /**
+ * 部门id
+ */
+ deptId?: string | number;
+
+ /**
+ * 用户id
+ */
+ userId?: string | number;
+
+ /**
+ * 值
+ */
+ treeName?: string;
+}
diff --git a/src/api/login.ts b/src/api/login.ts
new file mode 100644
index 0000000..c7c291e
--- /dev/null
+++ b/src/api/login.ts
@@ -0,0 +1,111 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
+import { UserInfo } from '@/api/system/user/types';
+
+// pc端固定客户端授权id
+const clientId = import.meta.env.VITE_APP_CLIENT_ID;
+
+/**
+ * @param data {LoginData}
+ * @returns
+ */
+export function login(data: LoginData): AxiosPromise {
+ const params = {
+ ...data,
+ clientId: data.clientId || clientId,
+ grantType: data.grantType || 'password'
+ };
+ return request({
+ url: '/auth/login',
+ headers: {
+ isToken: false,
+ isEncrypt: true,
+ repeatSubmit: false
+ },
+ method: 'post',
+ data: params
+ });
+}
+
+// 注册方法
+export function register(data: any) {
+ const params = {
+ ...data,
+ clientId: clientId,
+ grantType: 'password'
+ };
+ return request({
+ url: '/auth/register',
+ headers: {
+ isToken: false,
+ isEncrypt: true,
+ repeatSubmit: false
+ },
+ method: 'post',
+ data: params
+ });
+}
+
+/**
+ * 注销
+ */
+export function logout() {
+ request({
+ url: '/resource/sse/close',
+ method: 'get'
+ });
+ return request({
+ url: '/auth/logout',
+ method: 'post'
+ });
+}
+
+/**
+ * 获取验证码
+ */
+export function getCodeImg(): AxiosPromise {
+ return request({
+ url: '/auth/code',
+ headers: {
+ isToken: false
+ },
+ method: 'get',
+ timeout: 20000
+ });
+}
+
+/**
+ * 第三方登录
+ */
+export function callback(data: LoginData): AxiosPromise {
+ const LoginData = {
+ ...data,
+ clientId: clientId,
+ grantType: 'social'
+ };
+ return request({
+ url: '/auth/social/callback',
+ method: 'post',
+ data: LoginData
+ });
+}
+
+// 获取用户详细信息
+export function getInfo(): AxiosPromise {
+ return request({
+ url: '/system/user/getInfo',
+ method: 'get'
+ });
+}
+
+// 获取租户列表
+export function getTenantList(): AxiosPromise {
+ return request({
+ url: '/auth/tenant/list',
+ headers: {
+ isToken: false
+ },
+ method: 'get'
+ });
+}
diff --git a/src/api/menu.ts b/src/api/menu.ts
new file mode 100644
index 0000000..a3ae80e
--- /dev/null
+++ b/src/api/menu.ts
@@ -0,0 +1,11 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { RouteRecordRaw } from 'vue-router';
+
+// 获取路由
+export function getRouters(): AxiosPromise {
+ return request({
+ url: '/system/menu/getRouters',
+ method: 'get'
+ });
+}
diff --git a/src/api/monitor/cache/index.ts b/src/api/monitor/cache/index.ts
new file mode 100644
index 0000000..e45d6fb
--- /dev/null
+++ b/src/api/monitor/cache/index.ts
@@ -0,0 +1,59 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CacheVO } from './types';
+
+// 查询缓存详细
+export function getCache(): AxiosPromise {
+ return request({
+ url: '/monitor/cache',
+ method: 'get'
+ });
+}
+
+// 查询缓存名称列表
+export function listCacheName() {
+ return request({
+ url: '/monitor/cache/getNames',
+ method: 'get'
+ });
+}
+
+// 查询缓存键名列表
+export function listCacheKey(cacheName: string) {
+ return request({
+ url: '/monitor/cache/getKeys/' + cacheName,
+ method: 'get'
+ });
+}
+
+// 查询缓存内容
+export function getCacheValue(cacheName: string, cacheKey: string) {
+ return request({
+ url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
+ method: 'get'
+ });
+}
+
+// 清理指定名称缓存
+export function clearCacheName(cacheName: string) {
+ return request({
+ url: '/monitor/cache/clearCacheName/' + cacheName,
+ method: 'delete'
+ });
+}
+
+// 清理指定键名缓存
+export function clearCacheKey(cacheName: string, cacheKey: string) {
+ return request({
+ url: '/monitor/cache/clearCacheKey/' + cacheName + '/' + cacheKey,
+ method: 'delete'
+ });
+}
+
+// 清理全部缓存
+export function clearCacheAll() {
+ return request({
+ url: '/monitor/cache/clearCacheAll',
+ method: 'delete'
+ });
+}
diff --git a/src/api/monitor/cache/types.ts b/src/api/monitor/cache/types.ts
new file mode 100644
index 0000000..4017b65
--- /dev/null
+++ b/src/api/monitor/cache/types.ts
@@ -0,0 +1,7 @@
+export interface CacheVO {
+ commandStats: Array<{ name: string; value: string }>;
+
+ dbSize: number;
+
+ info: { [key: string]: string };
+}
diff --git a/src/api/monitor/loginInfo/index.ts b/src/api/monitor/loginInfo/index.ts
new file mode 100644
index 0000000..f8877c9
--- /dev/null
+++ b/src/api/monitor/loginInfo/index.ts
@@ -0,0 +1,36 @@
+import request from '@/utils/request';
+import { LoginInfoQuery, LoginInfoVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询登录日志列表
+export function list(query: LoginInfoQuery): AxiosPromise {
+ return request({
+ url: '/monitor/logininfor/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 删除登录日志
+export function delLoginInfo(infoId: string | number | Array) {
+ return request({
+ url: '/monitor/logininfor/' + infoId,
+ method: 'delete'
+ });
+}
+
+// 解锁用户登录状态
+export function unlockLoginInfo(userName: string | Array) {
+ return request({
+ url: '/monitor/logininfor/unlock/' + userName,
+ method: 'get'
+ });
+}
+
+// 清空登录日志
+export function cleanLoginInfo() {
+ return request({
+ url: '/monitor/logininfor/clean',
+ method: 'delete'
+ });
+}
diff --git a/src/api/monitor/loginInfo/types.ts b/src/api/monitor/loginInfo/types.ts
new file mode 100644
index 0000000..202c779
--- /dev/null
+++ b/src/api/monitor/loginInfo/types.ts
@@ -0,0 +1,20 @@
+export interface LoginInfoVO {
+ infoId: string | number;
+ tenantId: string | number;
+ userName: string;
+ status: string;
+ ipaddr: string;
+ loginLocation: string;
+ browser: string;
+ os: string;
+ msg: string;
+ loginTime: string;
+}
+
+export interface LoginInfoQuery extends PageQuery {
+ ipaddr: string;
+ userName: string;
+ status: string;
+ orderByColumn: string;
+ isAsc: string;
+}
diff --git a/src/api/monitor/online/index.ts b/src/api/monitor/online/index.ts
new file mode 100644
index 0000000..7484702
--- /dev/null
+++ b/src/api/monitor/online/index.ts
@@ -0,0 +1,36 @@
+import request from '@/utils/request';
+import { OnlineQuery, OnlineVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询在线用户列表
+export function list(query: OnlineQuery): AxiosPromise {
+ return request({
+ url: '/monitor/online/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 强退用户
+export function forceLogout(tokenId: string) {
+ return request({
+ url: '/monitor/online/' + tokenId,
+ method: 'delete'
+ });
+}
+
+// 获取当前用户登录在线设备
+export function getOnline() {
+ return request({
+ url: '/monitor/online',
+ method: 'get'
+ });
+}
+
+// 删除当前在线设备
+export function delOnline(tokenId: string) {
+ return request({
+ url: '/monitor/online/' + tokenId,
+ method: 'post'
+ });
+}
diff --git a/src/api/monitor/online/types.ts b/src/api/monitor/online/types.ts
new file mode 100644
index 0000000..8c0ec27
--- /dev/null
+++ b/src/api/monitor/online/types.ts
@@ -0,0 +1,15 @@
+export interface OnlineQuery extends PageQuery {
+ ipaddr: string;
+ userName: string;
+}
+
+export interface OnlineVO extends BaseEntity {
+ tokenId: string;
+ deptName: string;
+ userName: string;
+ ipaddr: string;
+ loginLocation: string;
+ browser: string;
+ os: string;
+ loginTime: number;
+}
diff --git a/src/api/monitor/operlog/index.ts b/src/api/monitor/operlog/index.ts
new file mode 100644
index 0000000..7ac3453
--- /dev/null
+++ b/src/api/monitor/operlog/index.ts
@@ -0,0 +1,28 @@
+import request from '@/utils/request';
+import { OperLogQuery, OperLogVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询操作日志列表
+export function list(query: OperLogQuery): AxiosPromise {
+ return request({
+ url: '/monitor/operlog/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 删除操作日志
+export function delOperlog(operId: string | number | Array) {
+ return request({
+ url: '/monitor/operlog/' + operId,
+ method: 'delete'
+ });
+}
+
+// 清空操作日志
+export function cleanOperlog() {
+ return request({
+ url: '/monitor/operlog/clean',
+ method: 'delete'
+ });
+}
diff --git a/src/api/monitor/operlog/types.ts b/src/api/monitor/operlog/types.ts
new file mode 100644
index 0000000..10f65c7
--- /dev/null
+++ b/src/api/monitor/operlog/types.ts
@@ -0,0 +1,53 @@
+export interface OperLogQuery extends PageQuery {
+ operIp: string;
+ title: string;
+ operName: string;
+ businessType: string;
+ status: string;
+ orderByColumn: string;
+ isAsc: string;
+}
+
+export interface OperLogVO extends BaseEntity {
+ operId: string | number;
+ tenantId: string;
+ title: string;
+ businessType: number;
+ businessTypes: number[] | undefined;
+ method: string;
+ requestMethod: string;
+ operatorType: number;
+ operName: string;
+ deptName: string;
+ operUrl: string;
+ operIp: string;
+ operLocation: string;
+ operParam: string;
+ jsonResult: string;
+ status: number;
+ errorMsg: string;
+ operTime: string;
+ costTime: number;
+}
+
+export interface OperLogForm {
+ operId: number | string | undefined;
+ tenantId: string | number | undefined;
+ title: string;
+ businessType: number;
+ businessTypes: number[] | undefined;
+ method: string;
+ requestMethod: string;
+ operatorType: number;
+ operName: string;
+ deptName: string;
+ operUrl: string;
+ operIp: string;
+ operLocation: string;
+ operParam: string;
+ jsonResult: string;
+ status: number;
+ errorMsg: string;
+ operTime: string;
+ costTime: number;
+}
diff --git a/src/api/system/client/index.ts b/src/api/system/client/index.ts
new file mode 100644
index 0000000..6b302b0
--- /dev/null
+++ b/src/api/system/client/index.ts
@@ -0,0 +1,80 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { ClientVO, ClientForm, ClientQuery } from '@/api/system/client/types';
+
+/**
+ * 查询客户端管理列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listClient = (query?: ClientQuery): AxiosPromise => {
+ return request({
+ url: '/system/client/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询客户端管理详细
+ * @param id
+ */
+export const getClient = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/system/client/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增客户端管理
+ * @param data
+ */
+export const addClient = (data: ClientForm) => {
+ return request({
+ url: '/system/client',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改客户端管理
+ * @param data
+ */
+export const updateClient = (data: ClientForm) => {
+ return request({
+ url: '/system/client',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除客户端管理
+ * @param id
+ */
+export const delClient = (id: string | number | Array) => {
+ return request({
+ url: '/system/client/' + id,
+ method: 'delete'
+ });
+};
+
+/**
+ * 状态修改
+ * @param clientId 客户端id
+ * @param status 状态
+ */
+export function changeStatus(clientId: string, status: string) {
+ const data = {
+ clientId,
+ status
+ };
+ return request({
+ url: '/system/client/changeStatus',
+ method: 'put',
+ data: data
+ });
+}
diff --git a/src/api/system/client/types.ts b/src/api/system/client/types.ts
new file mode 100644
index 0000000..142118d
--- /dev/null
+++ b/src/api/system/client/types.ts
@@ -0,0 +1,135 @@
+export interface ClientVO {
+ /**
+ * id
+ */
+ id: string | number;
+
+ /**
+ * 客户端id
+ */
+ clientId: string;
+
+ /**
+ * 客户端key
+ */
+ clientKey: string;
+
+ /**
+ * 客户端秘钥
+ */
+ clientSecret: string;
+
+ /**
+ * 授权类型
+ */
+ grantTypeList: string[];
+
+ /**
+ * 设备类型
+ */
+ deviceType: string;
+
+ /**
+ * token活跃超时时间
+ */
+ activeTimeout: number;
+
+ /**
+ * token固定超时
+ */
+ timeout: number;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ status: string;
+}
+
+export interface ClientForm extends BaseEntity {
+ /**
+ * id
+ */
+ id?: string | number;
+
+ /**
+ * 客户端id
+ */
+ clientId?: string | number;
+
+ /**
+ * 客户端key
+ */
+ clientKey?: string;
+
+ /**
+ * 客户端秘钥
+ */
+ clientSecret?: string;
+
+ /**
+ * 授权类型
+ */
+ grantTypeList?: string[];
+
+ /**
+ * 设备类型
+ */
+ deviceType?: string;
+
+ /**
+ * token活跃超时时间
+ */
+ activeTimeout?: number;
+
+ /**
+ * token固定超时
+ */
+ timeout?: number;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ status?: string;
+}
+
+export interface ClientQuery extends PageQuery {
+ /**
+ * 客户端id
+ */
+ clientId?: string | number;
+
+ /**
+ * 客户端key
+ */
+ clientKey?: string;
+
+ /**
+ * 客户端秘钥
+ */
+ clientSecret?: string;
+
+ /**
+ * 授权类型
+ */
+ grantType?: string;
+
+ /**
+ * 设备类型
+ */
+ deviceType?: string;
+
+ /**
+ * token活跃超时时间
+ */
+ activeTimeout?: number;
+
+ /**
+ * token固定超时
+ */
+ timeout?: number;
+
+ /**
+ * 状态(0正常 1停用)
+ */
+ status?: string;
+}
diff --git a/src/api/system/config/index.ts b/src/api/system/config/index.ts
new file mode 100644
index 0000000..1e4842d
--- /dev/null
+++ b/src/api/system/config/index.ts
@@ -0,0 +1,74 @@
+import request from '@/utils/request';
+import { ConfigForm, ConfigQuery, ConfigVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询参数列表
+export function listConfig(query: ConfigQuery): AxiosPromise {
+ return request({
+ url: '/system/config/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询参数详细
+export function getConfig(configId: string | number): AxiosPromise {
+ return request({
+ url: '/system/config/' + configId,
+ method: 'get'
+ });
+}
+
+// 根据参数键名查询参数值
+export function getConfigKey(configKey: string): AxiosPromise {
+ return request({
+ url: '/system/config/configKey/' + configKey,
+ method: 'get'
+ });
+}
+
+// 新增参数配置
+export function addConfig(data: ConfigForm) {
+ return request({
+ url: '/system/config',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改参数配置
+export function updateConfig(data: ConfigForm) {
+ return request({
+ url: '/system/config',
+ method: 'put',
+ data: data
+ });
+}
+
+// 修改参数配置
+export function updateConfigByKey(key: string, value: any) {
+ return request({
+ url: '/system/config/updateByKey',
+ method: 'put',
+ data: {
+ configKey: key,
+ configValue: value
+ }
+ });
+}
+
+// 删除参数配置
+export function delConfig(configId: string | number | Array) {
+ return request({
+ url: '/system/config/' + configId,
+ method: 'delete'
+ });
+}
+
+// 刷新参数缓存
+export function refreshCache() {
+ return request({
+ url: '/system/config/refreshCache',
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/config/types.ts b/src/api/system/config/types.ts
new file mode 100644
index 0000000..b68f073
--- /dev/null
+++ b/src/api/system/config/types.ts
@@ -0,0 +1,23 @@
+export interface ConfigVO extends BaseEntity {
+ configId: number | string;
+ configName: string;
+ configKey: string;
+ configValue: string;
+ configType: string;
+ remark: string;
+}
+
+export interface ConfigForm {
+ configId: number | string | undefined;
+ configName: string;
+ configKey: string;
+ configValue: string;
+ configType: string;
+ remark: string;
+}
+
+export interface ConfigQuery extends PageQuery {
+ configName: string;
+ configKey: string;
+ configType: string;
+}
diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts
new file mode 100644
index 0000000..7e097fd
--- /dev/null
+++ b/src/api/system/dept/index.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DeptForm, DeptQuery, DeptVO } from './types';
+
+// 查询部门列表
+export const listDept = (query?: DeptQuery) => {
+ return request({
+ url: '/system/dept/list',
+ method: 'get',
+ params: query
+ });
+};
+
+// 查询部门列表(排除节点)
+export const listDeptExcludeChild = (deptId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/dept/list/exclude/' + deptId,
+ method: 'get'
+ });
+};
+
+// 查询部门详细
+export const getDept = (deptId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/dept/' + deptId,
+ method: 'get'
+ });
+};
+
+// 查询部门下拉树结构
+export const treeselect = (): AxiosPromise => {
+ return request({
+ url: '/system/dept/treeselect',
+ method: 'get'
+ });
+};
+
+// 新增部门
+export const addDept = (data: DeptForm) => {
+ return request({
+ url: '/system/dept',
+ method: 'post',
+ data: data
+ });
+};
+
+// 修改部门
+export const updateDept = (data: DeptForm) => {
+ return request({
+ url: '/system/dept',
+ method: 'put',
+ data: data
+ });
+};
+
+// 删除部门
+export const delDept = (deptId: number | string) => {
+ return request({
+ url: '/system/dept/' + deptId,
+ method: 'delete'
+ });
+};
diff --git a/src/api/system/dept/types.ts b/src/api/system/dept/types.ts
new file mode 100644
index 0000000..494745c
--- /dev/null
+++ b/src/api/system/dept/types.ts
@@ -0,0 +1,48 @@
+/**
+ * 部门查询参数
+ */
+export interface DeptQuery extends PageQuery {
+ deptName?: string;
+ deptCategory?: string;
+ status?: number;
+}
+
+/**
+ * 部门类型
+ */
+export interface DeptVO extends BaseEntity {
+ id: number | string;
+ parentName: string;
+ parentId: number | string;
+ children: DeptVO[];
+ deptId: number | string;
+ deptName: string;
+ deptCategory: string;
+ orderNum: number;
+ leader: string;
+ phone: string;
+ email: string;
+ status: string;
+ delFlag: string;
+ ancestors: string;
+ menuId: string | number;
+}
+
+/**
+ * 部门表单类型
+ */
+export interface DeptForm {
+ parentName?: string;
+ parentId?: number | string;
+ children?: DeptForm[];
+ deptId?: number | string;
+ deptName?: string;
+ deptCategory?: string;
+ orderNum?: number;
+ leader?: string;
+ phone?: string;
+ email?: string;
+ status?: string;
+ delFlag?: string;
+ ancestors?: string;
+}
diff --git a/src/api/system/dict/data/index.ts b/src/api/system/dict/data/index.ts
new file mode 100644
index 0000000..7692abc
--- /dev/null
+++ b/src/api/system/dict/data/index.ts
@@ -0,0 +1,53 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DictDataForm, DictDataQuery, DictDataVO } from './types';
+// 根据字典类型查询字典数据信息
+export function getDicts(dictType: string): AxiosPromise {
+ return request({
+ url: '/system/dict/data/type/' + dictType,
+ method: 'get'
+ });
+}
+
+// 查询字典数据列表
+export function listData(query: DictDataQuery): AxiosPromise {
+ return request({
+ url: '/system/dict/data/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询字典数据详细
+export function getData(dictCode: string | number): AxiosPromise {
+ return request({
+ url: '/system/dict/data/' + dictCode,
+ method: 'get'
+ });
+}
+
+// 新增字典数据
+export function addData(data: DictDataForm) {
+ return request({
+ url: '/system/dict/data',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改字典数据
+export function updateData(data: DictDataForm) {
+ return request({
+ url: '/system/dict/data',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除字典数据
+export function delData(dictCode: string | number | Array) {
+ return request({
+ url: '/system/dict/data/' + dictCode,
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/dict/data/types.ts b/src/api/system/dict/data/types.ts
new file mode 100644
index 0000000..e4abb9b
--- /dev/null
+++ b/src/api/system/dict/data/types.ts
@@ -0,0 +1,26 @@
+export interface DictDataQuery extends PageQuery {
+ dictName: string;
+ dictType: string;
+ dictLabel: string;
+}
+
+export interface DictDataVO extends BaseEntity {
+ dictCode: string;
+ dictLabel: string;
+ dictValue: string;
+ cssClass: string;
+ listClass: ElTagType;
+ dictSort: number;
+ remark: string;
+}
+
+export interface DictDataForm {
+ dictType?: string;
+ dictCode: string | undefined;
+ dictLabel: string;
+ dictValue: string;
+ cssClass: string;
+ listClass: ElTagType;
+ dictSort: number;
+ remark: string;
+}
diff --git a/src/api/system/dict/type/index.ts b/src/api/system/dict/type/index.ts
new file mode 100644
index 0000000..7dc3d66
--- /dev/null
+++ b/src/api/system/dict/type/index.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { DictTypeForm, DictTypeVO, DictTypeQuery } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询字典类型列表
+export function listType(query: DictTypeQuery): AxiosPromise {
+ return request({
+ url: '/system/dict/type/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询字典类型详细
+export function getType(dictId: number | string): AxiosPromise {
+ return request({
+ url: '/system/dict/type/' + dictId,
+ method: 'get'
+ });
+}
+
+// 新增字典类型
+export function addType(data: DictTypeForm) {
+ return request({
+ url: '/system/dict/type',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改字典类型
+export function updateType(data: DictTypeForm) {
+ return request({
+ url: '/system/dict/type',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除字典类型
+export function delType(dictId: string | number | Array) {
+ return request({
+ url: '/system/dict/type/' + dictId,
+ method: 'delete'
+ });
+}
+
+// 刷新字典缓存
+export function refreshCache() {
+ return request({
+ url: '/system/dict/type/refreshCache',
+ method: 'delete'
+ });
+}
+
+// 获取字典选择框列表
+export function optionselect(): AxiosPromise {
+ return request({
+ url: '/system/dict/type/optionselect',
+ method: 'get'
+ });
+}
diff --git a/src/api/system/dict/type/types.ts b/src/api/system/dict/type/types.ts
new file mode 100644
index 0000000..4987dbf
--- /dev/null
+++ b/src/api/system/dict/type/types.ts
@@ -0,0 +1,18 @@
+export interface DictTypeVO extends BaseEntity {
+ dictId: number | string;
+ dictName: string;
+ dictType: string;
+ remark: string;
+}
+
+export interface DictTypeForm {
+ dictId: number | string | undefined;
+ dictName: string;
+ dictType: string;
+ remark: string;
+}
+
+export interface DictTypeQuery extends PageQuery {
+ dictName: string;
+ dictType: string;
+}
diff --git a/src/api/system/menu/index.ts b/src/api/system/menu/index.ts
new file mode 100644
index 0000000..7a0cf74
--- /dev/null
+++ b/src/api/system/menu/index.ts
@@ -0,0 +1,70 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from './types';
+
+// 查询菜单列表
+export const listMenu = (query?: MenuQuery): AxiosPromise => {
+ return request({
+ url: '/system/menu/list',
+ method: 'get',
+ params: query
+ });
+};
+
+// 查询菜单详细
+export const getMenu = (menuId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/menu/' + menuId,
+ method: 'get'
+ });
+};
+
+// 查询菜单下拉树结构
+export const treeselect = (): AxiosPromise => {
+ return request({
+ url: '/system/menu/treeselect',
+ method: 'get'
+ });
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const roleMenuTreeselect = (roleId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/menu/roleMenuTreeselect/' + roleId,
+ method: 'get'
+ });
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const tenantPackageMenuTreeselect = (packageId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/menu/tenantPackageMenuTreeselect/' + packageId,
+ method: 'get'
+ });
+};
+
+// 新增菜单
+export const addMenu = (data: MenuForm) => {
+ return request({
+ url: '/system/menu',
+ method: 'post',
+ data: data
+ });
+};
+
+// 修改菜单
+export const updateMenu = (data: MenuForm) => {
+ return request({
+ url: '/system/menu',
+ method: 'put',
+ data: data
+ });
+};
+
+// 删除菜单
+export const delMenu = (menuId: string | number) => {
+ return request({
+ url: '/system/menu/' + menuId,
+ method: 'delete'
+ });
+};
diff --git a/src/api/system/menu/types.ts b/src/api/system/menu/types.ts
new file mode 100644
index 0000000..ca19840
--- /dev/null
+++ b/src/api/system/menu/types.ts
@@ -0,0 +1,69 @@
+import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
+
+/**
+ * 菜单树形结构类型
+ */
+export interface MenuTreeOption {
+ id: string | number;
+ label: string;
+ parentId: string | number;
+ weight: number;
+ children?: MenuTreeOption[];
+}
+
+export interface RoleMenuTree {
+ menus: MenuTreeOption[];
+ checkedKeys: string[];
+}
+
+/**
+ * 菜单查询参数类型
+ */
+export interface MenuQuery {
+ keywords?: string;
+ menuName?: string;
+ status?: string;
+}
+
+/**
+ * 菜单视图对象类型
+ */
+export interface MenuVO extends BaseEntity {
+ parentName: string;
+ parentId: string | number;
+ children: MenuVO[];
+ menuId: string | number;
+ menuName: string;
+ orderNum: number;
+ path: string;
+ component: string;
+ queryParam: string;
+ isFrame: string;
+ isCache: string;
+ menuType: MenuTypeEnum;
+ visible: string;
+ status: string;
+ icon: string;
+ remark: string;
+}
+
+export interface MenuForm {
+ parentName?: string;
+ parentId?: string | number;
+ children?: MenuForm[];
+ menuId?: string | number;
+ menuName: string;
+ orderNum: number;
+ path: string;
+ component?: string;
+ queryParam?: string;
+ isFrame?: string;
+ isCache?: string;
+ menuType?: MenuTypeEnum;
+ visible?: string;
+ status?: string;
+ icon?: string;
+ remark?: string;
+ query?: string;
+ perms?: string;
+}
diff --git a/src/api/system/notice/index.ts b/src/api/system/notice/index.ts
new file mode 100644
index 0000000..285d1f4
--- /dev/null
+++ b/src/api/system/notice/index.ts
@@ -0,0 +1,45 @@
+import request from '@/utils/request';
+import { NoticeForm, NoticeQuery, NoticeVO } from './types';
+import { AxiosPromise } from 'axios';
+// 查询公告列表
+export function listNotice(query: NoticeQuery): AxiosPromise {
+ return request({
+ url: '/system/notice/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询公告详细
+export function getNotice(noticeId: string | number): AxiosPromise {
+ return request({
+ url: '/system/notice/' + noticeId,
+ method: 'get'
+ });
+}
+
+// 新增公告
+export function addNotice(data: NoticeForm) {
+ return request({
+ url: '/system/notice',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改公告
+export function updateNotice(data: NoticeForm) {
+ return request({
+ url: '/system/notice',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除公告
+export function delNotice(noticeId: string | number | Array) {
+ return request({
+ url: '/system/notice/' + noticeId,
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/notice/types.ts b/src/api/system/notice/types.ts
new file mode 100644
index 0000000..abfd5b2
--- /dev/null
+++ b/src/api/system/notice/types.ts
@@ -0,0 +1,26 @@
+export interface NoticeVO extends BaseEntity {
+ noticeId: number;
+ noticeTitle: string;
+ noticeType: string;
+ noticeContent: string;
+ status: string;
+ remark: string;
+ createByName: string;
+}
+
+export interface NoticeQuery extends PageQuery {
+ noticeTitle: string;
+ createByName: string;
+ status: string;
+ noticeType: string;
+}
+
+export interface NoticeForm {
+ noticeId: number | string | undefined;
+ noticeTitle: string;
+ noticeType: string;
+ noticeContent: string;
+ status: string;
+ remark: string;
+ createByName: string;
+}
diff --git a/src/api/system/oss/index.ts b/src/api/system/oss/index.ts
new file mode 100644
index 0000000..4472112
--- /dev/null
+++ b/src/api/system/oss/index.ts
@@ -0,0 +1,28 @@
+import request from '@/utils/request';
+import { OssQuery, OssVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询OSS对象存储列表
+export function listOss(query: OssQuery): AxiosPromise {
+ return request({
+ url: '/resource/oss/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询OSS对象基于id串
+export function listByIds(ossId: string | number): AxiosPromise {
+ return request({
+ url: '/resource/oss/listByIds/' + ossId,
+ method: 'get'
+ });
+}
+
+// 删除OSS对象存储
+export function delOss(ossId: string | number | Array) {
+ return request({
+ url: '/resource/oss/' + ossId,
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/oss/types.ts b/src/api/system/oss/types.ts
new file mode 100644
index 0000000..bc0bc1f
--- /dev/null
+++ b/src/api/system/oss/types.ts
@@ -0,0 +1,22 @@
+export interface OssVO extends BaseEntity {
+ ossId: string | number;
+ fileName: string;
+ originalName: string;
+ fileSuffix: string;
+ url: string;
+ createByName: string;
+ service: string;
+}
+
+export interface OssQuery extends PageQuery {
+ fileName: string;
+ originalName: string;
+ fileSuffix: string;
+ createTime: string;
+ service: string;
+ orderByColumn: string;
+ isAsc: string;
+}
+export interface OssForm {
+ file: undefined | string;
+}
diff --git a/src/api/system/ossConfig/index.ts b/src/api/system/ossConfig/index.ts
new file mode 100644
index 0000000..d0faefe
--- /dev/null
+++ b/src/api/system/ossConfig/index.ts
@@ -0,0 +1,60 @@
+import request from '@/utils/request';
+import { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询对象存储配置列表
+export function listOssConfig(query: OssConfigQuery): AxiosPromise {
+ return request({
+ url: '/resource/oss/config/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询对象存储配置详细
+export function getOssConfig(ossConfigId: string | number): AxiosPromise {
+ return request({
+ url: '/resource/oss/config/' + ossConfigId,
+ method: 'get'
+ });
+}
+
+// 新增对象存储配置
+export function addOssConfig(data: OssConfigForm) {
+ return request({
+ url: '/resource/oss/config',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改对象存储配置
+export function updateOssConfig(data: OssConfigForm) {
+ return request({
+ url: '/resource/oss/config',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除对象存储配置
+export function delOssConfig(ossConfigId: string | number | Array) {
+ return request({
+ url: '/resource/oss/config/' + ossConfigId,
+ method: 'delete'
+ });
+}
+
+// 对象存储状态修改
+export function changeOssConfigStatus(ossConfigId: string | number, status: string, configKey: string) {
+ const data = {
+ ossConfigId,
+ status,
+ configKey
+ };
+ return request({
+ url: '/resource/oss/config/changeStatus',
+ method: 'put',
+ data: data
+ });
+}
diff --git a/src/api/system/ossConfig/types.ts b/src/api/system/ossConfig/types.ts
new file mode 100644
index 0000000..d227bd0
--- /dev/null
+++ b/src/api/system/ossConfig/types.ts
@@ -0,0 +1,38 @@
+export interface OssConfigVO extends BaseEntity {
+ ossConfigId: number | string;
+ configKey: string;
+ accessKey: string;
+ secretKey: string;
+ bucketName: string;
+ prefix: string;
+ endpoint: string;
+ domain: string;
+ isHttps: string;
+ region: string;
+ status: string;
+ ext1: string;
+ remark: string;
+ accessPolicy: string;
+}
+
+export interface OssConfigQuery extends PageQuery {
+ configKey: string;
+ bucketName: string;
+ status: string;
+}
+
+export interface OssConfigForm {
+ ossConfigId: string | number | undefined;
+ configKey: string;
+ accessKey: string;
+ secretKey: string;
+ bucketName: string;
+ prefix: string;
+ endpoint: string;
+ domain: string;
+ isHttps: string;
+ accessPolicy: string;
+ region: string;
+ status: string;
+ remark: string;
+}
diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts
new file mode 100644
index 0000000..5f6ab18
--- /dev/null
+++ b/src/api/system/post/index.ts
@@ -0,0 +1,58 @@
+import request from '@/utils/request';
+import { PostForm, PostQuery, PostVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询岗位列表
+export function listPost(query: PostQuery): AxiosPromise {
+ return request({
+ url: '/system/post/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询岗位详细
+export function getPost(postId: string | number): AxiosPromise {
+ return request({
+ url: '/system/post/' + postId,
+ method: 'get'
+ });
+}
+
+// 获取岗位选择框列表
+export function optionselect(deptId?: number | string, postIds?: (number | string)[]): AxiosPromise {
+ return request({
+ url: '/system/post/optionselect',
+ method: 'get',
+ params: {
+ postIds: postIds,
+ deptId: deptId
+ }
+ });
+}
+
+// 新增岗位
+export function addPost(data: PostForm) {
+ return request({
+ url: '/system/post',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改岗位
+export function updatePost(data: PostForm) {
+ return request({
+ url: '/system/post',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除岗位
+export function delPost(postId: string | number | (string | number)[]) {
+ return request({
+ url: '/system/post/' + postId,
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/post/types.ts b/src/api/system/post/types.ts
new file mode 100644
index 0000000..45a0540
--- /dev/null
+++ b/src/api/system/post/types.ts
@@ -0,0 +1,31 @@
+export interface PostVO extends BaseEntity {
+ postId: number | string;
+ deptId: number | string;
+ postCode: string;
+ postName: string;
+ postCategory: string;
+ deptName: string;
+ postSort: number;
+ status: string;
+ remark: string;
+}
+
+export interface PostForm {
+ postId: number | string | undefined;
+ deptId: number | string | undefined;
+ postCode: string;
+ postName: string;
+ postCategory: string;
+ postSort: number;
+ status: string;
+ remark: string;
+}
+
+export interface PostQuery extends PageQuery {
+ deptId: number | string;
+ belongDeptId: number | string;
+ postCode: string;
+ postName: string;
+ postCategory: string;
+ status: string;
+}
diff --git a/src/api/system/role/index.ts b/src/api/system/role/index.ts
new file mode 100644
index 0000000..fb0fcab
--- /dev/null
+++ b/src/api/system/role/index.ts
@@ -0,0 +1,160 @@
+import { UserVO } from '@/api/system/user/types';
+import { UserQuery } from '@/api/system/user/types';
+import { AxiosPromise } from 'axios';
+import { RoleQuery, RoleVO, RoleDeptTree } from './types';
+import request from '@/utils/request';
+
+export const listRole = (query: RoleQuery): AxiosPromise => {
+ return request({
+ url: '/system/role/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 通过roleIds查询角色
+ * @param roleIds
+ */
+export const optionSelect = (roleIds: (number | string)[]): AxiosPromise => {
+ return request({
+ url: '/system/role/optionselect?roleIds=' + roleIds,
+ method: 'get'
+ });
+};
+
+/**
+ * 查询角色详细
+ */
+export const getRole = (roleId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/role/' + roleId,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增角色
+ */
+export const addRole = (data: any) => {
+ return request({
+ url: '/system/role',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改角色
+ * @param data
+ */
+export const updateRole = (data: any) => {
+ return request({
+ url: '/system/role',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 角色数据权限
+ */
+export const dataScope = (data: any) => {
+ return request({
+ url: '/system/role/dataScope',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 角色状态修改
+ */
+export const changeRoleStatus = (roleId: string | number, status: string) => {
+ const data = {
+ roleId,
+ status
+ };
+ return request({
+ url: '/system/role/changeStatus',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除角色
+ */
+export const delRole = (roleId: Array | string | number) => {
+ return request({
+ url: '/system/role/' + roleId,
+ method: 'delete'
+ });
+};
+
+/**
+ * 查询角色已授权用户列表
+ */
+export const allocatedUserList = (query: UserQuery): AxiosPromise => {
+ return request({
+ url: '/system/role/authUser/allocatedList',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询角色未授权用户列表
+ */
+export const unallocatedUserList = (query: UserQuery): AxiosPromise => {
+ return request({
+ url: '/system/role/authUser/unallocatedList',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 取消用户授权角色
+ */
+export const authUserCancel = (data: any) => {
+ return request({
+ url: '/system/role/authUser/cancel',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 批量取消用户授权角色
+ */
+export const authUserCancelAll = (data: any) => {
+ return request({
+ url: '/system/role/authUser/cancelAll',
+ method: 'put',
+ params: data
+ });
+};
+
+/**
+ * 授权用户选择
+ */
+export const authUserSelectAll = (data: any) => {
+ return request({
+ url: '/system/role/authUser/selectAll',
+ method: 'put',
+ params: data
+ });
+};
+// 根据角色ID查询部门树结构
+export const deptTreeSelect = (roleId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/role/deptTree/' + roleId,
+ method: 'get'
+ });
+};
+
+export default {
+ optionSelect,
+ listRole
+};
diff --git a/src/api/system/role/types.ts b/src/api/system/role/types.ts
new file mode 100644
index 0000000..7dbb6ff
--- /dev/null
+++ b/src/api/system/role/types.ts
@@ -0,0 +1,52 @@
+/**
+ * 菜单树形结构类型
+ */
+export interface DeptTreeOption {
+ id: string;
+ label: string;
+ parentId: string;
+ weight: number;
+ children?: DeptTreeOption[];
+}
+
+export interface RoleDeptTree {
+ checkedKeys: string[];
+ depts: DeptTreeOption[];
+}
+
+export interface RoleVO extends BaseEntity {
+ roleId: string | number;
+ roleName: string;
+ roleKey: string;
+ roleSort: number;
+ dataScope: string;
+ menuCheckStrictly: boolean;
+ deptCheckStrictly: boolean;
+ status: string;
+ delFlag: string;
+ remark?: any;
+ flag: boolean;
+ menuIds?: Array;
+ deptIds?: Array;
+ admin: boolean;
+}
+
+export interface RoleQuery extends PageQuery {
+ roleName: string;
+ roleKey: string;
+ status: string;
+}
+
+export interface RoleForm {
+ roleName: string;
+ roleKey: string;
+ roleSort: number;
+ status: string;
+ menuCheckStrictly: boolean;
+ deptCheckStrictly: boolean;
+ remark: string;
+ dataScope?: string;
+ roleId: string | undefined;
+ menuIds: Array;
+ deptIds: Array;
+}
diff --git a/src/api/system/social/auth.ts b/src/api/system/social/auth.ts
new file mode 100644
index 0000000..69f0d7e
--- /dev/null
+++ b/src/api/system/social/auth.ts
@@ -0,0 +1,28 @@
+import request from '@/utils/request';
+
+// 绑定账号
+export function authBinding(source: string, tenantId: string) {
+ return request({
+ url: '/auth/binding/' + source,
+ method: 'get',
+ params: {
+ tenantId: tenantId,
+ domain: window.location.host
+ }
+ });
+}
+
+// 解绑账号
+export function authUnlock(authId: string) {
+ return request({
+ url: '/auth/unlock/' + authId,
+ method: 'delete'
+ });
+}
+//获取授权列表
+export function getAuthList() {
+ return request({
+ url: '/system/social/list',
+ method: 'get'
+ });
+}
diff --git a/src/api/system/tenant/index.ts b/src/api/system/tenant/index.ts
new file mode 100644
index 0000000..7b7b93f
--- /dev/null
+++ b/src/api/system/tenant/index.ts
@@ -0,0 +1,101 @@
+import request from '@/utils/request';
+import { TenantForm, TenantQuery, TenantVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询租户列表
+export function listTenant(query: TenantQuery): AxiosPromise {
+ return request({
+ url: '/system/tenant/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询租户详细
+export function getTenant(id: string | number): AxiosPromise {
+ return request({
+ url: '/system/tenant/' + id,
+ method: 'get'
+ });
+}
+
+// 新增租户
+export function addTenant(data: TenantForm) {
+ return request({
+ url: '/system/tenant',
+ method: 'post',
+ headers: {
+ isEncrypt: true,
+ repeatSubmit: false
+ },
+ data: data
+ });
+}
+
+// 修改租户
+export function updateTenant(data: TenantForm) {
+ return request({
+ url: '/system/tenant',
+ method: 'put',
+ data: data
+ });
+}
+
+// 租户状态修改
+export function changeTenantStatus(id: string | number, tenantId: string | number, status: string) {
+ const data = {
+ id,
+ tenantId,
+ status
+ };
+ return request({
+ url: '/system/tenant/changeStatus',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除租户
+export function delTenant(id: string | number | Array) {
+ return request({
+ url: '/system/tenant/' + id,
+ method: 'delete'
+ });
+}
+
+// 动态切换租户
+export function dynamicTenant(tenantId: string | number) {
+ return request({
+ url: '/system/tenant/dynamic/' + tenantId,
+ method: 'get'
+ });
+}
+
+// 清除动态租户
+export function dynamicClear() {
+ return request({
+ url: '/system/tenant/dynamic/clear',
+ method: 'get'
+ });
+}
+
+// 同步租户套餐
+export function syncTenantPackage(tenantId: string | number, packageId: string | number) {
+ const data = {
+ tenantId,
+ packageId
+ };
+ return request({
+ url: '/system/tenant/syncTenantPackage',
+ method: 'get',
+ params: data
+ });
+}
+
+// 同步租户字典
+export function syncTenantDict() {
+ return request({
+ url: '/system/tenant/syncTenantDict',
+ method: 'get',
+ });
+}
diff --git a/src/api/system/tenant/types.ts b/src/api/system/tenant/types.ts
new file mode 100644
index 0000000..25395fa
--- /dev/null
+++ b/src/api/system/tenant/types.ts
@@ -0,0 +1,46 @@
+export interface TenantVO extends BaseEntity {
+ id: number | string;
+ tenantId: number | string;
+ username: string;
+ contactUserName: string;
+ contactPhone: string;
+ companyName: string;
+ licenseNumber: string;
+ address: string;
+ domain: string;
+ intro: string;
+ remark: string;
+ packageId: string | number;
+ expireTime: string;
+ accountCount: number;
+ status: string;
+}
+
+export interface TenantQuery extends PageQuery {
+ tenantId: string | number;
+
+ contactUserName: string;
+
+ contactPhone: string;
+
+ companyName: string;
+}
+
+export interface TenantForm {
+ id: number | string | undefined;
+ tenantId: number | string | undefined;
+ username: string;
+ password: string;
+ contactUserName: string;
+ contactPhone: string;
+ companyName: string;
+ licenseNumber: string;
+ domain: string;
+ address: string;
+ intro: string;
+ remark: string;
+ packageId: string | number;
+ expireTime: string;
+ accountCount: number;
+ status: string;
+}
diff --git a/src/api/system/tenantPackage/index.ts b/src/api/system/tenantPackage/index.ts
new file mode 100644
index 0000000..70d0dab
--- /dev/null
+++ b/src/api/system/tenantPackage/index.ts
@@ -0,0 +1,67 @@
+import request from '@/utils/request';
+import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询租户套餐列表
+export function listTenantPackage(query?: TenantPkgQuery): AxiosPromise {
+ return request({
+ url: '/system/tenant/package/list',
+ method: 'get',
+ params: query
+ });
+}
+
+// 查询租户套餐下拉选列表
+export function selectTenantPackage(): AxiosPromise {
+ return request({
+ url: '/system/tenant/package/selectList',
+ method: 'get'
+ });
+}
+
+// 查询租户套餐详细
+export function getTenantPackage(packageId: string | number): AxiosPromise {
+ return request({
+ url: '/system/tenant/package/' + packageId,
+ method: 'get'
+ });
+}
+
+// 新增租户套餐
+export function addTenantPackage(data: TenantPkgForm) {
+ return request({
+ url: '/system/tenant/package',
+ method: 'post',
+ data: data
+ });
+}
+
+// 修改租户套餐
+export function updateTenantPackage(data: TenantPkgForm) {
+ return request({
+ url: '/system/tenant/package',
+ method: 'put',
+ data: data
+ });
+}
+
+// 租户套餐状态修改
+export function changePackageStatus(packageId: number | string, status: string) {
+ const data = {
+ packageId,
+ status
+ };
+ return request({
+ url: '/system/tenant/package/changeStatus',
+ method: 'put',
+ data: data
+ });
+}
+
+// 删除租户套餐
+export function delTenantPackage(packageId: string | number | Array) {
+ return request({
+ url: '/system/tenant/package/' + packageId,
+ method: 'delete'
+ });
+}
diff --git a/src/api/system/tenantPackage/types.ts b/src/api/system/tenantPackage/types.ts
new file mode 100644
index 0000000..c24b8fc
--- /dev/null
+++ b/src/api/system/tenantPackage/types.ts
@@ -0,0 +1,20 @@
+export interface TenantPkgVO extends BaseEntity {
+ packageId: string | number;
+ packageName: string;
+ menuIds: string;
+ remark: string;
+ menuCheckStrictly: boolean;
+ status: string;
+}
+
+export interface TenantPkgQuery extends PageQuery {
+ packageName: string;
+}
+
+export interface TenantPkgForm {
+ packageId: string | number | undefined;
+ packageName: string;
+ menuIds: string;
+ remark: string;
+ menuCheckStrictly: boolean;
+}
diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts
new file mode 100644
index 0000000..25c7884
--- /dev/null
+++ b/src/api/system/user/index.ts
@@ -0,0 +1,229 @@
+import { DeptVO } from './../dept/types';
+import { RoleVO } from '@/api/system/role/types';
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { UserForm, UserQuery, UserVO, UserInfoVO } from './types';
+import { parseStrEmpty } from '@/utils/ruoyi';
+
+/**
+ * 查询用户列表
+ * @param query
+ */
+export const listUser = (query: UserQuery): AxiosPromise => {
+ return request({
+ url: '/system/user/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 通过用户ids查询用户
+ * @param userIds
+ */
+export const optionSelect = (userIds: (number | string)[]): AxiosPromise => {
+ return request({
+ url: '/system/user/optionselect?userIds=' + userIds,
+ method: 'get'
+ });
+};
+
+/**
+ * 获取用户详情
+ * @param userId
+ */
+export const getUser = (userId?: string | number): AxiosPromise => {
+ return request({
+ url: '/system/user/' + parseStrEmpty(userId),
+ method: 'get'
+ });
+};
+
+/**
+ * 新增用户
+ */
+export const addUser = (data: UserForm) => {
+ return request({
+ url: '/system/user',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改用户
+ */
+export const updateUser = (data: UserForm) => {
+ return request({
+ url: '/system/user',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除用户
+ * @param userId 用户ID
+ */
+export const delUser = (userId: Array | string | number) => {
+ return request({
+ url: '/system/user/' + userId,
+ method: 'delete'
+ });
+};
+
+/**
+ * 用户密码重置
+ * @param userId 用户ID
+ * @param password 密码
+ */
+export const resetUserPwd = (userId: string | number, password: string) => {
+ const data = {
+ userId,
+ password
+ };
+ return request({
+ url: '/system/user/resetPwd',
+ method: 'put',
+ headers: {
+ isEncrypt: true,
+ repeatSubmit: false
+ },
+ data: data
+ });
+};
+
+/**
+ * 用户状态修改
+ * @param userId 用户ID
+ * @param status 用户状态
+ */
+export const changeUserStatus = (userId: number | string, status: string) => {
+ const data = {
+ userId,
+ status
+ };
+ return request({
+ url: '/system/user/changeStatus',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 查询用户个人信息
+ */
+export const getUserProfile = (): AxiosPromise => {
+ return request({
+ url: '/system/user/profile',
+ method: 'get'
+ });
+};
+
+/**
+ * 修改用户个人信息
+ * @param data 用户信息
+ */
+export const updateUserProfile = (data: UserForm) => {
+ return request({
+ url: '/system/user/profile',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 用户密码重置
+ * @param oldPassword 旧密码
+ * @param newPassword 新密码
+ */
+export const updateUserPwd = (oldPassword: string, newPassword: string) => {
+ const data = {
+ oldPassword,
+ newPassword
+ };
+ return request({
+ url: '/system/user/profile/updatePwd',
+ method: 'put',
+ headers: {
+ isEncrypt: true,
+ repeatSubmit: false
+ },
+ data: data
+ });
+};
+
+/**
+ * 用户头像上传
+ * @param data 头像文件
+ */
+export const uploadAvatar = (data: FormData) => {
+ return request({
+ url: '/system/user/profile/avatar',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 查询授权角色
+ * @param userId 用户ID
+ */
+export const getAuthRole = (userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> => {
+ return request({
+ url: '/system/user/authRole/' + userId,
+ method: 'get'
+ });
+};
+
+/**
+ * 保存授权角色
+ * @param data 用户ID
+ */
+export const updateAuthRole = (data: { userId: string; roleIds: string }) => {
+ return request({
+ url: '/system/user/authRole',
+ method: 'put',
+ params: data
+ });
+};
+
+/**
+ * 查询当前部门的所有用户信息
+ * @param deptId
+ */
+export const listUserByDeptId = (deptId: string | number): AxiosPromise => {
+ return request({
+ url: '/system/user/list/dept/' + deptId,
+ method: 'get'
+ });
+};
+
+/**
+ * 查询部门下拉树结构
+ */
+export const deptTreeSelect = (): AxiosPromise => {
+ return request({
+ url: '/system/user/deptTree',
+ method: 'get'
+ });
+};
+
+export default {
+ listUser,
+ getUser,
+ optionSelect,
+ addUser,
+ updateUser,
+ delUser,
+ resetUserPwd,
+ changeUserStatus,
+ getUserProfile,
+ updateUserProfile,
+ updateUserPwd,
+ uploadAvatar,
+ getAuthRole,
+ updateAuthRole,
+ deptTreeSelect,
+ listUserByDeptId
+};
diff --git a/src/api/system/user/types.ts b/src/api/system/user/types.ts
new file mode 100644
index 0000000..0787372
--- /dev/null
+++ b/src/api/system/user/types.ts
@@ -0,0 +1,84 @@
+import { RoleVO } from '@/api/system/role/types';
+import { PostVO } from '@/api/system/post/types';
+
+/**
+ * 用户信息
+ */
+export interface UserInfo {
+ user: UserVO;
+ roles: string[];
+ permissions: string[];
+}
+
+/**
+ * 用户查询对象类型
+ */
+export interface UserQuery extends PageQuery {
+ userName?: string;
+ phonenumber?: string;
+ status?: string;
+ deptId?: string | number;
+ roleId?: string | number;
+}
+
+/**
+ * 用户返回对象
+ */
+export interface UserVO extends BaseEntity {
+ userId: string | number;
+ tenantId: string;
+ deptId: number;
+ userName: string;
+ nickName: string;
+ userType: string;
+ email: string;
+ phonenumber: string;
+ sex: string;
+ avatar: string;
+ status: string;
+ delFlag: string;
+ loginIp: string;
+ loginDate: string;
+ remark: string;
+ deptName: string;
+ roles: RoleVO[];
+ roleIds: any;
+ postIds: any;
+ roleId: any;
+ admin: boolean;
+}
+
+/**
+ * 用户表单类型
+ */
+export interface UserForm {
+ id?: string;
+ userId?: string;
+ deptId?: number;
+ userName: string;
+ nickName?: string;
+ password: string;
+ phonenumber?: string;
+ email?: string;
+ sex?: string;
+ status: string;
+ remark?: string;
+ postIds: string[];
+ roleIds: string[];
+}
+
+export interface UserInfoVO {
+ user: UserVO;
+ roles: RoleVO[];
+ roleIds: string[];
+ posts: PostVO[];
+ postIds: string[];
+ roleGroup: string;
+ postGroup: string;
+}
+
+export interface ResetPwdForm {
+ oldPassword: string;
+ newPassword: string;
+ confirmPassword: string;
+}
diff --git a/src/api/tool/gen/index.ts b/src/api/tool/gen/index.ts
new file mode 100644
index 0000000..efe079c
--- /dev/null
+++ b/src/api/tool/gen/index.ts
@@ -0,0 +1,86 @@
+import request from '@/utils/request';
+import { DbTableQuery, DbTableVO, TableQuery, TableVO, GenTableVO, DbTableForm } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询生成表数据
+export const listTable = (query: TableQuery): AxiosPromise => {
+ return request({
+ url: '/tool/gen/list',
+ method: 'get',
+ params: query
+ });
+};
+// 查询db数据库列表
+export const listDbTable = (query: DbTableQuery): AxiosPromise => {
+ return request({
+ url: '/tool/gen/db/list',
+ method: 'get',
+ params: query
+ });
+};
+
+// 查询表详细信息
+export const getGenTable = (tableId: string | number): AxiosPromise => {
+ return request({
+ url: '/tool/gen/' + tableId,
+ method: 'get'
+ });
+};
+
+// 修改代码生成信息
+export const updateGenTable = (data: DbTableForm): AxiosPromise => {
+ return request({
+ url: '/tool/gen',
+ method: 'put',
+ data: data
+ });
+};
+
+// 导入表
+export const importTable = (data: { tables: string; dataName: string }): AxiosPromise => {
+ return request({
+ url: '/tool/gen/importTable',
+ method: 'post',
+ params: data
+ });
+};
+
+// 预览生成代码
+export const previewTable = (tableId: string | number) => {
+ return request({
+ url: '/tool/gen/preview/' + tableId,
+ method: 'get'
+ });
+};
+
+// 删除表数据
+export const delTable = (tableId: string | number | Array) => {
+ return request({
+ url: '/tool/gen/' + tableId,
+ method: 'delete'
+ });
+};
+
+// 生成代码(自定义路径)
+export const genCode = (tableId: string | number) => {
+ return request({
+ url: '/tool/gen/genCode/' + tableId,
+ method: 'get'
+ });
+};
+
+// 同步数据库
+export const synchDb = (tableId: string | number) => {
+ return request({
+ url: '/tool/gen/synchDb/' + tableId,
+ method: 'get'
+ });
+};
+
+// 获取数据源名称
+export const getDataNames = () => {
+ return request({
+ url: '/tool/gen/getDataNames',
+ method: 'get'
+ });
+};
diff --git a/src/api/tool/gen/types.ts b/src/api/tool/gen/types.ts
new file mode 100644
index 0000000..7f7b62f
--- /dev/null
+++ b/src/api/tool/gen/types.ts
@@ -0,0 +1,180 @@
+export interface TableVO extends BaseEntity {
+ createDept: number | string;
+ tableId: string | number;
+ dataName: string;
+ tableName: string;
+ tableComment: string;
+ subTableName?: any;
+ subTableFkName?: any;
+ className: string;
+ tplCategory: string;
+ packageName: string;
+ moduleName: string;
+ businessName: string;
+ functionName: string;
+ functionAuthor: string;
+ genType: string;
+ genPath: string;
+ pkColumn?: any;
+ columns?: any;
+ options?: any;
+ remark?: any;
+ treeCode?: any;
+ treeParentCode?: any;
+ treeName?: any;
+ menuIds?: any;
+ parentMenuId?: any;
+ parentMenuName?: any;
+ tree: boolean;
+ crud: boolean;
+}
+
+export interface TableQuery extends PageQuery {
+ tableName: string;
+ tableComment: string;
+ dataName: string;
+}
+
+export interface DbColumnVO extends BaseEntity {
+ createDept?: any;
+ columnId?: any;
+ tableId?: any;
+ columnName?: any;
+ columnComment?: any;
+ columnType?: any;
+ javaType?: any;
+ javaField?: any;
+ isPk?: any;
+ isIncrement?: any;
+ isRequired?: any;
+ isInsert?: any;
+ isEdit?: any;
+ isList?: any;
+ isQuery?: any;
+ queryType?: any;
+ htmlType?: any;
+ dictType?: any;
+ sort?: any;
+ increment: boolean;
+ capJavaField?: any;
+ usableColumn: boolean;
+ superColumn: boolean;
+ list: boolean;
+ pk: boolean;
+ insert: boolean;
+ edit: boolean;
+ query: boolean;
+ required: boolean;
+}
+
+export interface DbTableVO {
+ createDept?: any;
+ tableId?: any;
+ tableName: string;
+ tableComment: string;
+ subTableName?: any;
+ subTableFkName?: any;
+ className?: any;
+ tplCategory?: any;
+ packageName?: any;
+ moduleName?: any;
+ businessName?: any;
+ functionName?: any;
+ functionAuthor?: any;
+ genType?: any;
+ genPath?: any;
+ pkColumn?: any;
+ columns: DbColumnVO[];
+ options?: any;
+ remark?: any;
+ treeCode?: any;
+ treeParentCode?: any;
+ treeName?: any;
+ menuIds?: any;
+ parentMenuId?: any;
+ parentMenuName?: any;
+ tree: boolean;
+ crud: boolean;
+}
+
+export interface DbTableQuery extends PageQuery {
+ dataName: string;
+ tableName: string;
+ tableComment: string;
+}
+
+export interface GenTableVO {
+ info: DbTableVO;
+ rows: DbColumnVO[];
+ tables: DbTableVO[];
+}
+
+export interface DbColumnForm extends BaseEntity {
+ createDept: number;
+ columnId: string;
+ tableId: string;
+ columnName: string;
+ columnComment: string;
+ columnType: string;
+ javaType: string;
+ javaField: string;
+ isPk: string;
+ isIncrement: string;
+ isRequired: string;
+ isInsert?: any;
+ isEdit: string;
+ isList: string;
+ isQuery?: any;
+ queryType: string;
+ htmlType: string;
+ dictType: string;
+ sort: number;
+ increment: boolean;
+ capJavaField: string;
+ usableColumn: boolean;
+ superColumn: boolean;
+ list: boolean;
+ pk: boolean;
+ insert: boolean;
+ edit: boolean;
+ query: boolean;
+ required: boolean;
+}
+
+export interface DbParamForm {
+ treeCode?: any;
+ treeName?: any;
+ treeParentCode?: any;
+ parentMenuId: string;
+}
+
+export interface DbTableForm extends BaseEntity {
+ createDept?: any;
+ tableId: string | string;
+ tableName: string;
+ tableComment: string;
+ subTableName?: any;
+ subTableFkName?: any;
+ className: string;
+ tplCategory: string;
+ packageName: string;
+ moduleName: string;
+ businessName: string;
+ functionName: string;
+ functionAuthor: string;
+ genType: string;
+ genPath: string;
+ pkColumn?: any;
+ columns: DbColumnForm[];
+ options: string;
+ remark?: any;
+ treeCode?: any;
+ treeParentCode?: any;
+ treeName?: any;
+ menuIds?: any;
+ parentMenuId: string;
+ parentMenuName?: any;
+ tree: boolean;
+ crud: boolean;
+ params: DbParamForm;
+}
diff --git a/src/api/types.ts b/src/api/types.ts
new file mode 100644
index 0000000..617286c
--- /dev/null
+++ b/src/api/types.ts
@@ -0,0 +1,59 @@
+/**
+ * 注册
+ */
+export type RegisterForm = {
+ tenantId: string;
+ username: string;
+ password: string;
+ confirmPassword?: string;
+ code?: string;
+ uuid?: string;
+ userType?: string;
+};
+
+/**
+ * 登录请求
+ */
+export interface LoginData {
+ tenantId?: string;
+ username?: string;
+ password?: string;
+ rememberMe?: boolean;
+ socialCode?: string;
+ socialState?: string;
+ source?: string;
+ code?: string;
+ uuid?: string;
+ clientId: string;
+ grantType: string;
+}
+
+/**
+ * 登录响应
+ */
+export interface LoginResult {
+ access_token: string;
+}
+
+/**
+ * 验证码返回
+ */
+export interface VerifyCodeResult {
+ captchaEnabled: boolean;
+ uuid?: string;
+ img?: string;
+}
+
+/**
+ * 租户
+ */
+export interface TenantVO {
+ companyName: string;
+ domain: any;
+ tenantId: string;
+}
+
+export interface TenantInfo {
+ tenantEnabled: boolean;
+ voList: TenantVO[];
+}
diff --git a/src/api/workflow/category/index.ts b/src/api/workflow/category/index.ts
new file mode 100644
index 0000000..e9723b0
--- /dev/null
+++ b/src/api/workflow/category/index.ts
@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/workflow/category/types';
+
+/**
+ * 查询流程分类列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listCategory = (query?: CategoryQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/category/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询流程分类详细
+ * @param id
+ */
+export const getCategory = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/workflow/category/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增流程分类
+ * @param data
+ */
+export const addCategory = (data: CategoryForm) => {
+ return request({
+ url: '/workflow/category',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改流程分类
+ * @param data
+ */
+export const updateCategory = (data: CategoryForm) => {
+ return request({
+ url: '/workflow/category',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除流程分类
+ * @param id
+ */
+export const delCategory = (id: string | number | Array) => {
+ return request({
+ url: '/workflow/category/' + id,
+ method: 'delete'
+ });
+};
diff --git a/src/api/workflow/category/types.ts b/src/api/workflow/category/types.ts
new file mode 100644
index 0000000..414fa55
--- /dev/null
+++ b/src/api/workflow/category/types.ts
@@ -0,0 +1,67 @@
+export interface CategoryVO {
+ /**
+ * 主键
+ */
+ id: string;
+
+ /**
+ * 分类名称
+ */
+ categoryName: string;
+
+ /**
+ * 分类编码
+ */
+ categoryCode: string;
+
+ /**
+ * 父级id
+ */
+ parentId: string | number;
+
+ /**
+ * 排序
+ */
+ sortNum: number;
+
+ children?: CategoryVO[];
+}
+
+export interface CategoryForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: string | number;
+
+ /**
+ * 分类名称
+ */
+ categoryName?: string;
+
+ /**
+ * 分类编码
+ */
+ categoryCode?: string;
+
+ /**
+ * 父级id
+ */
+ parentId?: string | number;
+
+ /**
+ * 排序
+ */
+ sortNum?: number;
+}
+
+export interface CategoryQuery extends PageQuery {
+ /**
+ * 分类名称
+ */
+ categoryName?: string;
+
+ /**
+ * 分类编码
+ */
+ categoryCode?: string;
+}
diff --git a/src/api/workflow/definitionConfig/index.ts b/src/api/workflow/definitionConfig/index.ts
new file mode 100644
index 0000000..d34bf05
--- /dev/null
+++ b/src/api/workflow/definitionConfig/index.ts
@@ -0,0 +1,49 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DefinitionConfigVO, DefinitionConfigForm } from '@/api/workflow/definitionConfig/types';
+
+/**
+ * 查询表单配置详细
+ * @param definitionId
+ */
+export const getByDefId = (definitionId: string | number): AxiosPromise => {
+ return request({
+ url: '/workflow/definitionConfig/getByDefId/' + definitionId,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增表单配置
+ * @param data
+ */
+export const saveOrUpdate = (data: DefinitionConfigForm) => {
+ return request({
+ url: '/workflow/definitionConfig/saveOrUpdate',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 删除表单配置
+ * @param id
+ */
+export const deldefinitionConfig = (id: string | number | Array) => {
+ return request({
+ url: '/workflow/definitionConfig/' + id,
+ method: 'delete'
+ });
+};
+
+/**
+ * 查询流程定义配置排除当前查询的流程定义
+ * @param tableName
+ * @param definitionId
+ */
+export const getByTableNameNotDefId = (tableName: string, definitionId: string | number) => {
+ return request({
+ url: `/workflow/definitionConfig/getByTableNameNotDefId/${tableName}/${definitionId}`,
+ method: 'get'
+ });
+};
diff --git a/src/api/workflow/definitionConfig/types.ts b/src/api/workflow/definitionConfig/types.ts
new file mode 100644
index 0000000..7627403
--- /dev/null
+++ b/src/api/workflow/definitionConfig/types.ts
@@ -0,0 +1,102 @@
+import { FormManageVO } from '@/api/workflow/formManage/types';
+
+export interface DefinitionConfigVO {
+ /**
+ * 主键
+ */
+ id: string | number;
+
+ /**
+ * 表名
+ */
+ tableName?: string;
+
+ /**
+ * 流程定义ID
+ */
+ definitionId: string | number;
+
+ /**
+ * 流程KEY
+ */
+ processKey: string;
+
+ /**
+ * 流程版本
+ */
+ version?: string | number;
+
+ /**
+ * 备注
+ */
+ remark: string;
+
+ /**
+ * 表单管理
+ */
+ wfFormManageVo: FormManageVO;
+}
+
+export interface DefinitionConfigForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: string | number;
+
+ /**
+ * 表名
+ */
+ tableName?: string;
+
+ /**
+ * 流程定义ID
+ */
+ definitionId?: string | number;
+
+ /**
+ * 流程KEY
+ */
+ processKey?: string;
+
+ /**
+ * 流程版本
+ */
+ version?: string | number;
+
+ /**
+ * 备注
+ */
+ remark?: string;
+
+ /**
+ * 表单管理
+ */
+ wfFormManageVo?: FormManageVO;
+}
+
+export interface DefinitionConfigQuery extends PageQuery {
+ /**
+ * 表名
+ */
+ tableName?: string;
+
+ /**
+ * 流程定义ID
+ */
+ definitionId?: string | number;
+
+ /**
+ * 流程KEY
+ */
+ processKey?: string;
+
+ /**
+ * 流程版本
+ */
+ version?: string | number;
+
+ /**
+ * 表单管理
+ */
+ wfFormManageVo: FormManageVO;
+}
diff --git a/src/api/workflow/formManage/index.ts b/src/api/workflow/formManage/index.ts
new file mode 100644
index 0000000..6c5ec60
--- /dev/null
+++ b/src/api/workflow/formManage/index.ts
@@ -0,0 +1,76 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { FormManageVO, FormManageForm, FormManageQuery } from '@/api/workflow/formManage/types';
+
+/**
+ * 查询表单管理列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listFormManage = (query?: FormManageQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/formManage/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询表单管理列表
+ * @param query
+ * @returns {*}
+ */
+
+export const selectListFormManage = (): AxiosPromise => {
+ return request({
+ url: '/workflow/formManage/list/selectList',
+ method: 'get'
+ });
+};
+
+/**
+ * 查询表单管理详细
+ * @param id
+ */
+export const getFormManage = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/workflow/formManage/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增表单管理
+ * @param data
+ */
+export const addFormManage = (data: FormManageForm) => {
+ return request({
+ url: '/workflow/formManage',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改表单管理
+ * @param data
+ */
+export const updateFormManage = (data: FormManageForm) => {
+ return request({
+ url: '/workflow/formManage',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除表单管理
+ * @param id
+ */
+export const delFormManage = (id: string | number | Array) => {
+ return request({
+ url: '/workflow/formManage/' + id,
+ method: 'delete'
+ });
+};
diff --git a/src/api/workflow/formManage/types.ts b/src/api/workflow/formManage/types.ts
new file mode 100644
index 0000000..b9dc1d8
--- /dev/null
+++ b/src/api/workflow/formManage/types.ts
@@ -0,0 +1,69 @@
+export interface FormManageVO {
+ /**
+ * 主键
+ */
+ id: string | number;
+
+ /**
+ * 表单名称
+ */
+ formName: string;
+
+ /**
+ * 表单类型
+ */
+ formType: string;
+ /**
+ * 表单类型名称
+ */
+ formTypeName: string;
+
+ /**
+ * 路由地址/表单ID
+ */
+ router: string;
+
+ /**
+ * 备注
+ */
+ remark: string;
+}
+
+export interface FormManageForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: string | number;
+
+ /**
+ * 表单名称
+ */
+ formName?: string;
+
+ /**
+ * 表单类型
+ */
+ formType?: string;
+
+ /**
+ * 路由地址/表单ID
+ */
+ router?: string;
+
+ /**
+ * 备注
+ */
+ remark?: string;
+}
+
+export interface FormManageQuery extends PageQuery {
+ /**
+ * 表单名称
+ */
+ formName?: string;
+
+ /**
+ * 表单类型
+ */
+ formType?: string;
+}
diff --git a/src/api/workflow/leave/index.ts b/src/api/workflow/leave/index.ts
new file mode 100644
index 0000000..4e6f363
--- /dev/null
+++ b/src/api/workflow/leave/index.ts
@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { LeaveVO, LeaveQuery, LeaveForm } from '@/api/workflow/leave/types';
+
+/**
+ * 查询请假列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listLeave = (query?: LeaveQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/leave/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询请假详细
+ * @param id
+ */
+export const getLeave = (id: string | number): AxiosPromise => {
+ return request({
+ url: '/workflow/leave/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增请假
+ * @param data
+ */
+export const addLeave = (data: LeaveForm): AxiosPromise => {
+ return request({
+ url: '/workflow/leave',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改请假
+ * @param data
+ */
+export const updateLeave = (data: LeaveForm): AxiosPromise => {
+ return request({
+ url: '/workflow/leave',
+ method: 'put',
+ data: data
+ });
+};
+
+/**
+ * 删除请假
+ * @param id
+ */
+export const delLeave = (id: string | number | Array) => {
+ return request({
+ url: '/workflow/leave/' + id,
+ method: 'delete'
+ });
+};
diff --git a/src/api/workflow/leave/types.ts b/src/api/workflow/leave/types.ts
new file mode 100644
index 0000000..a44d35d
--- /dev/null
+++ b/src/api/workflow/leave/types.ts
@@ -0,0 +1,24 @@
+export interface LeaveVO {
+ id: string | number;
+ leaveType: string;
+ startDate: string;
+ endDate: string;
+ leaveDays: number;
+ remark: string;
+ status?: string;
+}
+
+export interface LeaveForm extends BaseEntity {
+ id?: string | number;
+ leaveType?: string;
+ startDate?: string;
+ endDate?: string;
+ leaveDays?: number;
+ remark?: string;
+ status?: string;
+}
+
+export interface LeaveQuery extends PageQuery {
+ startLeaveDays?: number;
+ endLeaveDays?: number;
+}
diff --git a/src/api/workflow/model/index.ts b/src/api/workflow/model/index.ts
new file mode 100644
index 0000000..1ca8b19
--- /dev/null
+++ b/src/api/workflow/model/index.ts
@@ -0,0 +1,104 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { ModelForm, ModelQuery, ModelVO } from '@/api/workflow/model/types';
+
+/**
+ * 查询模型列表
+ * @param query
+ * @returns {*}
+ */
+export const listModel = (query: ModelQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/model/list',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询模型信息
+ * @param query
+ * @returns {*}
+ */
+export const getInfo = (id: string): AxiosPromise => {
+ return request({
+ url: '/workflow/model/getInfo/' + id,
+ method: 'get'
+ });
+};
+
+/**
+ * 新增模型
+ * @param data
+ * @returns {*}
+ */
+export const addModel = (data: ModelForm): AxiosPromise => {
+ return request({
+ url: '/workflow/model/save',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改模型信息
+ * @param data
+ * @returns {*}
+ */
+export function update(data: ModelForm): AxiosPromise {
+ return request({
+ url: '/workflow/model/update',
+ method: 'put',
+ data: data
+ });
+}
+
+/**
+ * 修改模型信息
+ * @param data
+ * @returns {*}
+ */
+export function editModelXml(data: ModelForm): AxiosPromise {
+ return request({
+ url: '/workflow/model/editModelXml',
+ method: 'put',
+ data: data
+ });
+}
+
+/**
+ * 按id删除模型
+ * @returns {*}
+ * @param id 模型id
+ */
+export function delModel(id: string | string[]): AxiosPromise {
+ return request({
+ url: '/workflow/model/' + id,
+ method: 'delete'
+ });
+}
+
+/**
+ * 模型部署
+ * @returns {*}
+ * @param id 模型id
+ */
+export const modelDeploy = (id: string): AxiosPromise => {
+ return request({
+ url: `/workflow/model/modelDeploy/${id}`,
+ method: 'post'
+ });
+};
+
+/**
+ * 复制模型
+ * @param data
+ * @returns {*}
+ */
+export const copyModel = (data: ModelForm): AxiosPromise => {
+ return request({
+ url: '/workflow/model/copyModel',
+ method: 'post',
+ data: data
+ });
+};
diff --git a/src/api/workflow/model/types.ts b/src/api/workflow/model/types.ts
new file mode 100644
index 0000000..77f947d
--- /dev/null
+++ b/src/api/workflow/model/types.ts
@@ -0,0 +1,66 @@
+export interface ModelForm {
+ id: string;
+ name: string;
+ key: string;
+ categoryCode: string;
+ xml: string;
+ svg: string;
+ description: string;
+}
+
+export interface ModelQuery extends PageQuery {
+ name?: string;
+ key?: string;
+ categoryCode?: string;
+}
+
+export interface OriginalPersistentState {
+ metaInfo: string;
+ editorSourceValueId: string;
+ createTime: string;
+ deploymentId?: string;
+ name: string;
+ tenantId: string;
+ category?: string;
+ version: number;
+ editorSourceExtraValueId?: string;
+ key: string;
+ lastUpdateTime: string;
+}
+
+export interface PersistentState {
+ metaInfo: string;
+ editorSourceValueId: string;
+ createTime: string;
+ deploymentId?: string;
+ name: string;
+ tenantId: string;
+ category?: string;
+ version: number;
+ editorSourceExtraValueId?: string;
+ key: string;
+ lastUpdateTime: string;
+}
+
+export interface ModelVO {
+ id: string;
+ revision: number;
+ originalPersistentState: OriginalPersistentState;
+ name: string;
+ key: string;
+ category?: string;
+ createTime: string;
+ lastUpdateTime: string;
+ version: number;
+ metaInfo: string;
+ deploymentId?: string;
+ editorSourceValueId: string;
+ editorSourceExtraValueId?: string;
+ tenantId: string;
+ persistentState: PersistentState;
+ revisionNext: number;
+ idPrefix: string;
+ inserted: boolean;
+ updated: boolean;
+ deleted: boolean;
+}
diff --git a/src/api/workflow/nodeConfig/types.ts b/src/api/workflow/nodeConfig/types.ts
new file mode 100644
index 0000000..a55fc91
--- /dev/null
+++ b/src/api/workflow/nodeConfig/types.ts
@@ -0,0 +1,38 @@
+import { FormManageVO } from '@/api/workflow/formManage/types';
+
+export interface NodeConfigVO {
+ /**
+ * 主键
+ */
+ id: string | number;
+
+ /**
+ * 表单id
+ */
+ formId: string | number;
+
+ /**
+ * 表单类型
+ */
+ formType: string;
+
+ /**
+ * 节点名称
+ */
+ nodeName: string;
+
+ /**
+ * 节点id
+ */
+ nodeId: string | number;
+
+ /**
+ * 流程定义id
+ */
+ definitionId: string | number;
+
+ /**
+ * 表单管理
+ */
+ wfFormManageVo: FormManageVO;
+}
diff --git a/src/api/workflow/processDefinition/index.ts b/src/api/workflow/processDefinition/index.ts
new file mode 100644
index 0000000..c063120
--- /dev/null
+++ b/src/api/workflow/processDefinition/index.ts
@@ -0,0 +1,114 @@
+import request from '@/utils/request';
+import { ProcessDefinitionQuery, ProcessDefinitionVO, definitionXmlVO } from '@/api/workflow/processDefinition/types';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 获取流程定义列表
+ * @param query 流程实例id
+ * @returns
+ */
+export const listProcessDefinition = (query: ProcessDefinitionQuery): AxiosPromise => {
+ return request({
+ url: `/workflow/processDefinition/list`,
+ method: 'get',
+ params: query
+ });
+};
+/**
+ * 按照流程定义key获取流程定义
+ * @param processInstanceId 流程实例id
+ * @returns
+ */
+export const getListByKey = (key: string) => {
+ return request({
+ url: `/workflow/processDefinition/getListByKey/${key}`,
+ method: 'get'
+ });
+};
+
+/**
+ * 通过流程定义id获取流程图
+ */
+export const definitionImage = (processDefinitionId: string): AxiosPromise => {
+ return request({
+ url: `/workflow/processDefinition/definitionImage/${processDefinitionId}` + '?t' + Math.random(),
+ method: 'get'
+ });
+};
+
+/**
+ * 通过流程定义id获取xml
+ * @param processDefinitionId 流程定义id
+ * @returns
+ */
+export const definitionXml = (processDefinitionId: string): AxiosPromise => {
+ return request({
+ url: `/workflow/processDefinition/definitionXml/${processDefinitionId}`,
+ method: 'get'
+ });
+};
+
+/**
+ * 删除流程定义
+ * @param deploymentId 部署id
+ * @param processDefinitionId 流程定义id
+ * @returns
+ */
+export const deleteProcessDefinition = (deploymentId: string | string[], processDefinitionId: string | string[]) => {
+ return request({
+ url: `/workflow/processDefinition/${deploymentId}/${processDefinitionId}`,
+ method: 'delete'
+ });
+};
+
+/**
+ * 挂起/激活
+ * @param processDefinitionId 流程定义id
+ * @returns
+ */
+export const updateDefinitionState = (processDefinitionId: string) => {
+ return request({
+ url: `/workflow/processDefinition/updateDefinitionState/${processDefinitionId}`,
+ method: 'put'
+ });
+};
+
+/**
+ * 流程定义转换为模型
+ * @param processDefinitionId 流程定义id
+ * @returns
+ */
+export const convertToModel = (processDefinitionId: string) => {
+ return request({
+ url: `/workflow/processDefinition/convertToModel/${processDefinitionId}`,
+ method: 'put'
+ });
+};
+
+/**
+ * 通过zip或xml部署流程定义
+ * @returns
+ */
+export function deployProcessFile(data: any) {
+ return request({
+ url: '/workflow/processDefinition/deployByFile',
+ method: 'post',
+ data: data,
+ headers: {
+ repeatSubmit: false
+ }
+ });
+}
+
+/**
+ * 迁移流程
+ * @param currentProcessDefinitionId
+ * @param fromProcessDefinitionId
+ * @returns
+ */
+export const migrationDefinition = (currentProcessDefinitionId: string, fromProcessDefinitionId: string) => {
+ return request({
+ url: `/workflow/processDefinition/migrationDefinition/${currentProcessDefinitionId}/${fromProcessDefinitionId}`,
+ method: 'put'
+ });
+};
diff --git a/src/api/workflow/processDefinition/types.ts b/src/api/workflow/processDefinition/types.ts
new file mode 100644
index 0000000..979ec25
--- /dev/null
+++ b/src/api/workflow/processDefinition/types.ts
@@ -0,0 +1,24 @@
+import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
+export interface ProcessDefinitionQuery extends PageQuery {
+ key?: string;
+ name?: string;
+ categoryCode?: string;
+}
+
+export interface ProcessDefinitionVO extends BaseEntity {
+ id: string;
+ name: string;
+ key: string;
+ version: number;
+ suspensionState: number;
+ resourceName: string;
+ diagramResourceName: string;
+ deploymentId: string;
+ deploymentTime: string;
+ wfDefinitionConfigVo: DefinitionConfigVO;
+}
+
+export interface definitionXmlVO {
+ xml: string[];
+ xmlStr: string;
+}
diff --git a/src/api/workflow/processInstance/index.ts b/src/api/workflow/processInstance/index.ts
new file mode 100644
index 0000000..6d5e53b
--- /dev/null
+++ b/src/api/workflow/processInstance/index.ts
@@ -0,0 +1,136 @@
+import request from '@/utils/request';
+import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 查询运行中实例列表
+ * @param query
+ * @returns {*}
+ */
+export const getPageByRunning = (query: ProcessInstanceQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/processInstance/getPageByRunning',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询已完成实例列表
+ * @param query
+ * @returns {*}
+ */
+export const getPageByFinish = (query: ProcessInstanceQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/processInstance/getPageByFinish',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 通过业务id获取历史流程图
+ */
+export const getHistoryImage = (businessKey: string) => {
+ return request({
+ url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(),
+ method: 'get'
+ });
+};
+
+/**
+ * 通过业务id获取历史流程图运行中,历史等节点
+ */
+export const getHistoryList = (businessKey: string): AxiosPromise> => {
+ return request({
+ url: `/workflow/processInstance/getHistoryList/${businessKey}` + '?t' + Math.random(),
+ method: 'get'
+ });
+};
+
+/**
+ * 获取审批记录
+ * @param businessKey 业务id
+ * @returns
+ */
+export const getHistoryRecord = (businessKey: string | number) => {
+ return request({
+ url: `/workflow/processInstance/getHistoryRecord/${businessKey}`,
+ method: 'get'
+ });
+};
+
+/**
+ * 作废
+ * @param data 参数
+ * @returns
+ */
+export const deleteRunInstance = (data: object) => {
+ return request({
+ url: `/workflow/processInstance/deleteRunInstance`,
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
+ * @param businessKey 业务id
+ * @returns
+ */
+export const deleteRunAndHisInstance = (businessKey: string | string[]) => {
+ return request({
+ url: `/workflow/processInstance/deleteRunAndHisInstance/${businessKey}`,
+ method: 'delete'
+ });
+};
+
+/**
+ * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
+ * @param businessKey 业务id
+ * @returns
+ */
+export const deleteFinishAndHisInstance = (businessKey: string | string[]) => {
+ return request({
+ url: `/workflow/processInstance/deleteFinishAndHisInstance/${businessKey}`,
+ method: 'delete'
+ });
+};
+
+/**
+ * 分页查询当前登录人单据
+ * @param query
+ * @returns {*}
+ */
+export const getPageByCurrent = (query: ProcessInstanceQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/processInstance/getPageByCurrent',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 撤销流程
+ * @param businessKey 业务id
+ * @returns
+ */
+export const cancelProcessApply = (businessKey: string) => {
+ return request({
+ url: `/workflow/processInstance/cancelProcessApply/${businessKey}`,
+ method: 'post'
+ });
+};
+
+export default {
+ getPageByRunning,
+ getPageByFinish,
+ getHistoryImage,
+ getHistoryList,
+ getHistoryRecord,
+ deleteRunInstance,
+ deleteRunAndHisInstance,
+ deleteFinishAndHisInstance,
+ getPageByCurrent,
+ cancelProcessApply
+};
diff --git a/src/api/workflow/processInstance/types.ts b/src/api/workflow/processInstance/types.ts
new file mode 100644
index 0000000..99d0511
--- /dev/null
+++ b/src/api/workflow/processInstance/types.ts
@@ -0,0 +1,27 @@
+import { TaskVO } from '@/api/workflow/task/types';
+
+export interface ProcessInstanceQuery extends PageQuery {
+ categoryCode?: string;
+ name?: string;
+ key?: string;
+ startUserId?: string;
+ businessKey?: string;
+}
+
+export interface ProcessInstanceVO extends BaseEntity {
+ id: string;
+ processDefinitionId: string;
+ processDefinitionName: string;
+ processDefinitionKey: string;
+ processDefinitionVersion: string;
+ deploymentId: string;
+ businessKey: string;
+ isSuspended?: any;
+ tenantId: string;
+ startTime: string;
+ endTime?: string;
+ startUserId: string;
+ businessStatus: string;
+ businessStatusName: string;
+ taskVoList: TaskVO[];
+}
diff --git a/src/api/workflow/task/index.ts b/src/api/workflow/task/index.ts
new file mode 100644
index 0000000..d29de30
--- /dev/null
+++ b/src/api/workflow/task/index.ts
@@ -0,0 +1,264 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { TaskQuery, TaskVO } from '@/api/workflow/task/types';
+
+/**
+ * 查询待办列表
+ * @param query
+ * @returns {*}
+ */
+export const getPageByTaskWait = (query: TaskQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/task/getPageByTaskWait',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询已办列表
+ * @param query
+ * @returns {*}
+ */
+export const getPageByTaskFinish = (query: TaskQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/task/getPageByTaskFinish',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 查询当前用户的抄送列表
+ * @param query
+ * @returns {*}
+ */
+export const getPageByTaskCopy = (query: TaskQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/task/getPageByTaskCopy',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 当前租户所有待办任务
+ * @param query
+ * @returns {*}
+ */
+export const getPageByAllTaskWait = (query: TaskQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/task/getPageByAllTaskWait',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 当前租户所有已办任务
+ * @param query
+ * @returns {*}
+ */
+export const getPageByAllTaskFinish = (query: TaskQuery): AxiosPromise => {
+ return request({
+ url: '/workflow/task/getPageByAllTaskFinish',
+ method: 'get',
+ params: query
+ });
+};
+
+/**
+ * 启动流程
+ * @param data
+ * @returns {*}
+ */
+export const startWorkFlow = (data: object): any => {
+ return request({
+ url: '/workflow/task/startWorkFlow',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 办理流程
+ * @param data
+ * @returns {*}
+ */
+export const completeTask = (data: object) => {
+ return request({
+ url: '/workflow/task/completeTask',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 认领任务
+ * @param taskId
+ * @returns {*}
+ */
+export const claim = (taskId: string): any => {
+ return request({
+ url: '/workflow/task/claim/' + taskId,
+ method: 'post'
+ });
+};
+
+/**
+ * 归还任务
+ * @param taskId
+ * @returns {*}
+ */
+export const returnTask = (taskId: string): any => {
+ return request({
+ url: '/workflow/task/returnTask/' + taskId,
+ method: 'post'
+ });
+};
+
+/**
+ * 任务驳回
+ * @param data
+ * @returns {*}
+ */
+export const backProcess = (data: any): any => {
+ return request({
+ url: '/workflow/task/backProcess',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 获取当前任务
+ * @param taskId
+ * @returns
+ */
+export const getTaskById = (taskId: string) => {
+ return request({
+ url: '/workflow/task/getTaskById/' + taskId,
+ method: 'get'
+ });
+};
+
+/**
+ * 加签
+ * @param data
+ * @returns
+ */
+export const addMultiInstanceExecution = (data: any) => {
+ return request({
+ url: '/workflow/task/addMultiInstanceExecution',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 减签
+ * @param data
+ * @returns
+ */
+export const deleteMultiInstanceExecution = (data: any) => {
+ return request({
+ url: '/workflow/task/deleteMultiInstanceExecution',
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 修改任务办理人
+ * @param taskIds
+ * @param userId
+ * @returns
+ */
+export const updateAssignee = (taskIds: Array, userId: string) => {
+ return request({
+ url: `/workflow/task/updateAssignee/${taskIds}/${userId}`,
+ method: 'put'
+ });
+};
+
+/**
+ * 转办任务
+ * @returns
+ */
+export const transferTask = (data: any) => {
+ return request({
+ url: `/workflow/task/transferTask`,
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 终止任务
+ * @returns
+ */
+export const terminationTask = (data: any) => {
+ return request({
+ url: `/workflow/task/terminationTask`,
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 查询流程变量
+ * @returns
+ */
+export const getInstanceVariable = (taskId: string) => {
+ return request({
+ url: `/workflow/task/getInstanceVariable/${taskId}`,
+ method: 'get'
+ });
+};
+
+/**
+ * 获取可驳回得任务节点
+ * @returns
+ */
+export const getTaskNodeList = (processInstanceId: string) => {
+ return request({
+ url: `/workflow/task/getTaskNodeList/${processInstanceId}`,
+ method: 'get'
+ });
+};
+
+/**
+ * 委托任务
+ * @returns
+ */
+export const delegateTask = (data: any) => {
+ return request({
+ url: `/workflow/task/delegateTask`,
+ method: 'post',
+ data: data
+ });
+};
+
+/**
+ * 查询工作流任务用户选择加签人员
+ * @param taskId
+ * @returns {*}
+ */
+export const getTaskUserIdsByAddMultiInstance = (taskId: string) => {
+ return request({
+ url: '/workflow/task/getTaskUserIdsByAddMultiInstance/' + taskId,
+ method: 'get'
+ });
+};
+
+/**
+ * 查询工作流选择减签人员
+ * @param taskId
+ * @returns {*}
+ */
+export const getListByDeleteMultiInstance = (taskId: string) => {
+ return request({
+ url: '/workflow/task/getListByDeleteMultiInstance/' + taskId,
+ method: 'get'
+ });
+};
diff --git a/src/api/workflow/task/types.ts b/src/api/workflow/task/types.ts
new file mode 100644
index 0000000..0425a1a
--- /dev/null
+++ b/src/api/workflow/task/types.ts
@@ -0,0 +1,49 @@
+import { NodeConfigVO } from '@/api/workflow/nodeConfig/types';
+import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
+export interface TaskQuery extends PageQuery {
+ name?: string;
+ processDefinitionKey?: string;
+ processDefinitionName?: string;
+}
+
+export interface ParticipantVo {
+ groupIds?: string[] | number[];
+ candidate: string[] | number[];
+ candidateName: string[];
+ claim: boolean;
+}
+
+export interface TaskVO extends BaseEntity {
+ id: string;
+ name: string;
+ description?: string;
+ priority: number;
+ owner?: string;
+ assignee?: string | number;
+ assigneeName?: string;
+ processInstanceId: string;
+ executionId: string;
+ taskDefinitionId?: any;
+ processDefinitionId: string;
+ endTime?: string;
+ taskDefinitionKey: string;
+ dueDate?: string;
+ category?: any;
+ parentTaskId?: any;
+ tenantId: string;
+ claimTime?: string;
+ businessStatus?: string;
+ businessStatusName?: string;
+ processDefinitionName?: string;
+ processDefinitionKey?: string;
+ participantVo?: ParticipantVo;
+ multiInstance?: boolean;
+ businessKey?: string;
+ wfNodeConfigVo?: NodeConfigVO;
+ wfDefinitionConfigVo?: DefinitionConfigVO;
+}
+
+export interface VariableVo {
+ key: string;
+ value: string;
+}
diff --git a/src/api/workflow/workflowCommon/index.ts b/src/api/workflow/workflowCommon/index.ts
new file mode 100644
index 0000000..63ce318
--- /dev/null
+++ b/src/api/workflow/workflowCommon/index.ts
@@ -0,0 +1,29 @@
+import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
+
+export default {
+ routerJump(routerJumpVo: RouterJumpVo, proxy) {
+ if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'static' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) {
+ proxy.$tab.closePage(proxy.$route);
+ proxy.$router.push({
+ path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`,
+ query: {
+ id: routerJumpVo.businessKey,
+ type: routerJumpVo.type,
+ taskId: routerJumpVo.taskId
+ }
+ });
+ } else if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'dynamic' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) {
+ proxy.$tab.closePage(proxy.$route);
+ proxy.$router.push({
+ path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`,
+ query: {
+ id: routerJumpVo.businessKey,
+ type: routerJumpVo.type,
+ taskId: routerJumpVo.taskId
+ }
+ });
+ } else {
+ proxy?.$modal.msgError('请到模型配置菜单!');
+ }
+ }
+};
diff --git a/src/api/workflow/workflowCommon/types.ts b/src/api/workflow/workflowCommon/types.ts
new file mode 100644
index 0000000..0f1ef1f
--- /dev/null
+++ b/src/api/workflow/workflowCommon/types.ts
@@ -0,0 +1,16 @@
+import { NodeConfigVO } from '@/api/workflow/nodeConfig/types';
+import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types';
+
+export interface RouterJumpVo {
+ wfNodeConfigVo: NodeConfigVO;
+ wfDefinitionConfigVo: DefinitionConfigVO;
+ businessKey: string;
+ taskId: string;
+ type: string;
+}
+
+export interface StartProcessBo {
+ businessKey: string | number;
+ tableName: string;
+ variables: any;
+}
diff --git a/src/assets/401_images/401.gif b/src/assets/401_images/401.gif
new file mode 100644
index 0000000..cd6e0d9
Binary files /dev/null and b/src/assets/401_images/401.gif differ
diff --git a/src/assets/404_images/404.png b/src/assets/404_images/404.png
new file mode 100644
index 0000000..3d8e230
Binary files /dev/null and b/src/assets/404_images/404.png differ
diff --git a/src/assets/404_images/404_cloud.png b/src/assets/404_images/404_cloud.png
new file mode 100644
index 0000000..c6281d0
Binary files /dev/null and b/src/assets/404_images/404_cloud.png differ
diff --git a/src/assets/icons/svg/404.svg b/src/assets/icons/svg/404.svg
new file mode 100644
index 0000000..6df5019
--- /dev/null
+++ b/src/assets/icons/svg/404.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/bug.svg b/src/assets/icons/svg/bug.svg
new file mode 100644
index 0000000..05a150d
--- /dev/null
+++ b/src/assets/icons/svg/bug.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/build.svg b/src/assets/icons/svg/build.svg
new file mode 100644
index 0000000..97c4688
--- /dev/null
+++ b/src/assets/icons/svg/build.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/button.svg b/src/assets/icons/svg/button.svg
new file mode 100644
index 0000000..904fddc
--- /dev/null
+++ b/src/assets/icons/svg/button.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/caret-back.svg b/src/assets/icons/svg/caret-back.svg
new file mode 100644
index 0000000..9bae722
--- /dev/null
+++ b/src/assets/icons/svg/caret-back.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/caret-forward.svg b/src/assets/icons/svg/caret-forward.svg
new file mode 100644
index 0000000..1ec3f7d
--- /dev/null
+++ b/src/assets/icons/svg/caret-forward.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/cascader.svg b/src/assets/icons/svg/cascader.svg
new file mode 100644
index 0000000..e256024
--- /dev/null
+++ b/src/assets/icons/svg/cascader.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/category.svg b/src/assets/icons/svg/category.svg
new file mode 100644
index 0000000..df92526
--- /dev/null
+++ b/src/assets/icons/svg/category.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/chart.svg b/src/assets/icons/svg/chart.svg
new file mode 100644
index 0000000..27728fb
--- /dev/null
+++ b/src/assets/icons/svg/chart.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/checkbox.svg b/src/assets/icons/svg/checkbox.svg
new file mode 100644
index 0000000..013fd3a
--- /dev/null
+++ b/src/assets/icons/svg/checkbox.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/clipboard.svg b/src/assets/icons/svg/clipboard.svg
new file mode 100644
index 0000000..90923ff
--- /dev/null
+++ b/src/assets/icons/svg/clipboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/code.svg b/src/assets/icons/svg/code.svg
new file mode 100644
index 0000000..5f9c5ab
--- /dev/null
+++ b/src/assets/icons/svg/code.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/color.svg b/src/assets/icons/svg/color.svg
new file mode 100644
index 0000000..44a81aa
--- /dev/null
+++ b/src/assets/icons/svg/color.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/company.svg b/src/assets/icons/svg/company.svg
new file mode 100644
index 0000000..fcf1394
--- /dev/null
+++ b/src/assets/icons/svg/company.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/component.svg b/src/assets/icons/svg/component.svg
new file mode 100644
index 0000000..29c3458
--- /dev/null
+++ b/src/assets/icons/svg/component.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/dashboard.svg b/src/assets/icons/svg/dashboard.svg
new file mode 100644
index 0000000..5317d37
--- /dev/null
+++ b/src/assets/icons/svg/dashboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/date-range.svg b/src/assets/icons/svg/date-range.svg
new file mode 100644
index 0000000..fda571e
--- /dev/null
+++ b/src/assets/icons/svg/date-range.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/date.svg b/src/assets/icons/svg/date.svg
new file mode 100644
index 0000000..52dc73e
--- /dev/null
+++ b/src/assets/icons/svg/date.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/dict.svg b/src/assets/icons/svg/dict.svg
new file mode 100644
index 0000000..4849377
--- /dev/null
+++ b/src/assets/icons/svg/dict.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/documentation.svg b/src/assets/icons/svg/documentation.svg
new file mode 100644
index 0000000..7043122
--- /dev/null
+++ b/src/assets/icons/svg/documentation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/download.svg b/src/assets/icons/svg/download.svg
new file mode 100644
index 0000000..c896951
--- /dev/null
+++ b/src/assets/icons/svg/download.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/drag.svg b/src/assets/icons/svg/drag.svg
new file mode 100644
index 0000000..4185d3c
--- /dev/null
+++ b/src/assets/icons/svg/drag.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/druid.svg b/src/assets/icons/svg/druid.svg
new file mode 100644
index 0000000..a2b4b4e
--- /dev/null
+++ b/src/assets/icons/svg/druid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/edit.svg b/src/assets/icons/svg/edit.svg
new file mode 100644
index 0000000..d26101f
--- /dev/null
+++ b/src/assets/icons/svg/edit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/education.svg b/src/assets/icons/svg/education.svg
new file mode 100644
index 0000000..7bfb01d
--- /dev/null
+++ b/src/assets/icons/svg/education.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/email.svg b/src/assets/icons/svg/email.svg
new file mode 100644
index 0000000..74d25e2
--- /dev/null
+++ b/src/assets/icons/svg/email.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/example.svg b/src/assets/icons/svg/example.svg
new file mode 100644
index 0000000..46f42b5
--- /dev/null
+++ b/src/assets/icons/svg/example.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/excel.svg b/src/assets/icons/svg/excel.svg
new file mode 100644
index 0000000..74d97b8
--- /dev/null
+++ b/src/assets/icons/svg/excel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/exit-fullscreen.svg b/src/assets/icons/svg/exit-fullscreen.svg
new file mode 100644
index 0000000..485c128
--- /dev/null
+++ b/src/assets/icons/svg/exit-fullscreen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/eye-open.svg b/src/assets/icons/svg/eye-open.svg
new file mode 100644
index 0000000..88dcc98
--- /dev/null
+++ b/src/assets/icons/svg/eye-open.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/eye.svg b/src/assets/icons/svg/eye.svg
new file mode 100644
index 0000000..16ed2d8
--- /dev/null
+++ b/src/assets/icons/svg/eye.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/finish.svg b/src/assets/icons/svg/finish.svg
new file mode 100644
index 0000000..4685c23
--- /dev/null
+++ b/src/assets/icons/svg/finish.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/form.svg b/src/assets/icons/svg/form.svg
new file mode 100644
index 0000000..dcbaa18
--- /dev/null
+++ b/src/assets/icons/svg/form.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/fullscreen.svg b/src/assets/icons/svg/fullscreen.svg
new file mode 100644
index 0000000..0e86b6f
--- /dev/null
+++ b/src/assets/icons/svg/fullscreen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/gitee.svg b/src/assets/icons/svg/gitee.svg
new file mode 100644
index 0000000..6324608
--- /dev/null
+++ b/src/assets/icons/svg/gitee.svg
@@ -0,0 +1 @@
+
diff --git a/src/assets/icons/svg/github.svg b/src/assets/icons/svg/github.svg
new file mode 100644
index 0000000..db0a0d4
--- /dev/null
+++ b/src/assets/icons/svg/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/guide.svg b/src/assets/icons/svg/guide.svg
new file mode 100644
index 0000000..b271001
--- /dev/null
+++ b/src/assets/icons/svg/guide.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/icon.svg b/src/assets/icons/svg/icon.svg
new file mode 100644
index 0000000..82be8ee
--- /dev/null
+++ b/src/assets/icons/svg/icon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/input.svg b/src/assets/icons/svg/input.svg
new file mode 100644
index 0000000..ab91381
--- /dev/null
+++ b/src/assets/icons/svg/input.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/international.svg b/src/assets/icons/svg/international.svg
new file mode 100644
index 0000000..e9b56ee
--- /dev/null
+++ b/src/assets/icons/svg/international.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/job.svg b/src/assets/icons/svg/job.svg
new file mode 100644
index 0000000..2a93a25
--- /dev/null
+++ b/src/assets/icons/svg/job.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/language.svg b/src/assets/icons/svg/language.svg
new file mode 100644
index 0000000..0082b57
--- /dev/null
+++ b/src/assets/icons/svg/language.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/link.svg b/src/assets/icons/svg/link.svg
new file mode 100644
index 0000000..48197ba
--- /dev/null
+++ b/src/assets/icons/svg/link.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/list.svg b/src/assets/icons/svg/list.svg
new file mode 100644
index 0000000..20259ed
--- /dev/null
+++ b/src/assets/icons/svg/list.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/lock.svg b/src/assets/icons/svg/lock.svg
new file mode 100644
index 0000000..74fee54
--- /dev/null
+++ b/src/assets/icons/svg/lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/log.svg b/src/assets/icons/svg/log.svg
new file mode 100644
index 0000000..d879d33
--- /dev/null
+++ b/src/assets/icons/svg/log.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/logininfor.svg b/src/assets/icons/svg/logininfor.svg
new file mode 100644
index 0000000..267f844
--- /dev/null
+++ b/src/assets/icons/svg/logininfor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/maxkey.svg b/src/assets/icons/svg/maxkey.svg
new file mode 100644
index 0000000..f8f8a7d
--- /dev/null
+++ b/src/assets/icons/svg/maxkey.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/icons/svg/message.svg b/src/assets/icons/svg/message.svg
new file mode 100644
index 0000000..14ca817
--- /dev/null
+++ b/src/assets/icons/svg/message.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/model.svg b/src/assets/icons/svg/model.svg
new file mode 100644
index 0000000..0c57d70
--- /dev/null
+++ b/src/assets/icons/svg/model.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/money.svg b/src/assets/icons/svg/money.svg
new file mode 100644
index 0000000..c1580de
--- /dev/null
+++ b/src/assets/icons/svg/money.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/monitor.svg b/src/assets/icons/svg/monitor.svg
new file mode 100644
index 0000000..bc308cb
--- /dev/null
+++ b/src/assets/icons/svg/monitor.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/my-copy.svg b/src/assets/icons/svg/my-copy.svg
new file mode 100644
index 0000000..49f69fa
--- /dev/null
+++ b/src/assets/icons/svg/my-copy.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/my-task.svg b/src/assets/icons/svg/my-task.svg
new file mode 100644
index 0000000..1f1ea44
--- /dev/null
+++ b/src/assets/icons/svg/my-task.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/nested.svg b/src/assets/icons/svg/nested.svg
new file mode 100644
index 0000000..06713a8
--- /dev/null
+++ b/src/assets/icons/svg/nested.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/number.svg b/src/assets/icons/svg/number.svg
new file mode 100644
index 0000000..ad5ce9a
--- /dev/null
+++ b/src/assets/icons/svg/number.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/online.svg b/src/assets/icons/svg/online.svg
new file mode 100644
index 0000000..330a202
--- /dev/null
+++ b/src/assets/icons/svg/online.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/password.svg b/src/assets/icons/svg/password.svg
new file mode 100644
index 0000000..6c64def
--- /dev/null
+++ b/src/assets/icons/svg/password.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/pdf.svg b/src/assets/icons/svg/pdf.svg
new file mode 100644
index 0000000..957aa0c
--- /dev/null
+++ b/src/assets/icons/svg/pdf.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/people.svg b/src/assets/icons/svg/people.svg
new file mode 100644
index 0000000..2bd54ae
--- /dev/null
+++ b/src/assets/icons/svg/people.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/peoples.svg b/src/assets/icons/svg/peoples.svg
new file mode 100644
index 0000000..aab852e
--- /dev/null
+++ b/src/assets/icons/svg/peoples.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/phone.svg b/src/assets/icons/svg/phone.svg
new file mode 100644
index 0000000..ab8e8c4
--- /dev/null
+++ b/src/assets/icons/svg/phone.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/post.svg b/src/assets/icons/svg/post.svg
new file mode 100644
index 0000000..2922c61
--- /dev/null
+++ b/src/assets/icons/svg/post.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/process-definition.svg b/src/assets/icons/svg/process-definition.svg
new file mode 100644
index 0000000..202d200
--- /dev/null
+++ b/src/assets/icons/svg/process-definition.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/qq.svg b/src/assets/icons/svg/qq.svg
new file mode 100644
index 0000000..ee13d4e
--- /dev/null
+++ b/src/assets/icons/svg/qq.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/question.svg b/src/assets/icons/svg/question.svg
new file mode 100644
index 0000000..cf75bd4
--- /dev/null
+++ b/src/assets/icons/svg/question.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/radio.svg b/src/assets/icons/svg/radio.svg
new file mode 100644
index 0000000..0cde345
--- /dev/null
+++ b/src/assets/icons/svg/radio.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/rate.svg b/src/assets/icons/svg/rate.svg
new file mode 100644
index 0000000..aa3b14d
--- /dev/null
+++ b/src/assets/icons/svg/rate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/redis-list.svg b/src/assets/icons/svg/redis-list.svg
new file mode 100644
index 0000000..98a15b2
--- /dev/null
+++ b/src/assets/icons/svg/redis-list.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/redis.svg b/src/assets/icons/svg/redis.svg
new file mode 100644
index 0000000..2f1d62d
--- /dev/null
+++ b/src/assets/icons/svg/redis.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/row.svg b/src/assets/icons/svg/row.svg
new file mode 100644
index 0000000..0780992
--- /dev/null
+++ b/src/assets/icons/svg/row.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/search.svg b/src/assets/icons/svg/search.svg
new file mode 100644
index 0000000..84233dd
--- /dev/null
+++ b/src/assets/icons/svg/search.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/select.svg b/src/assets/icons/svg/select.svg
new file mode 100644
index 0000000..d628382
--- /dev/null
+++ b/src/assets/icons/svg/select.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/server.svg b/src/assets/icons/svg/server.svg
new file mode 100644
index 0000000..eb287e3
--- /dev/null
+++ b/src/assets/icons/svg/server.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/shopping.svg b/src/assets/icons/svg/shopping.svg
new file mode 100644
index 0000000..87513e7
--- /dev/null
+++ b/src/assets/icons/svg/shopping.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/size.svg b/src/assets/icons/svg/size.svg
new file mode 100644
index 0000000..ddb25b8
--- /dev/null
+++ b/src/assets/icons/svg/size.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/skill.svg b/src/assets/icons/svg/skill.svg
new file mode 100644
index 0000000..a3b7312
--- /dev/null
+++ b/src/assets/icons/svg/skill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/slider.svg b/src/assets/icons/svg/slider.svg
new file mode 100644
index 0000000..fbe4f39
--- /dev/null
+++ b/src/assets/icons/svg/slider.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/star.svg b/src/assets/icons/svg/star.svg
new file mode 100644
index 0000000..6cf86e6
--- /dev/null
+++ b/src/assets/icons/svg/star.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/swagger.svg b/src/assets/icons/svg/swagger.svg
new file mode 100644
index 0000000..05d4e7b
--- /dev/null
+++ b/src/assets/icons/svg/swagger.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/switch.svg b/src/assets/icons/svg/switch.svg
new file mode 100644
index 0000000..0ba61e3
--- /dev/null
+++ b/src/assets/icons/svg/switch.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/system.svg b/src/assets/icons/svg/system.svg
new file mode 100644
index 0000000..5992593
--- /dev/null
+++ b/src/assets/icons/svg/system.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/tab.svg b/src/assets/icons/svg/tab.svg
new file mode 100644
index 0000000..b4b48e4
--- /dev/null
+++ b/src/assets/icons/svg/tab.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/table.svg b/src/assets/icons/svg/table.svg
new file mode 100644
index 0000000..0e3dc9d
--- /dev/null
+++ b/src/assets/icons/svg/table.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/textarea.svg b/src/assets/icons/svg/textarea.svg
new file mode 100644
index 0000000..2709f29
--- /dev/null
+++ b/src/assets/icons/svg/textarea.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/theme.svg b/src/assets/icons/svg/theme.svg
new file mode 100644
index 0000000..5982a2f
--- /dev/null
+++ b/src/assets/icons/svg/theme.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/time-range.svg b/src/assets/icons/svg/time-range.svg
new file mode 100644
index 0000000..13c1202
--- /dev/null
+++ b/src/assets/icons/svg/time-range.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/time.svg b/src/assets/icons/svg/time.svg
new file mode 100644
index 0000000..b376e32
--- /dev/null
+++ b/src/assets/icons/svg/time.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/tool.svg b/src/assets/icons/svg/tool.svg
new file mode 100644
index 0000000..48e0e35
--- /dev/null
+++ b/src/assets/icons/svg/tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/topiam.svg b/src/assets/icons/svg/topiam.svg
new file mode 100644
index 0000000..e7ea057
--- /dev/null
+++ b/src/assets/icons/svg/topiam.svg
@@ -0,0 +1,29 @@
+
diff --git a/src/assets/icons/svg/tree-table.svg b/src/assets/icons/svg/tree-table.svg
new file mode 100644
index 0000000..8aafdb8
--- /dev/null
+++ b/src/assets/icons/svg/tree-table.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/tree.svg b/src/assets/icons/svg/tree.svg
new file mode 100644
index 0000000..dd4b7dd
--- /dev/null
+++ b/src/assets/icons/svg/tree.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/upload.svg b/src/assets/icons/svg/upload.svg
new file mode 100644
index 0000000..bae49c0
--- /dev/null
+++ b/src/assets/icons/svg/upload.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/user.svg b/src/assets/icons/svg/user.svg
new file mode 100644
index 0000000..0ba0716
--- /dev/null
+++ b/src/assets/icons/svg/user.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/validCode.svg b/src/assets/icons/svg/validCode.svg
new file mode 100644
index 0000000..cfb1021
--- /dev/null
+++ b/src/assets/icons/svg/validCode.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/waiting.svg b/src/assets/icons/svg/waiting.svg
new file mode 100644
index 0000000..2c2042d
--- /dev/null
+++ b/src/assets/icons/svg/waiting.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/wechat.svg b/src/assets/icons/svg/wechat.svg
new file mode 100644
index 0000000..c586e55
--- /dev/null
+++ b/src/assets/icons/svg/wechat.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/workflow.svg b/src/assets/icons/svg/workflow.svg
new file mode 100644
index 0000000..2f7423a
--- /dev/null
+++ b/src/assets/icons/svg/workflow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/icons/svg/zip.svg b/src/assets/icons/svg/zip.svg
new file mode 100644
index 0000000..f806fc4
--- /dev/null
+++ b/src/assets/icons/svg/zip.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/images/dark.svg b/src/assets/images/dark.svg
new file mode 100644
index 0000000..f646bd7
--- /dev/null
+++ b/src/assets/images/dark.svg
@@ -0,0 +1,39 @@
+
+
\ No newline at end of file
diff --git a/src/assets/images/light.svg b/src/assets/images/light.svg
new file mode 100644
index 0000000..ab7cc08
--- /dev/null
+++ b/src/assets/images/light.svg
@@ -0,0 +1,39 @@
+
+
\ No newline at end of file
diff --git a/src/assets/images/login-background.jpg b/src/assets/images/login-background.jpg
new file mode 100644
index 0000000..fa6408b
Binary files /dev/null and b/src/assets/images/login-background.jpg differ
diff --git a/src/assets/images/profile.jpg b/src/assets/images/profile.jpg
new file mode 100644
index 0000000..f4fde57
Binary files /dev/null and b/src/assets/images/profile.jpg differ
diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png
new file mode 100644
index 0000000..3f919d8
Binary files /dev/null and b/src/assets/logo/logo.png differ
diff --git a/src/assets/styles/btn.scss b/src/assets/styles/btn.scss
new file mode 100644
index 0000000..a1ccd01
--- /dev/null
+++ b/src/assets/styles/btn.scss
@@ -0,0 +1,99 @@
+@import './variables.module.scss';
+
+@mixin colorBtn($color) {
+ background: $color;
+
+ &:hover {
+ color: $color;
+
+ &:before,
+ &:after {
+ background: $color;
+ }
+ }
+}
+
+.blue-btn {
+ @include colorBtn($blue);
+}
+
+.light-blue-btn {
+ @include colorBtn($light-blue);
+}
+
+.red-btn {
+ @include colorBtn($red);
+}
+
+.pink-btn {
+ @include colorBtn($pink);
+}
+
+.green-btn {
+ @include colorBtn($green);
+}
+
+.tiffany-btn {
+ @include colorBtn($tiffany);
+}
+
+.yellow-btn {
+ @include colorBtn($yellow);
+}
+
+.pan-btn {
+ font-size: 14px;
+ color: #fff;
+ padding: 14px 36px;
+ border-radius: 8px;
+ border: none;
+ outline: none;
+ transition: 600ms ease all;
+ position: relative;
+ display: inline-block;
+
+ &:hover {
+ background: #fff;
+
+ &:before,
+ &:after {
+ width: 100%;
+ transition: 600ms ease all;
+ }
+ }
+
+ &:before,
+ &:after {
+ content: '';
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 2px;
+ width: 0;
+ transition: 400ms ease all;
+ }
+
+ &::after {
+ right: inherit;
+ top: inherit;
+ left: 0;
+ bottom: 0;
+ }
+}
+
+.custom-button {
+ display: inline-block;
+ line-height: 1;
+ white-space: nowrap;
+ cursor: pointer;
+ background: #fff;
+ color: #fff;
+ -webkit-appearance: none;
+ text-align: center;
+ box-sizing: border-box;
+ outline: 0;
+ margin: 0;
+ padding: 10px 15px;
+ font-size: 14px;
+ border-radius: 4px;
+}
diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss
new file mode 100644
index 0000000..220e4ac
--- /dev/null
+++ b/src/assets/styles/element-ui.scss
@@ -0,0 +1,149 @@
+
+.el-collapse {
+ .collapse__title {
+ font-weight: 600;
+ padding: 0 8px;
+ font-size: 1.2em;
+ line-height: 1.1em;
+ }
+ .el-collapse-item__content {
+ padding: 0 8px;
+ }
+}
+
+.el-divider--horizontal {
+ margin-bottom: 10px;
+ margin-top: 10px;
+}
+
+.el-breadcrumb__inner,
+.el-breadcrumb__inner a {
+ font-weight: 400 !important;
+}
+
+.el-upload {
+ input[type='file'] {
+ display: none !important;
+ }
+}
+
+.el-upload__input {
+ display: none;
+}
+
+.cell {
+ .el-tag {
+ margin-right: 0px;
+ }
+}
+
+.small-padding {
+ .cell {
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+}
+
+.fixed-width {
+ .el-button--mini {
+ padding: 7px 10px;
+ width: 60px;
+ }
+}
+
+.status-col {
+ .cell {
+ padding: 0 10px;
+ text-align: center;
+
+ .el-tag {
+ margin-right: 0px;
+ }
+ }
+}
+
+/*-------------Dialog-------------**/
+.el-overlay {
+ overflow: hidden;
+
+ .el-overlay-dialog {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+
+ .el-dialog {
+ margin: 0 auto !important;
+
+ .el-dialog__body {
+ padding: 15px !important;
+ }
+ .el-dialog__header {
+ padding: 16px 16px 8px 16px;
+ box-sizing: border-box;
+ border-bottom: 1px solid var(--brder-color);
+ margin-right: 0;
+ }
+ }
+ }
+}
+
+.el-dialog__body {
+ max-height: calc(90vh - 111px) !important;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+// refine element ui upload
+.upload-container {
+ .el-upload {
+ width: 100%;
+
+ .el-upload-dragger {
+ width: 100%;
+ height: 200px;
+ }
+ }
+}
+
+// dropdown
+.el-dropdown-menu {
+ a {
+ display: block;
+ }
+}
+
+// fix date-picker ui bug in filter-item
+.el-range-editor.el-input__inner {
+ display: inline-flex !important;
+}
+
+// to fix el-date-picker css style
+.el-range-separator {
+ box-sizing: content-box;
+}
+
+.el-menu--collapse > div > .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
+ display: none;
+}
+
+.el-dropdown .el-dropdown-link {
+ color: var(--el-color-primary) !important;
+}
+
+/* 当 el-form 的 inline 属性为 true 时 */
+/* 设置 label 的宽度默认为 68px */
+.el-form--inline .el-form-item__label {
+ width: 68px;
+}
+
+/* 设置 el-select 的宽度默认为 240px */
+.el-form--inline .el-select {
+ width: 240px;
+}
+
+/* 设置 el-input 的宽度默认为 240px */
+.el-form--inline .el-input {
+ width: 240px;
+}
diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss
new file mode 100644
index 0000000..bdf9b03
--- /dev/null
+++ b/src/assets/styles/index.scss
@@ -0,0 +1,215 @@
+@import './variables.module.scss';
+@import './mixin.scss';
+@import './transition.scss';
+@import './element-ui.scss';
+@import './sidebar.scss';
+@import './btn.scss';
+@import './ruoyi.scss';
+@import 'animate.css';
+@import 'element-plus/dist/index.css';
+
+body {
+ height: 100%;
+ margin: 0;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ text-rendering: optimizeLegibility;
+ font-family:
+ Helvetica Neue,
+ Helvetica,
+ PingFang SC,
+ Hiragino Sans GB,
+ Microsoft YaHei,
+ Arial,
+ sans-serif;
+}
+
+label {
+ font-weight: 700;
+}
+
+html {
+ height: 100%;
+ box-sizing: border-box;
+}
+
+html.dark .svg-icon,
+html.dark svg {
+ fill: var(--el-text-color-regular);
+}
+
+#app {
+ height: 100%;
+}
+
+*,
+*:before,
+*:after {
+ box-sizing: inherit;
+}
+
+.no-padding {
+ padding: 0px !important;
+}
+
+.padding-content {
+ padding: 4px 0;
+}
+
+a:focus,
+a:active {
+ outline: none;
+}
+
+a,
+a:focus,
+a:hover {
+ cursor: pointer;
+ color: inherit;
+ text-decoration: none;
+}
+
+div:focus {
+ outline: none;
+}
+
+.fr {
+ float: right;
+}
+
+.fl {
+ float: left;
+}
+
+.pr-5 {
+ padding-right: 5px;
+}
+
+.pl-5 {
+ padding-left: 5px;
+}
+
+.block {
+ display: block;
+}
+
+.pointer {
+ cursor: pointer;
+}
+
+.inlineBlock {
+ display: block;
+}
+
+.clearfix {
+ &:after {
+ visibility: hidden;
+ display: block;
+ font-size: 0;
+ content: ' ';
+ clear: both;
+ height: 0;
+ }
+}
+
+aside {
+ background: #eef1f6;
+ padding: 8px 24px;
+ margin-bottom: 20px;
+ border-radius: 2px;
+ display: block;
+ line-height: 32px;
+ font-size: 16px;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ color: #2c3e50;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ a {
+ color: #337ab7;
+ cursor: pointer;
+
+ &:hover {
+ color: rgb(32, 160, 255);
+ }
+ }
+}
+
+//main-container全局样式
+.app-container {
+ padding: 20px;
+}
+
+// search面板样式
+.panel,
+.search {
+ margin-bottom: 0.75rem;
+ border-radius: 0.25rem;
+ border: 1px solid var(--el-border-color-light);
+ background-color: var(--el-bg-color-overlay);
+ padding: 0.75rem;
+ transition: all ease 0.3s;
+
+ &:hover {
+ box-shadow: 0 2px 12px #0000001a;
+ transition: all ease 0.3s;
+ }
+}
+
+.components-container {
+ margin: 30px 50px;
+ position: relative;
+}
+
+.pagination-container {
+ margin-top: 30px;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.sub-navbar {
+ height: 50px;
+ line-height: 50px;
+ position: relative;
+ width: 100%;
+ text-align: right;
+ padding-right: 20px;
+ transition: 600ms ease position;
+ background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
+
+ .subtitle {
+ font-size: 20px;
+ color: #fff;
+ }
+
+ &.draft {
+ background: #d0d0d0;
+ }
+
+ &.deleted {
+ background: #d0d0d0;
+ }
+}
+
+.link-type,
+.link-type:focus {
+ color: #337ab7;
+ cursor: pointer;
+
+ &:hover {
+ color: rgb(32, 160, 255);
+ }
+}
+
+.filter-container {
+ padding-bottom: 10px;
+
+ .filter-item {
+ display: inline-block;
+ vertical-align: middle;
+ margin-bottom: 10px;
+ }
+}
diff --git a/src/assets/styles/mixin.scss b/src/assets/styles/mixin.scss
new file mode 100644
index 0000000..5250e71
--- /dev/null
+++ b/src/assets/styles/mixin.scss
@@ -0,0 +1,60 @@
+@mixin clearfix {
+ &:after {
+ content: '';
+ display: table;
+ clear: both;
+ }
+}
+
+@mixin scrollBar {
+ &::-webkit-scrollbar-track-piece {
+ background: #d3dce6;
+ }
+
+ &::-webkit-scrollbar {
+ width: 6px;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background: #99a9bf;
+ border-radius: 20px;
+ }
+}
+
+@mixin relative {
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+
+@mixin pct($pct) {
+ width: #{$pct};
+ position: relative;
+ margin: 0 auto;
+}
+
+@mixin triangle($width, $height, $color, $direction) {
+ $width: $width/2;
+ $color-border-style: $height solid $color;
+ $transparent-border-style: $width solid transparent;
+ height: 0;
+ width: 0;
+
+ @if $direction==up {
+ border-bottom: $color-border-style;
+ border-left: $transparent-border-style;
+ border-right: $transparent-border-style;
+ } @else if $direction==right {
+ border-left: $color-border-style;
+ border-top: $transparent-border-style;
+ border-bottom: $transparent-border-style;
+ } @else if $direction==down {
+ border-top: $color-border-style;
+ border-left: $transparent-border-style;
+ border-right: $transparent-border-style;
+ } @else if $direction==left {
+ border-right: $color-border-style;
+ border-top: $transparent-border-style;
+ border-bottom: $transparent-border-style;
+ }
+}
diff --git a/src/assets/styles/ruoyi.scss b/src/assets/styles/ruoyi.scss
new file mode 100644
index 0000000..d2ecb24
--- /dev/null
+++ b/src/assets/styles/ruoyi.scss
@@ -0,0 +1,290 @@
+/**
+ * 通用css样式布局处理
+ * Copyright (c) 2019 ruoyi
+ */
+
+/** 基础通用 **/
+.pt5 {
+ padding-top: 5px;
+}
+.pr5 {
+ padding-right: 5px;
+}
+.pb5 {
+ padding-bottom: 5px;
+}
+.mt5 {
+ margin-top: 5px;
+}
+.mr5 {
+ margin-right: 5px;
+}
+.mb5 {
+ margin-bottom: 5px;
+}
+.mb8 {
+ margin-bottom: 8px;
+}
+.ml5 {
+ margin-left: 5px;
+}
+.mt10 {
+ margin-top: 10px;
+}
+.mr10 {
+ margin-right: 10px;
+}
+.mb10 {
+ margin-bottom: 10px;
+}
+.ml10 {
+ margin-left: 10px;
+}
+.mt20 {
+ margin-top: 20px;
+}
+.mr20 {
+ margin-right: 20px;
+}
+.mb20 {
+ margin-bottom: 20px;
+}
+.ml20 {
+ margin-left: 20px;
+}
+
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+}
+
+.el-form .el-form-item__label {
+ font-weight: 700;
+}
+.el-dialog:not(.is-fullscreen) {
+ margin-top: 6vh !important;
+}
+
+.el-dialog.scrollbar .el-dialog__body {
+ overflow: auto;
+ overflow-x: hidden;
+ max-height: 70vh;
+ padding: 10px 20px 0;
+}
+
+.el-table {
+ .el-table__header-wrapper,
+ .el-table__fixed-header-wrapper {
+ th {
+ word-break: break-word;
+ background-color: $table-header-bg !important;
+ color: $table-header-text-color;
+ height: 40px !important;
+ font-size: 13px;
+ }
+ }
+ .el-table__body-wrapper {
+ .el-button [class*='el-icon-'] + span {
+ margin-left: 1px;
+ }
+ }
+}
+
+/** 表单布局 **/
+.form-header {
+ font-size: 15px;
+ color: #6379bb;
+ border-bottom: 1px solid #ddd;
+ margin: 8px 10px 25px 10px;
+ padding-bottom: 5px;
+}
+
+/** 表格布局 **/
+.pagination-container {
+ // position: relative;
+ height: 25px;
+ margin-bottom: 10px;
+ margin-top: 15px;
+ padding: 10px 20px !important;
+}
+
+/* tree border */
+.tree-border {
+ margin-top: 5px;
+ border: 1px solid #e5e6e7;
+ background: #ffffff none;
+ border-radius: 4px;
+ width: 100%;
+}
+
+.pagination-container .el-pagination {
+ //right: 0;
+ //position: absolute;
+}
+
+@media (max-width: 768px) {
+ .pagination-container .el-pagination > .el-pagination__jump {
+ display: none !important;
+ }
+ .pagination-container .el-pagination > .el-pagination__sizes {
+ display: none !important;
+ }
+}
+
+.el-table .fixed-width .el-button--small {
+ padding-left: 0;
+ padding-right: 0;
+ width: inherit;
+}
+
+/** 表格更多操作下拉样式 */
+.el-table .el-dropdown-link {
+ cursor: pointer;
+ color: #409eff;
+ margin-left: 10px;
+}
+
+.el-table .el-dropdown,
+.el-icon-arrow-down {
+ font-size: 12px;
+}
+
+.el-tree-node__content > .el-checkbox {
+ margin-right: 8px;
+}
+
+.list-group-striped > .list-group-item {
+ border-left: 0;
+ border-right: 0;
+ border-radius: 0;
+ padding-left: 0;
+ padding-right: 0;
+}
+
+.list-group {
+ padding-left: 0px;
+ list-style: none;
+}
+
+.list-group-item {
+ border-bottom: 1px solid #e7eaec;
+ border-top: 1px solid #e7eaec;
+ margin-bottom: -1px;
+ padding: 11px 0px;
+ font-size: 13px;
+}
+
+.pull-right {
+ float: right !important;
+}
+
+.el-card__header {
+ padding: 14px 15px 7px !important;
+ min-height: 40px;
+}
+
+.el-card__body {
+ padding: 15px 20px 20px 20px !important;
+}
+
+.card-box {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-bottom: 10px;
+}
+
+/* button color */
+.el-button--cyan.is-active,
+.el-button--cyan:active {
+ background: #20b2aa;
+ border-color: #20b2aa;
+ color: #ffffff;
+}
+
+.el-button--cyan:focus,
+.el-button--cyan:hover {
+ background: #48d1cc;
+ border-color: #48d1cc;
+ color: #ffffff;
+}
+
+.el-button--cyan {
+ background-color: #20b2aa;
+ border-color: #20b2aa;
+ color: #ffffff;
+}
+
+/* text color */
+.text-navy {
+ color: #1ab394;
+}
+
+.text-primary {
+ color: inherit;
+}
+
+.text-success {
+ color: #1c84c6;
+}
+
+.text-info {
+ color: #23c6c8;
+}
+
+.text-warning {
+ color: #f8ac59;
+}
+
+.text-danger {
+ color: #ed5565;
+}
+
+.text-muted {
+ color: #888888;
+}
+
+/* image */
+.img-circle {
+ border-radius: 50%;
+}
+
+.img-lg {
+ width: 120px;
+ height: 120px;
+}
+
+.avatar-upload-preview {
+ position: absolute;
+ top: 50%;
+ transform: translate(50%, -50%);
+ width: 200px;
+ height: 200px;
+ border-radius: 50%;
+ box-shadow: 0 0 4px #ccc;
+ overflow: hidden;
+}
+
+/* 拖拽列样式 */
+.sortable-ghost {
+ opacity: 0.8;
+ color: #fff !important;
+ background: #42b983 !important;
+}
+
+/* 表格右侧工具栏样式 */
+.top-right-btn {
+ margin-left: auto;
+}
diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss
new file mode 100644
index 0000000..d85da55
--- /dev/null
+++ b/src/assets/styles/sidebar.scss
@@ -0,0 +1,232 @@
+#app {
+ .main-container {
+ height: 100%;
+ transition: margin-left 0.28s;
+ margin-left: $base-sidebar-width;
+ position: relative;
+ }
+
+ .sidebarHide {
+ margin-left: 0 !important;
+ }
+
+ .sidebar-container {
+ -webkit-transition: width 0.28s;
+ transition: width 0.28s;
+ width: $base-sidebar-width !important;
+ background-color: $base-menu-background;
+ height: 100%;
+ position: fixed;
+ font-size: 0;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1001;
+ overflow: hidden;
+ -webkit-box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+ box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+
+ // reset element-ui css
+ .horizontal-collapse-transition {
+ transition:
+ 0s width ease-in-out,
+ 0s padding-left ease-in-out,
+ 0s padding-right ease-in-out;
+ }
+
+ .scrollbar-wrapper {
+ overflow-x: hidden !important;
+ }
+
+ .el-scrollbar__bar.is-vertical {
+ right: 0;
+ }
+
+ .el-scrollbar {
+ height: 100%;
+ }
+
+ &.has-logo {
+ .el-scrollbar {
+ height: calc(100% - 50px);
+ }
+ }
+
+ .is-horizontal {
+ display: none;
+ }
+
+ a {
+ display: inline-block;
+ width: 100%;
+ overflow: hidden;
+ }
+
+ .svg-icon {
+ margin-right: 16px;
+ }
+
+ .el-menu {
+ border: none;
+ height: 100%;
+ width: 100% !important;
+ }
+
+ .el-menu-item,
+ .menu-title {
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ white-space: nowrap !important;
+ }
+
+ .el-menu-item .el-menu-tooltip__trigger {
+ display: inline-block !important;
+ }
+
+ // menu hover
+ .theme-dark .sub-menu-title-noDropdown,
+ .theme-dark .el-sub-menu__title {
+ &:hover {
+ background-color: $base-sub-menu-title-hover !important;
+ }
+ }
+ .sub-menu-title-noDropdown,
+ .el-sub-menu__title {
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.05) !important;
+ }
+ }
+
+ & .theme-dark .is-active > .el-sub-menu__title {
+ color: $base-menu-color-active !important;
+ }
+
+ & .nest-menu .el-sub-menu > .el-sub-menu__title,
+ & .el-sub-menu .el-menu-item {
+ min-width: $base-sidebar-width !important;
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.1) !important;
+ }
+ }
+
+ & .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
+ & .theme-dark .el-sub-menu .el-menu-item {
+ background-color: $base-sub-menu-background !important;
+
+ &:hover {
+ background-color: $base-sub-menu-hover !important;
+ }
+ }
+
+ & .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
+ & .theme-dark .el-menu-item {
+ &:hover {
+ // you can use $sub-menuHover
+ background-color: $base-menu-hover !important;
+ }
+ }
+ & .nest-menu .el-sub-menu > .el-sub-menu__title,
+ & .el-menu-item {
+ &:hover {
+ // you can use $sub-menuHover
+ background-color: rgba(0, 0, 0, 0.04) !important;
+ }
+ }
+ }
+
+ .hideSidebar {
+ .sidebar-container {
+ width: 54px !important;
+ }
+
+ .main-container {
+ margin-left: 54px;
+ }
+
+ .sub-menu-title-noDropdown {
+ padding: 0 !important;
+ position: relative;
+
+ .el-tooltip {
+ padding: 0 !important;
+
+ .svg-icon {
+ margin-left: 20px;
+ }
+ }
+ }
+
+ .el-sub-menu {
+ overflow: hidden;
+
+ & > .el-sub-menu__title {
+ padding: 0 !important;
+
+ .svg-icon {
+ margin-left: 20px;
+ }
+ }
+ }
+
+ .el-menu--collapse {
+ .el-sub-menu {
+ & > .el-sub-menu__title {
+ & > span {
+ height: 0;
+ width: 0;
+ overflow: hidden;
+ visibility: hidden;
+ display: inline-block;
+ }
+ & > i {
+ height: 0;
+ width: 0;
+ overflow: hidden;
+ visibility: hidden;
+ display: inline-block;
+ }
+ }
+ }
+ }
+ }
+
+ .el-menu--collapse .el-menu .el-sub-menu {
+ min-width: $base-sidebar-width !important;
+ }
+
+ // mobile responsive
+ .mobile {
+ .main-container {
+ margin-left: 0px;
+ }
+
+ .sidebar-container {
+ transition: transform 0.28s;
+ width: $base-sidebar-width !important;
+ }
+
+ &.hideSidebar {
+ .sidebar-container {
+ pointer-events: none;
+ transition-duration: 0.3s;
+ transform: translate3d(-$base-sidebar-width, 0, 0);
+ }
+ }
+ }
+
+ .withoutAnimation {
+ .main-container,
+ .sidebar-container {
+ transition: none;
+ }
+ }
+}
+
+// when menu collapsed
+.el-menu--vertical {
+ & > .el-menu {
+ .svg-icon {
+ margin-right: 16px;
+ }
+ }
+}
diff --git a/src/assets/styles/transition.scss b/src/assets/styles/transition.scss
new file mode 100644
index 0000000..468ad3c
--- /dev/null
+++ b/src/assets/styles/transition.scss
@@ -0,0 +1,49 @@
+// global transition css
+
+/* fade */
+.fade-enter-active,
+.fade-leave-active {
+ transition: opacity 0.28s;
+}
+
+.fade-enter,
+.fade-leave-active {
+ opacity: 0;
+}
+
+/* fade-transform */
+.fade-transform--move,
+.fade-transform-leave-active,
+.fade-transform-enter-active {
+ transition: all 0.5s;
+}
+
+.fade-transform-enter {
+ opacity: 0;
+ transform: translateX(-30px);
+}
+
+.fade-transform-leave-to {
+ opacity: 0;
+ transform: translateX(30px);
+}
+
+/* breadcrumb transition */
+.breadcrumb-enter-active,
+.breadcrumb-leave-active {
+ transition: all 0.5s;
+}
+
+.breadcrumb-enter,
+.breadcrumb-leave-active {
+ opacity: 0;
+ transform: translateX(20px);
+}
+
+.breadcrumb-move {
+ transition: all 0.5s;
+}
+
+.breadcrumb-leave-active {
+ position: absolute;
+}
diff --git a/src/assets/styles/variables.module.scss b/src/assets/styles/variables.module.scss
new file mode 100644
index 0000000..92fc34d
--- /dev/null
+++ b/src/assets/styles/variables.module.scss
@@ -0,0 +1,121 @@
+// 全局SCSS变量
+:root {
+ --menuBg: #304156;
+ --menuColor: #bfcbd9;
+ --menuActiveText: #f4f4f5;
+ --menuHover: #263445;
+
+ --subMenuBg: #1f2d3d;
+ --subMenuActiveText: #f4f4f5;
+ --subMenuHover: #001528;
+ --subMenuTitleHover: #293444;
+
+ --fixedHeaderBg: #ffffff;
+ --tableHeaderBg: #f8f8f9;
+ --tableHeaderTextColor: #515a6e;
+
+ // 工作流
+ --bpmn-panel-border: #eeeeee;
+ --bpmn-panel-box-shadow: #cccccc;
+ --bpmn-panel-bar-background-color: #f5f7fa;
+
+ // ele
+ --brder-color: #e8e8e8
+}
+html.dark {
+ --menuBg: #1d1e1f;
+ --menuColor: #bfcbd9;
+ --menuActiveText: #f4f4f5;
+ --menuHover: #171819;
+
+ --subMenuBg: #1d1e1f;
+ --subMenuActiveText: #1d1e1f;
+ --subMenuHover: #171819;
+ --subMenuTitleHover: #171819;
+
+ --fixedHeaderBg: #171819;
+ --tableHeaderBg: var(--el-bg-color);
+ --tableHeaderTextColor: var(--el-text-color);
+
+ // 覆盖ele 高亮当前行的标准暗色
+ .el-tree-node__content {
+ --el-color-primary-light-9: #262727;
+ }
+ // vxe-table 主题
+ --vxe-font-color: #98989E;
+ --vxe-primary-color: #2C7ECF;
+ --vxe-icon-background-color: #98989E;
+ --vxe-table-font-color: #98989E;
+ --vxe-table-resizable-color: #95969a;
+ --vxe-table-header-background-color: #28282A;
+ --vxe-table-body-background-color: #151518;
+ --vxe-table-background-color: #4a5663;
+ --vxe-table-border-width: 1px;
+ --vxe-table-border-color: #37373A;
+ --vxe-toolbar-background-color: #37373A;
+
+ // 工作流
+ --bpmn-panel-border: #37373A;
+ --bpmn-panel-box-shadow: #37373A;
+ --bpmn-panel-bar-background-color: #37373A;
+
+ // ele
+ --brder-color: #37373A
+}
+
+// base color
+$blue: #324157;
+$light-blue: #3a71a8;
+$red: #c03639;
+$pink: #e65d6e;
+$green: #30b08f;
+$tiffany: #4ab7bd;
+$yellow: #fec171;
+$panGreen: #30b08f;
+
+// 默认菜单主题风格
+$base-menu-color: var(--menuColor);
+$base-menu-hover: var(--menuHover);
+$base-menu-color-active: var(--menuActiveText);
+$base-menu-background: var(--menuBg);
+$base-logo-title-color: #ffffff;
+
+$base-menu-light-color: rgba(0, 0, 0, 0.7);
+$base-menu-light-background: #ffffff;
+$base-logo-light-title-color: #001529;
+
+$base-sub-menu-background: var(--subMenuBg);
+$base-sub-menu-hover: var(--subMenuHover);
+$base-sub-menu-title-hover: var(--subMenuTitleHover);
+// 表单头背景色和标题颜色
+$fixed-header-bg: var(--fixedHeaderBg);
+$table-header-bg: var(--tableHeaderBg);
+$table-header-text-color: var(--tableHeaderTextColor);
+
+$--color-primary: #409eff;
+$--color-success: #67c23a;
+$--color-warning: #e6a23c;
+$--color-danger: #f56c6c;
+$--color-info: #909399;
+
+$base-sidebar-width: 200px;
+
+// the :export directive is the magic sauce for webpack
+// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
+:export {
+ menuColor: $base-menu-color;
+ menuLightColor: $base-menu-light-color;
+ menuColorActive: $base-menu-color-active;
+ menuBackground: $base-menu-background;
+ menuLightBackground: $base-menu-light-background;
+ subMenuBackground: $base-sub-menu-background;
+ subMenuHover: $base-sub-menu-hover;
+ sideBarWidth: $base-sidebar-width;
+ logoTitleColor: $base-logo-title-color;
+ logoLightTitleColor: $base-logo-light-title-color;
+ primaryColor: $--color-primary;
+ successColor: $--color-success;
+ dangerColor: $--color-danger;
+ infoColor: $--color-info;
+ warningColor: $--color-warning;
+}
diff --git a/src/bpmn/assets/defaultXML.ts b/src/bpmn/assets/defaultXML.ts
new file mode 100644
index 0000000..dff0349
--- /dev/null
+++ b/src/bpmn/assets/defaultXML.ts
@@ -0,0 +1,23 @@
+function generateRandomValue() {
+ // 生成一个随机数
+ const randomValue = Math.random().toString(36).slice(2, 12);
+ return `Process_${randomValue}`;
+}
+
+const cartage: string = 'default';
+export default `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/bpmn/assets/lang/zh.ts b/src/bpmn/assets/lang/zh.ts
new file mode 100644
index 0000000..ee0c5de
--- /dev/null
+++ b/src/bpmn/assets/lang/zh.ts
@@ -0,0 +1,126 @@
+export const NodeName = {
+ 'bpmn:Process': '流程',
+ 'bpmn:StartEvent': '开始事件',
+ 'bpmn:IntermediateThrowEvent': '中间事件',
+ 'bpmn:Task': '任务',
+ 'bpmn:SendTask': '发送任务',
+ 'bpmn:ReceiveTask': '接收任务',
+ 'bpmn:UserTask': '用户任务',
+ 'bpmn:ManualTask': '手工任务',
+ 'bpmn:BusinessRuleTask': '业务规则任务',
+ 'bpmn:ServiceTask': '服务任务',
+ 'bpmn:ScriptTask': '脚本任务',
+ 'bpmn:EndEvent': '结束事件',
+ 'bpmn:SequenceFlow': '流程线',
+ 'bpmn:ExclusiveGateway': '互斥网关',
+ 'bpmn:ParallelGateway': '并行网关',
+ 'bpmn:InclusiveGateway': '相容网关',
+ 'bpmn:ComplexGateway': '复杂网关',
+ 'bpmn:EventBasedGateway': '事件网关',
+ 'bpmn:Participant': '池/参与者',
+ 'bpmn:SubProcess': '子流程',
+ 'bpmn:DataObjectReference': '数据对象引用',
+ 'bpmn:DataStoreReference': '数据存储引用',
+ 'bpmn:Group': '组'
+};
+
+export default {
+ 'Activate hand tool': '启动手动工具',
+ 'Activate lasso tool': '启动 Lasso 工具',
+ 'Activate create/remove space tool': '启动创建/删除空间工具',
+ 'Activate global connect tool': '启动全局连接工具',
+ 'Ad-hoc': 'Ad-hoc',
+ 'Add lane above': '在上方添加泳道',
+ 'Add lane below': '在下方添加泳道',
+ 'Business rule task': '规则任务',
+ 'Call activity': '引用流程',
+ 'Compensation end event': '结束补偿事件',
+ 'Compensation intermediate throw event': '中间补偿抛出事件',
+ 'Complex gateway': '复杂网关',
+ 'Conditional intermediate catch event': '中间条件捕获事件',
+ 'Conditional start event (non-interrupting)': '条件启动事件 (非中断)',
+ 'Conditional start event': '条件启动事件',
+ 'Connect using association': '文本关联',
+ 'Connect using sequence/message flow or association': '消息关联',
+ 'Change element': '更改元素',
+ 'Change type': '更改类型',
+ 'Create data object reference': '创建数据对象引用',
+ 'Create data store reference': '创建数据存储引用',
+ 'Create expanded sub-process': '创建可折叠子流程',
+ 'Create pool/participant': '创建池/参与者',
+ 'Collection': '集合',
+ 'Connect using data input association': '数据输入关联',
+ 'Data store reference': '数据存储引用',
+ 'Data object reference': '数据对象引用',
+ 'Divide into two lanes': '分成两个泳道',
+ 'Divide into three lanes': '分成三个泳道',
+ 'End event': '结束事件',
+ 'Error end event': '结束错误事件',
+ 'Escalation end event': '结束升级事件',
+ 'Escalation intermediate throw event': '中间升级抛出事件',
+ 'Event sub-process': '事件子流程',
+ 'Event-based gateway': '事件网关',
+ 'Exclusive gateway': '互斥网关',
+ 'Empty pool/participant (removes content)': '清空池/参与者 (删除内容)',
+ 'Empty pool/participant': '清空池/参与者',
+ 'Expanded pool/participant': '展开池/参与者',
+ 'Inclusive gateway': '相容网关',
+ 'Intermediate throw event': '中间抛出事件',
+ 'Loop': '循环',
+ 'Link intermediate catch event': '中间链接捕获事件',
+ 'Link intermediate throw event': '中间链接抛出事件',
+ 'Manual task': '手动任务',
+ 'Message end event': '结束消息事件',
+ 'Message intermediate catch event': '中间消息捕获事件',
+ 'Message intermediate throw event': '中间消息抛出事件',
+ 'Message start event': '消息启动事件',
+ 'Parallel gateway': '并行网关',
+ 'Parallel multi-instance': '并行多实例',
+ 'Participant multiplicity': '参与者多重性',
+ 'Receive task': '接受任务',
+ 'Remove': '移除',
+ 'Script task': '脚本任务',
+ 'Send task': '发送任务',
+ 'Sequential multi-instance': '串行多实例',
+ 'Service task': '服务任务',
+ 'Signal end event': '结束信号事件',
+ 'Signal intermediate catch event': '中间信号捕获事件',
+ 'Signal intermediate throw event': '中间信号抛出事件',
+ 'Signal start event (non-interrupting)': '信号启动事件 (非中断)',
+ 'Signal start event': '信号启动事件',
+ 'Start event': '开始事件',
+ 'Sub-process (collapsed)': '可折叠子流程',
+ 'Sub-process (expanded)': '可展开子流程',
+ 'Sub rocess': '子流程',
+ 'Task': '任务',
+ 'Transaction': '事务',
+ 'Terminate end event': '终止边界事件',
+ 'Timer intermediate catch event': '中间定时捕获事件',
+ 'Timer start event (non-interrupting)': '定时启动事件 (非中断)',
+ 'Timer start event': '定时启动事件',
+ 'User task': '用户任务',
+ 'Create start event': '创建开始事件',
+ 'Create gateway': '创建网关',
+ 'Create intermediate/boundary event': '创建中间/边界事件',
+ 'Create end event': '创建结束事件',
+ 'Create group': '创建组',
+ 'Create startEvent': '开始节点',
+ 'Create endEvent': '结束节点',
+ 'Create exclusiveGateway': '互斥网关',
+ 'Create parallelGateway': '并行网关',
+ 'Create task': '任务节点',
+ 'Create userTask': '用户任务节点',
+ 'Condition type': '条件类型',
+ 'Append end event': '追加结束事件节点',
+ 'Append gateway': '追加网关节点',
+ 'Append task': '追加任务',
+ 'Append user task': '追加用户任务节点',
+ 'Append text annotation': '追加文本注释',
+ 'Append intermediate/boundary event': '追加中间或边界事件',
+ 'Append receive task': '追加接收任务节点',
+ 'Append message intermediate catch event': '追加中间消息捕获事件',
+ 'Append timer intermediate catch event': '追加中间定时捕获事件',
+ 'Append conditional intermediate catch event': '追加中间条件捕获事件',
+ 'Append signal intermediate catch event': '追加中间信号捕获事件',
+ 'flow elements must be children of pools/participants': '流程元素必须是池/参与者的子元素'
+};
diff --git a/src/bpmn/assets/moddle/flowable.ts b/src/bpmn/assets/moddle/flowable.ts
new file mode 100644
index 0000000..de959a6
--- /dev/null
+++ b/src/bpmn/assets/moddle/flowable.ts
@@ -0,0 +1,1250 @@
+export default {
+ 'name': 'Flowable',
+ 'uri': 'http://flowable.org/bpmn',
+ 'prefix': 'flowable',
+ 'xml': {
+ 'tagAlias': 'lowerCase'
+ },
+ 'associations': [],
+ 'types': [
+ {
+ 'name': 'flowable:extCandidateUsers',
+ 'isAbstract': true,
+ 'extends': [],
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['*']
+ },
+ 'properties': [
+ {
+ 'name': 'body',
+ 'type': 'String',
+ 'isBody': true
+ }
+ ]
+ },
+ {
+ 'name': 'flowable:extAssignee',
+ 'isAbstract': true,
+ 'extends': [],
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['*']
+ },
+ 'properties': [
+ {
+ 'name': 'body',
+ 'type': 'String',
+ 'isBody': true
+ }
+ ]
+ },
+ {
+ 'name': 'flowable:property',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'id',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'name',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'value',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'flowable:properties',
+ 'isAbstract': true,
+ 'extends': [],
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['*']
+ },
+ 'properties': [
+ {
+ 'name': 'values',
+ 'type': 'flowable:property',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'InOutBinding',
+ 'superClass': ['Element'],
+ 'isAbstract': true,
+ 'properties': [
+ {
+ 'name': 'source',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'sourceExpression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'target',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'businessKey',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'local',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': false
+ },
+ {
+ 'name': 'variables',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'In',
+ 'superClass': ['InOutBinding'],
+ 'meta': {
+ 'allowedIn': ['bpmn:CallActivity']
+ }
+ },
+ {
+ 'name': 'Out',
+ 'superClass': ['InOutBinding'],
+ 'meta': {
+ 'allowedIn': ['bpmn:CallActivity']
+ }
+ },
+ {
+ 'name': 'AsyncCapable',
+ 'isAbstract': true,
+ 'extends': ['bpmn:Activity', 'bpmn:Gateway', 'bpmn:Event'],
+ 'properties': [
+ {
+ 'name': 'async',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': false
+ },
+ {
+ 'name': 'asyncBefore',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': false
+ },
+ {
+ 'name': 'asyncAfter',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': false
+ },
+ {
+ 'name': 'exclusive',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': true
+ }
+ ]
+ },
+ {
+ 'name': 'flowable:in',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'source',
+ 'type': 'string',
+ 'isAttr': true
+ },
+ {
+ 'name': 'target',
+ 'type': 'string',
+ 'isAttr': true
+ }
+ ]
+ },
+ {
+ 'name': 'flowable:out',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'source',
+ 'type': 'string',
+ 'isAttr': true
+ },
+ {
+ 'name': 'target',
+ 'type': 'string',
+ 'isAttr': true
+ }
+ ]
+ },
+ {
+ 'name': 'BoundaryEvent',
+ 'superClass': ['CatchEvent'],
+ 'properties': [
+ {
+ 'name': 'cancelActivity',
+ 'default': true,
+ 'isAttr': true,
+ 'type': 'Boolean'
+ },
+ {
+ 'name': 'attachedToRef',
+ 'type': 'Activity',
+ 'isAttr': true,
+ 'isReference': true
+ }
+ ]
+ },
+ {
+ 'name': 'JobPriorized',
+ 'isAbstract': true,
+ 'extends': ['bpmn:Process', 'flowable:AsyncCapable'],
+ 'properties': [
+ {
+ 'name': 'jobPriority',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'SignalEventDefinition',
+ 'isAbstract': true,
+ 'extends': ['bpmn:SignalEventDefinition'],
+ 'properties': [
+ {
+ 'name': 'async',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': false
+ }
+ ]
+ },
+ {
+ 'name': 'ErrorEventDefinition',
+ 'isAbstract': true,
+ 'extends': ['bpmn:ErrorEventDefinition'],
+ 'properties': [
+ {
+ 'name': 'errorCodeVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'errorMessageVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Error',
+ 'isAbstract': true,
+ 'extends': ['bpmn:Error'],
+ 'properties': [
+ {
+ 'name': 'flowable:errorMessage',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'PotentialStarter',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'resourceAssignmentExpression',
+ 'type': 'bpmn:ResourceAssignmentExpression'
+ }
+ ]
+ },
+ {
+ 'name': 'UserTask',
+ 'isAbstract': true,
+ 'extends': ['bpmn:UserTask'],
+ 'properties': [
+ {
+ 'name': 'timerEventDefinition',
+ 'type': 'Expression'
+ },
+ {
+ 'name': 'multiInstanceLoopCharacteristics',
+ 'type': 'MultiInstanceLoopCharacteristics'
+ }
+ ]
+ },
+ {
+ 'name': 'StartEvent',
+ 'isAbstract': true,
+ 'extends': ['bpmn:StartEvent'],
+ 'properties': [
+ {
+ 'name': 'timerEventDefinition',
+ 'type': 'Expression'
+ }
+ ]
+ },
+ {
+ 'name': 'FormSupported',
+ 'isAbstract': true,
+ 'extends': ['bpmn:StartEvent', 'bpmn:UserTask'],
+ 'properties': [
+ {
+ 'name': 'formHandlerClass',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'formKey',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'TemplateSupported',
+ 'isAbstract': true,
+ 'extends': ['bpmn:Process', 'bpmn:FlowElement'],
+ 'properties': [
+ {
+ 'name': 'modelerTemplate',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Initiator',
+ 'isAbstract': true,
+ 'extends': ['bpmn:StartEvent'],
+ 'properties': [
+ {
+ 'name': 'initiator',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'ScriptTask',
+ 'isAbstract': true,
+ 'extends': ['bpmn:ScriptTask'],
+ 'properties': [
+ {
+ 'name': 'resultVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'resource',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Process',
+ 'isAbstract': true,
+ 'extends': ['bpmn:Process'],
+ 'properties': [
+ {
+ 'name': 'candidateStarterGroups',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'candidateStarterUsers',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'versionTag',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'historyTimeToLive',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'isStartableInTasklist',
+ 'isAttr': true,
+ 'type': 'Boolean',
+ 'default': true
+ }
+ ]
+ },
+ {
+ 'name': 'EscalationEventDefinition',
+ 'isAbstract': true,
+ 'extends': ['bpmn:EscalationEventDefinition'],
+ 'properties': [
+ {
+ 'name': 'escalationCodeVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'FormalExpression',
+ 'isAbstract': true,
+ 'extends': ['bpmn:FormalExpression'],
+ 'properties': [
+ {
+ 'name': 'resource',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Assignable',
+ 'extends': ['bpmn:UserTask'],
+ 'properties': [
+ {
+ 'name': 'candidateGroups',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'dueDate',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'followUpDate',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'priority',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'CallActivity',
+ 'extends': ['bpmn:CallActivity'],
+ 'properties': [
+ {
+ 'name': 'calledElementBinding',
+ 'isAttr': true,
+ 'type': 'String',
+ 'default': 'latest'
+ },
+ {
+ 'name': 'calledElementVersion',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'calledElementVersionTag',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'calledElementTenantId',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'caseRef',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'caseBinding',
+ 'isAttr': true,
+ 'type': 'String',
+ 'default': 'latest'
+ },
+ {
+ 'name': 'caseVersion',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'caseTenantId',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'variableMappingClass',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'variableMappingDelegateExpression',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'ServiceTaskLike',
+ 'extends': ['bpmn:ServiceTask', 'bpmn:BusinessRuleTask', 'bpmn:SendTask', 'bpmn:MessageEventDefinition'],
+ 'properties': [
+ {
+ 'name': 'expression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'class',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'delegateExpression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'resultVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'ExclusiveGateway',
+ 'isAbstract': true,
+ 'extends': ['bpmn:ExclusiveGateway'],
+ 'properties': [
+ {
+ 'name': 'serviceClass',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'DmnCapable',
+ 'extends': ['bpmn:BusinessRuleTask'],
+ 'properties': [
+ {
+ 'name': 'decisionRef',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'decisionRefBinding',
+ 'isAttr': true,
+ 'type': 'String',
+ 'default': 'latest'
+ },
+ {
+ 'name': 'decisionRefVersion',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'mapDecisionResult',
+ 'isAttr': true,
+ 'type': 'String',
+ 'default': 'resultList'
+ },
+ {
+ 'name': 'decisionRefTenantId',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'ExternalCapable',
+ 'extends': ['flowable:ServiceTaskLike'],
+ 'properties': [
+ {
+ 'name': 'type',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'topic',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'TaskPriorized',
+ 'extends': ['bpmn:Process', 'flowable:ExternalCapable'],
+ 'properties': [
+ {
+ 'name': 'taskPriority',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Properties',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['*']
+ },
+ 'properties': [
+ {
+ 'name': 'values',
+ 'type': 'Property',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'Property',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'id',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'name',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'value',
+ 'type': 'String',
+ 'isAttr': true
+ }
+ ]
+ },
+ {
+ 'name': 'Connector',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['flowable:ServiceTaskLike']
+ },
+ 'properties': [
+ {
+ 'name': 'inputOutput',
+ 'type': 'InputOutput'
+ },
+ {
+ 'name': 'connectorId',
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'InputOutput',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['bpmn:FlowNode', 'flowable:Connector']
+ },
+ 'properties': [
+ {
+ 'name': 'inputOutput',
+ 'type': 'InputOutput'
+ },
+ {
+ 'name': 'connectorId',
+ 'type': 'String'
+ },
+ {
+ 'name': 'inputParameters',
+ 'isMany': true,
+ 'type': 'InputParameter'
+ },
+ {
+ 'name': 'outputParameters',
+ 'isMany': true,
+ 'type': 'OutputParameter'
+ }
+ ]
+ },
+ {
+ 'name': 'InputOutputParameter',
+ 'properties': [
+ {
+ 'name': 'name',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'value',
+ 'isBody': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'definition',
+ 'type': 'InputOutputParameterDefinition'
+ }
+ ]
+ },
+ {
+ 'name': 'InputOutputParameterDefinition',
+ 'isAbstract': true
+ },
+ {
+ 'name': 'List',
+ 'superClass': ['InputOutputParameterDefinition'],
+ 'properties': [
+ {
+ 'name': 'items',
+ 'isMany': true,
+ 'type': 'InputOutputParameterDefinition'
+ }
+ ]
+ },
+ {
+ 'name': 'Map',
+ 'superClass': ['InputOutputParameterDefinition'],
+ 'properties': [
+ {
+ 'name': 'entries',
+ 'isMany': true,
+ 'type': 'Entry'
+ }
+ ]
+ },
+ {
+ 'name': 'Entry',
+ 'properties': [
+ {
+ 'name': 'key',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'value',
+ 'isBody': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'definition',
+ 'type': 'InputOutputParameterDefinition'
+ }
+ ]
+ },
+ {
+ 'name': 'Value',
+ 'superClass': ['InputOutputParameterDefinition'],
+ 'properties': [
+ {
+ 'name': 'id',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'name',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'value',
+ 'isBody': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Script',
+ 'superClass': ['InputOutputParameterDefinition'],
+ 'properties': [
+ {
+ 'name': 'scriptFormat',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'resource',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'value',
+ 'isBody': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'Field',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['flowable:ServiceTaskLike', 'flowable:ExecutionListener', 'flowable:TaskListener']
+ },
+ 'properties': [
+ {
+ 'name': 'name',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'expression',
+ 'isAttr': true,
+ 'type': 'expression'
+ },
+ {
+ 'name': 'string',
+ 'type': 'string'
+ },
+ {
+ 'name': 'stringValue',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'string',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['flowable:Field']
+ },
+ 'properties': [
+ {
+ 'name': 'body',
+ 'isBody': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'expression',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['flowable:Field']
+ },
+ 'properties': [
+ {
+ 'name': 'body',
+ 'isBody': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'InputParameter',
+ 'superClass': ['InputOutputParameter']
+ },
+ {
+ 'name': 'OutputParameter',
+ 'superClass': ['InputOutputParameter']
+ },
+ {
+ 'name': 'Collectable',
+ 'isAbstract': true,
+ 'extends': ['bpmn:MultiInstanceLoopCharacteristics'],
+ 'superClass': ['flowable:AsyncCapable'],
+ 'properties': [
+ {
+ 'name': 'collection',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'elementVariable',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'SequenceFlow',
+ 'superClass': ['FlowElement'],
+ 'properties': [
+ {
+ 'name': 'isImmediate',
+ 'isAttr': true,
+ 'type': 'Boolean'
+ },
+ {
+ 'name': 'conditionExpression',
+ 'type': 'Expression'
+ },
+ {
+ 'name': 'sourceRef',
+ 'type': 'FlowNode',
+ 'isAttr': true,
+ 'isReference': true
+ },
+ {
+ 'name': 'targetRef',
+ 'type': 'FlowNode',
+ 'isAttr': true,
+ 'isReference': true
+ }
+ ]
+ },
+ {
+ 'name': 'MultiInstanceLoopCharacteristics',
+ 'superClass': ['LoopCharacteristics'],
+ 'properties': [
+ {
+ 'name': 'isSequential',
+ 'default': false,
+ 'isAttr': true,
+ 'type': 'Boolean'
+ },
+ {
+ 'name': 'behavior',
+ 'type': 'MultiInstanceBehavior',
+ 'default': 'All',
+ 'isAttr': true
+ },
+ {
+ 'name': 'loopCardinality',
+ 'type': 'Expression',
+ 'xml': {
+ 'serialize': 'xsi:type'
+ }
+ },
+ {
+ 'name': 'loopDataInputRef',
+ 'type': 'ItemAwareElement',
+ 'isReference': true
+ },
+ {
+ 'name': 'loopDataOutputRef',
+ 'type': 'ItemAwareElement',
+ 'isReference': true
+ },
+ {
+ 'name': 'inputDataItem',
+ 'type': 'DataInput',
+ 'xml': {
+ 'serialize': 'property'
+ }
+ },
+ {
+ 'name': 'outputDataItem',
+ 'type': 'DataOutput',
+ 'xml': {
+ 'serialize': 'property'
+ }
+ },
+ {
+ 'name': 'complexBehaviorDefinition',
+ 'type': 'ComplexBehaviorDefinition',
+ 'isMany': true
+ },
+ {
+ 'name': 'completionCondition',
+ 'type': 'Expression',
+ 'xml': {
+ 'serialize': 'xsi:type'
+ }
+ },
+ {
+ 'name': 'oneBehaviorEventRef',
+ 'type': 'EventDefinition',
+ 'isAttr': true,
+ 'isReference': true
+ },
+ {
+ 'name': 'noneBehaviorEventRef',
+ 'type': 'EventDefinition',
+ 'isAttr': true,
+ 'isReference': true
+ }
+ ]
+ },
+ {
+ 'name': 'FailedJobRetryTimeCycle',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['flowable:AsyncCapable', 'bpmn:MultiInstanceLoopCharacteristics']
+ },
+ 'properties': [
+ {
+ 'name': 'body',
+ 'isBody': true,
+ 'type': 'String'
+ }
+ ]
+ },
+ {
+ 'name': 'ExecutionListener',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': [
+ 'bpmn:Task',
+ 'bpmn:ServiceTask',
+ 'bpmn:UserTask',
+ 'bpmn:BusinessRuleTask',
+ 'bpmn:ScriptTask',
+ 'bpmn:ReceiveTask',
+ 'bpmn:ManualTask',
+ 'bpmn:ExclusiveGateway',
+ 'bpmn:SequenceFlow',
+ 'bpmn:ParallelGateway',
+ 'bpmn:InclusiveGateway',
+ 'bpmn:EventBasedGateway',
+ 'bpmn:StartEvent',
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn:IntermediateThrowEvent',
+ 'bpmn:EndEvent',
+ 'bpmn:BoundaryEvent',
+ 'bpmn:CallActivity',
+ 'bpmn:SubProcess',
+ 'bpmn:Process'
+ ]
+ },
+ 'properties': [
+ {
+ 'name': 'expression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'class',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'delegateExpression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'event',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'script',
+ 'type': 'Script'
+ },
+ {
+ 'name': 'fields',
+ 'type': 'Field',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'TaskListener',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['bpmn:UserTask']
+ },
+ 'properties': [
+ {
+ 'name': 'expression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'class',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'delegateExpression',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'event',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'script',
+ 'type': 'Script'
+ },
+ {
+ 'name': 'fields',
+ 'type': 'Field',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'FormProperty',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask']
+ },
+ 'properties': [
+ {
+ 'name': 'id',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'name',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'type',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'required',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'readable',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'writable',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'variable',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'expression',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'datePattern',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'default',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'values',
+ 'type': 'Value',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'FormData',
+ 'superClass': ['Element'],
+ 'meta': {
+ 'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask']
+ },
+ 'properties': [
+ {
+ 'name': 'fields',
+ 'type': 'FormField',
+ 'isMany': true
+ },
+ {
+ 'name': 'businessKey',
+ 'type': 'String',
+ 'isAttr': true
+ }
+ ]
+ },
+ {
+ 'name': 'FormField',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'id',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'label',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'type',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'datePattern',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'defaultValue',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'properties',
+ 'type': 'Properties'
+ },
+ {
+ 'name': 'validation',
+ 'type': 'Validation'
+ },
+ {
+ 'name': 'values',
+ 'type': 'Value',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'Validation',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'constraints',
+ 'type': 'Constraint',
+ 'isMany': true
+ }
+ ]
+ },
+ {
+ 'name': 'Constraint',
+ 'superClass': ['Element'],
+ 'properties': [
+ {
+ 'name': 'name',
+ 'type': 'String',
+ 'isAttr': true
+ },
+ {
+ 'name': 'config',
+ 'type': 'String',
+ 'isAttr': true
+ }
+ ]
+ },
+ {
+ 'name': 'ConditionalEventDefinition',
+ 'isAbstract': true,
+ 'extends': ['bpmn:ConditionalEventDefinition'],
+ 'properties': [
+ {
+ 'name': 'variableName',
+ 'isAttr': true,
+ 'type': 'String'
+ },
+ {
+ 'name': 'variableEvent',
+ 'isAttr': true,
+ 'type': 'String'
+ }
+ ]
+ }
+ ],
+ 'emumerations': []
+};
diff --git a/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts b/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts
new file mode 100644
index 0000000..13ccf50
--- /dev/null
+++ b/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts
@@ -0,0 +1,138 @@
+import ContextPadProvider from 'bpmn-js/lib/features/context-pad/ContextPadProvider';
+import { Injector } from 'didi';
+import EventBus from 'diagram-js/lib/core/EventBus';
+import ContextPad from 'diagram-js/lib/features/context-pad/ContextPad';
+import Modeling from 'bpmn-js/lib/features/modeling/Modeling.js';
+import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory';
+import Connect from 'diagram-js/lib/features/connect/Connect';
+import Create from 'diagram-js/lib/features/create/Create';
+import PopupMenu from 'diagram-js/lib/features/popup-menu/PopupMenu';
+import Canvas from 'diagram-js/lib/core/Canvas';
+import Rules from 'diagram-js/lib/features/rules/Rules';
+import { Element, Shape } from 'diagram-js/lib/model/Types';
+import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory';
+import modeler from '@/store/modules/modeler';
+
+// @Description: 增强元素连线事件
+
+class CustomContextPadProvider extends ContextPadProvider {
+ private _contextPad: ContextPad;
+ private _modeling: Modeling;
+ private _elementFactory: ElementFactory;
+ private _autoPlace: any;
+ private _connect: Connect;
+ private _create: Create;
+ private _popupMenu: PopupMenu;
+ private _canvas: Canvas;
+ private _rules: Rules;
+
+ constructor(
+ config: any,
+ injector: Injector,
+ eventBus: EventBus,
+ contextPad: ContextPad,
+ modeling: Modeling,
+ elementFactory: ElementFactory,
+ connect: Connect,
+ create: Create,
+ popupMenu: PopupMenu,
+ canvas: Canvas,
+ rules: Rules,
+ translate
+ ) {
+ // @ts-expect-error 忽略异常
+ super(config, injector, eventBus, contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate);
+
+ this._contextPad = contextPad;
+ this._modeling = modeling;
+ this._elementFactory = elementFactory;
+ this._connect = connect;
+ this._create = create;
+ this._popupMenu = popupMenu;
+ this._canvas = canvas;
+ this._rules = rules;
+
+ this._autoPlace = injector.get('autoPlace', false);
+ }
+
+ getContextPadEntries(element: Element) {
+ const actions: Record = {};
+
+ const appendUserTask = (event: Event, element: Shape) => {
+ const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' });
+ this._create.start(event, shape, {
+ source: element
+ });
+ };
+
+ const appendMultiInstanceUserTask = (event: Event, element: Shape) => {
+ const store = modeler();
+ const bpmnFactory = store.getModeler().get('bpmnFactory') as BpmnFactory;
+ const businessObject = bpmnFactory.create('bpmn:UserTask', {
+ // name: '多实例用户任务',
+ isForCompensation: false
+ });
+ businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
+ // 创建 Shape
+ const shape = this._elementFactory.createShape({
+ type: 'bpmn:UserTask',
+ businessObject: businessObject
+ });
+ this._create.start(event, shape, { source: element });
+ };
+
+ const appendTask = this._autoPlace
+ ? (event, element) => {
+ const bpmnFactory: BpmnFactory | undefined = modeler().getModeler().get('bpmnFactory');
+ const businessObject = bpmnFactory.create('bpmn:UserTask', {
+ // name: '多实例用户任务',// 右键创建显示
+ isForCompensation: false
+ });
+
+ // 创建多实例属性并分配给用户任务的 loopCharacteristics
+ businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
+
+ // 创建 Shape
+ const shape = this._elementFactory.createShape({
+ type: 'bpmn:UserTask',
+ businessObject: businessObject
+ });
+
+ this._autoPlace.append(element, shape);
+ }
+ : appendMultiInstanceUserTask;
+
+ const append = this._autoPlace
+ ? (event: Event, element: Shape) => {
+ const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' });
+ this._autoPlace.append(element, shape);
+ }
+ : appendUserTask;
+
+ // // 添加创建用户任务按钮
+ actions['append.append-user-task'] = {
+ group: 'model',
+ className: 'bpmn-icon-user-task',
+ title: '用户任务',
+ action: {
+ dragstart: appendUserTask,
+ click: append
+ }
+ };
+
+ // 添加创建多实例用户任务按钮
+ actions['append.append-multi-instance-user-task'] = {
+ group: 'model',
+ className: 'bpmn-icon-user', // 你可以使用多实例用户任务的图标 bpmn-icon-user bpmn-icon-user-task
+ title: '多实例用户任务',
+ action: {
+ dragstart: appendMultiInstanceUserTask,
+ click: appendTask
+ }
+ };
+
+ return actions;
+ }
+}
+
+export default CustomContextPadProvider;
diff --git a/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts b/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts
new file mode 100644
index 0000000..8556d9b
--- /dev/null
+++ b/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts
@@ -0,0 +1,109 @@
+import { assign } from 'min-dash';
+import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider';
+import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory';
+import Create from 'diagram-js/lib/features/create/Create';
+import SpaceTool from 'diagram-js/lib/features/space-tool/SpaceTool';
+import LassoTool from 'diagram-js/lib/features/lasso-tool/LassoTool';
+import HandTool from 'diagram-js/lib/features/hand-tool/HandTool';
+import GlobalConnect from 'diagram-js/lib/features/global-connect/GlobalConnect';
+import Palette from 'diagram-js/lib/features/palette/Palette';
+import modeler from '@/store/modules/modeler';
+import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory';
+
+// @Description: 增强左侧面板
+class CustomPaletteProvider extends PaletteProvider {
+ private readonly _palette: Palette;
+ private readonly _create: Create;
+ private readonly _elementFactory: ElementFactory;
+ private readonly _spaceTool: SpaceTool;
+ private readonly _lassoTool: LassoTool;
+ private readonly _handTool: HandTool;
+ private readonly _globalConnect: GlobalConnect;
+ private readonly _translate: any;
+
+ constructor(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate) {
+ super(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate);
+ this._palette = palette;
+ this._create = create;
+ this._elementFactory = elementFactory;
+ this._spaceTool = spaceTool;
+ this._lassoTool = lassoTool;
+ this._handTool = handTool;
+ this._globalConnect = globalConnect;
+ this._translate = translate;
+ }
+
+ getPaletteEntries() {
+ const actions = {},
+ create = this._create,
+ elementFactory = this._elementFactory,
+ translate = this._translate;
+
+ function createAction(type: string, group: string, className: string, title: string, options?: object) {
+ function createListener(event) {
+ const shape = elementFactory.createShape(assign({ type: type }, options));
+ if (options) {
+ !shape.businessObject.di && (shape.businessObject.di = {});
+ shape.businessObject.di.isExpanded = (options as { [key: string]: any }).isExpanded;
+ }
+ create.start(event, shape, null);
+ }
+ const shortType = type.replace(/^bpmn:/, '');
+ return {
+ group: group,
+ className: className,
+ title: title || translate('Create {type}', { type: shortType }),
+ action: {
+ dragstart: createListener,
+ click: createListener
+ }
+ };
+ }
+
+ function createMultiInstanceUserTask(event) {
+ const bpmnFactory: BpmnFactory | undefined = modeler().getBpmnFactory();
+ // 创建一个 bpmn:UserTask
+ const userTask = bpmnFactory.create('bpmn:UserTask', {
+ // name: '多实例用户任务', // 在画板中显示字段
+ isForCompensation: false
+ });
+ // 将多实例属性分配给 bpmn:UserTask 的 loopCharacteristics
+ userTask.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics');
+ const customUserTask = elementFactory.createShape({
+ type: 'bpmn:UserTask',
+ businessObject: userTask // 分配创建的 userTask 到 businessObject
+ });
+ create.start(event, customUserTask, {});
+ }
+
+ assign(actions, {
+ 'create.parallel-gateway': createAction('bpmn:ParallelGateway', 'gateway', 'bpmn-icon-gateway-parallel', '并行网关'),
+ 'create.event-base-gateway': createAction('bpmn:EventBasedGateway', 'gateway', 'bpmn-icon-gateway-eventbased', '事件网关'),
+ // 分组线
+ 'gateway-separator': {
+ group: 'gateway',
+ separator: true
+ },
+ 'create.user-task': createAction('bpmn:UserTask', 'activity', 'bpmn-icon-user-task', '创建用户任务'),
+ 'create.multi-instance-user-task': {
+ group: 'activity',
+ type: 'bpmn:UserTask',
+ className: 'bpmn-icon-user task-multi-instance',
+ title: '创建多实例用户任务',
+ action: {
+ click: createMultiInstanceUserTask,
+ dragstart: createMultiInstanceUserTask
+ }
+ },
+ 'task-separator': {
+ group: 'activity',
+ separator: true
+ }
+ });
+ return actions;
+ }
+}
+
+CustomPaletteProvider['$inject'] = ['palette', 'create', 'elementFactory', 'spaceTool', 'lassoTool', 'handTool', 'globalConnect', 'translate'];
+
+export default CustomPaletteProvider;
diff --git a/src/bpmn/assets/module/Renderer/CustomRenderer.ts b/src/bpmn/assets/module/Renderer/CustomRenderer.ts
new file mode 100644
index 0000000..6a4eb1a
--- /dev/null
+++ b/src/bpmn/assets/module/Renderer/CustomRenderer.ts
@@ -0,0 +1,56 @@
+import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
+import {
+ append as svgAppend,
+ attr as svgAttr,
+ create as svgCreate,
+ select as svgSelect,
+ selectAll as svgSelectAll,
+ clone as svgClone,
+ clear as svgClear,
+ remove as svgRemove
+} from 'tiny-svg';
+
+const HIGH_PRIORITY = 1500;
+export default class CustomRenderer extends BaseRenderer {
+ bpmnRenderer: BaseRenderer;
+ modeling: any;
+ constructor(eventBus, bpmnRenderer, modeling) {
+ super(eventBus, HIGH_PRIORITY);
+ this.bpmnRenderer = bpmnRenderer;
+ this.modeling = modeling;
+ }
+ canRender(element) {
+ // ignore labels
+ return !element.labelTarget;
+ }
+
+ /**
+ * 自定义节点图形
+ * @param {*} parentNode 当前元素的svgNode
+ * @param {*} element
+ * @returns
+ */
+ drawShape(parentNode, element) {
+ const shape = this.bpmnRenderer.drawShape(parentNode, element);
+ const { type, width, height } = element;
+ // 开始 填充绿色
+ if (type === 'bpmn:StartEvent') {
+ svgAttr(shape, { fill: '#77DF6D' });
+ return shape;
+ }
+ if (type === 'bpmn:EndEvent') {
+ svgAttr(shape, { fill: '#EE7B77' });
+ return shape;
+ }
+ if (type === 'bpmn:UserTask') {
+ svgAttr(shape, { fill: '#A9C4F8' });
+ return shape;
+ }
+ return shape;
+ }
+
+ getShapePath(shape) {
+ return this.bpmnRenderer.getShapePath(shape);
+ }
+}
+CustomRenderer['$inject'] = ['eventBus', 'bpmnRenderer'];
diff --git a/src/bpmn/assets/module/Translate/index.ts b/src/bpmn/assets/module/Translate/index.ts
new file mode 100644
index 0000000..6b52dae
--- /dev/null
+++ b/src/bpmn/assets/module/Translate/index.ts
@@ -0,0 +1,15 @@
+import zh from '../../lang/zh';
+
+const customTranslate = (template: any, replacements: any) => {
+ replacements = replacements || {};
+ template = zh[template] || template;
+ return template.replace(/{([^}]+)}/g, function (_: any, key: any) {
+ return replacements[key] || '{' + key + '}';
+ });
+};
+
+export const translateModule = {
+ translate: ['value', customTranslate]
+};
+
+export default translateModule;
diff --git a/src/bpmn/assets/module/index.ts b/src/bpmn/assets/module/index.ts
new file mode 100644
index 0000000..55f6b9f
--- /dev/null
+++ b/src/bpmn/assets/module/index.ts
@@ -0,0 +1,17 @@
+// 翻译模块
+import TranslationModule from './Translate';
+import { ModuleDeclaration } from 'didi';
+import CustomPaletteProvider from './Palette/CustomPaletteProvider';
+import CustomRenderer from './Renderer/CustomRenderer';
+import CustomContextPadProvider from './ContextPad/CustomContextPadProvider';
+
+const Module: ModuleDeclaration[] = [
+ {
+ __init__: ['customPaletteProvider', 'customContextPadProvider', 'customRenderer'],
+ customPaletteProvider: ['type', CustomPaletteProvider],
+ customRenderer: ['type', CustomRenderer],
+ customContextPadProvider: ['type', CustomContextPadProvider]
+ },
+ TranslationModule
+];
+export default Module;
diff --git a/src/bpmn/assets/showConfig.ts b/src/bpmn/assets/showConfig.ts
new file mode 100644
index 0000000..853eb35
--- /dev/null
+++ b/src/bpmn/assets/showConfig.ts
@@ -0,0 +1,50 @@
+export default {
+ 'bpmn:EndEvent': {},
+ 'bpmn:StartEvent': {
+ initiator: true,
+ formKey: true
+ },
+ 'bpmn:UserTask': {
+ allocationType: true,
+ specifyDesc: true,
+ multipleUserAuditType: true,
+ async: true,
+ priority: true,
+ skipExpression: true,
+ dueDate: true,
+ taskListener: true,
+ executionListener: true
+ },
+ 'bpmn:ServiceTask': {
+ async: true,
+ skipExpression: true,
+ isForCompensation: true,
+ triggerable: true,
+ class: true
+ },
+ 'bpmn:ScriptTask': {
+ async: true,
+ isForCompensation: true,
+ autoStoreVariables: true
+ },
+ 'bpmn:ManualTask': {
+ async: true,
+ isForCompensation: true
+ },
+ 'bpmn:ReceiveTask': {
+ async: true,
+ isForCompensation: true
+ },
+ 'bpmn:SendTask': {
+ async: true,
+ isForCompensation: true
+ },
+ 'bpmn:BusinessRuleTask': {
+ async: true,
+ isForCompensation: true,
+ ruleVariablesInput: true,
+ rules: true,
+ resultVariable: true,
+ exclude: true
+ }
+};
diff --git a/src/bpmn/assets/style/index.scss b/src/bpmn/assets/style/index.scss
new file mode 100644
index 0000000..3c92792
--- /dev/null
+++ b/src/bpmn/assets/style/index.scss
@@ -0,0 +1,284 @@
+.djs-palette {
+ width: 300px;
+
+ .bpmn-icon-hand-tool:hover {
+ &:after {
+ content: '启动手动工具';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-lasso-tool:hover {
+ &:after {
+ content: '启动套索工具';
+ position: absolute;
+ left: 100px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-space-tool:hover {
+ &:after {
+ content: '启动创建/删除空间工具';
+ position: absolute;
+ left: 45px;
+ width: 170px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-connection-multi:hover {
+ &:after {
+ content: '启动全局连接工具';
+ position: absolute;
+ left: 100px;
+ width: 140px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-start-event-none:hover {
+ &:after {
+ content: '创建开始事件';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-intermediate-event-none:hover {
+ &:after {
+ content: '创建中间/边界事件';
+ position: absolute;
+ left: 100px;
+ width: 140px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-end-event-none:hover {
+ &:after {
+ content: '创建结束事件';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-gateway-none:hover {
+ &:after {
+ content: '创建网关';
+ position: absolute;
+ left: 100px;
+ width: 90px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-gateway-parallel:hover {
+ &:after {
+ content: '创建并行网关';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-gateway-eventbased:hover {
+ &:after {
+ content: '创建事件网关';
+ position: absolute;
+ left: 100px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-task:hover {
+ &:after {
+ content: '创建任务';
+ position: absolute;
+ left: 45px;
+ width: 80px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-subprocess-expanded:hover {
+ &:after {
+ content: '创建可折叠子流程';
+ position: absolute;
+ left: 100px;
+ width: 140px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-user-task:hover {
+ &:after {
+ content: '创建用户任务';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+
+ .task-multi-instance:hover {
+ &:after {
+ content: '创建多实例用户任务';
+ position: absolute;
+ left: 100px;
+ width: 160px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-participant:hover {
+ &:after {
+ content: '创建泳池/泳道';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ .bpmn-icon-data-object {
+ display: none;
+ &:hover {
+ &:after {
+ content: '创建数据对象';
+ position: absolute;
+ left: 45px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ }
+ .bpmn-icon-data-store {
+ display: none;
+ &:hover {
+ &:after {
+ content: '创建数据存储';
+ position: absolute;
+ left: 100px;
+ width: 120px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ }
+ .bpmn-icon-group {
+ display: none;
+ &:hover {
+ &:after {
+ content: '创建分组';
+ position: absolute;
+ left: 100px;
+ width: 100px;
+ font-size: 15px;
+ font-weight: bold;
+ color: #3a84de;
+ border-radius: 2px;
+ border: 1px solid #cccccc;
+ background-color: #fafafa;
+ opacity: 0.8;
+ }
+ }
+ }
+}
diff --git a/src/bpmn/hooks/usePanel.ts b/src/bpmn/hooks/usePanel.ts
new file mode 100644
index 0000000..ace579b
--- /dev/null
+++ b/src/bpmn/hooks/usePanel.ts
@@ -0,0 +1,145 @@
+import showConfig from '../assets/showConfig';
+import type { ModdleElement } from 'bpmn';
+import useModelerStore from '@/store/modules/modeler';
+import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
+interface Options {
+ element: ModdleElement;
+}
+
+export default (ops: Options) => {
+ const { element } = ops;
+ const { getModeling, getModdle } = useModelerStore();
+ const modeling = getModeling();
+ const moddle = getModdle();
+
+ /**
+ * 当前节点类型
+ */
+ const elementType = computed(() => {
+ const bizObj = element.businessObject;
+ return bizObj.eventDefinitions ? bizObj.eventDefinitions[0].$type : bizObj.$type;
+ });
+
+ /**
+ * 用于控制面板字段显示与隐藏的配置
+ */
+ const config = computed(() => showConfig[elementType.value] || {});
+
+ /**
+ * 创建一个节点
+ * @param elementType 节点类型
+ * @param properties 属性
+ * @param parent 父节点
+ */
+ const createModdleElement = (elementType: string, properties: any, parent: ModdleElement) => {
+ const element = moddle.create(elementType, properties);
+ parent && (element.$parent = parent);
+ return element;
+ };
+
+ /**
+ * 获取扩展属性,如果不存在会自动创建
+ */
+ const getExtensionElements = (create = true) => {
+ let extensionElements = element.businessObject.get('extensionElements');
+ if (!extensionElements && create) {
+ extensionElements = createModdleElement('bpmn:ExtensionElements', { values: [] }, element.businessObject);
+ modeling.updateModdleProperties(element, element.businessObject, { extensionElements });
+ }
+ return extensionElements;
+ };
+
+ /**
+ * 获取extensionElements下的properties
+ * @param extensionElements 可选参数,默认获取当前Element下的extensionElements下的Properties
+ */
+ const getPropertiesElements = (extensionElements?: ModdleElement) => {
+ if (!extensionElements) {
+ extensionElements = getExtensionElements();
+ }
+ let propertiesElements = extensionElements.values.find((item) => item.$type === 'flowable:properties');
+ if (!propertiesElements) {
+ propertiesElements = createModdleElement('flowable:properties', { values: [] }, extensionElements);
+ modeling.updateModdleProperties(element, extensionElements, {
+ values: [...extensionElements.get<[]>('values'), propertiesElements]
+ });
+ }
+ return propertiesElements;
+ };
+
+ /**
+ * 更新节点属性
+ * @param properties 属性值
+ */
+ const updateProperties = (properties: any) => {
+ modeling.updateProperties(element, properties);
+ };
+
+ /**
+ * 更新节点信息
+ * @param updateElement 需要更新的节点
+ * @param properties 属性
+ */
+ const updateModdleProperties = (updateElement, properties: any) => {
+ modeling.updateModdleProperties(element, updateElement, properties);
+ };
+
+ /**
+ * 更新Property属性
+ * @param name key值
+ * @param value 值
+ */
+ const updateProperty = (name: string, value: string) => {
+ const propertiesElements = getPropertiesElements();
+
+ let propertyElements = propertiesElements.values.find((item) => item.name === name);
+ if (!propertyElements) {
+ propertyElements = createModdleElement('flowable:property', { name: name, value: value }, propertiesElements);
+ modeling.updateModdleProperties(element, propertiesElements, {
+ values: [...propertiesElements.get('values'), propertyElements]
+ });
+ } else {
+ propertyElements.name = name;
+ propertyElements.value = value;
+ }
+ return propertyElements;
+ };
+
+ const idChange = (newVal: string) => {
+ if (newVal) {
+ updateProperties({ id: newVal });
+ }
+ };
+ const nameChange = (newVal: string) => {
+ if (newVal) {
+ updateProperties({ name: newVal });
+ }
+ };
+ const formKeyChange = (newVal: string) => {
+ updateProperties({ formKey: newVal });
+ };
+ const constant = {
+ MultiInstanceType: [
+ { id: '373d4b81-a0d1-4eb8-8685-0d2fb1b468e2', label: '无', value: MultiInstanceTypeEnum.NONE },
+ { id: 'b5acea7c-b7e5-46b0-8778-390db091bdab', label: '串行', value: MultiInstanceTypeEnum.SERIAL },
+ { id: 'b4f0c683-1ccc-43c4-8380-e1b998986caf', label: '并行', value: MultiInstanceTypeEnum.PARALLEL }
+ ]
+ };
+
+ return {
+ elementType,
+ constant,
+ showConfig: config,
+
+ updateProperties,
+ updateProperty,
+ updateModdleProperties,
+
+ createModdleElement,
+ idChange,
+ nameChange,
+ formKeyChange,
+ getExtensionElements,
+ getPropertiesElements
+ };
+};
diff --git a/src/bpmn/hooks/useParseElement.ts b/src/bpmn/hooks/useParseElement.ts
new file mode 100644
index 0000000..e1a6054
--- /dev/null
+++ b/src/bpmn/hooks/useParseElement.ts
@@ -0,0 +1,34 @@
+import type { ModdleElement } from 'bpmn';
+
+interface Options {
+ element: ModdleElement;
+}
+
+interface Data {
+ id: string;
+}
+
+export default (ops: Options) => {
+ const { element } = ops;
+
+ const parseData = (): T => {
+ const result = {
+ ...element.businessObject,
+ ...element.businessObject.$attrs
+ };
+
+ // 移除flowable前缀,格式化数组
+ for (const key in result) {
+ if (key.indexOf('flowable:') === 0) {
+ const newKey = key.replace('flowable:', '');
+ result[newKey] = result[key];
+ delete result[key];
+ }
+ }
+ return { ...result } as T;
+ };
+
+ return {
+ parseData
+ };
+};
diff --git a/src/bpmn/index.vue b/src/bpmn/index.vue
new file mode 100644
index 0000000..15437c8
--- /dev/null
+++ b/src/bpmn/index.vue
@@ -0,0 +1,496 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保 存
+
+ 预 览
+
+
+ XML预览
+ SVG预览
+
+
+
+
+ 下 载
+
+
+ 下载XML
+ 下载SVG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/GatewayPanel.vue b/src/bpmn/panel/GatewayPanel.vue
new file mode 100644
index 0000000..20cc134
--- /dev/null
+++ b/src/bpmn/panel/GatewayPanel.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/ParticipantPanel.vue b/src/bpmn/panel/ParticipantPanel.vue
new file mode 100644
index 0000000..b1d42e6
--- /dev/null
+++ b/src/bpmn/panel/ParticipantPanel.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/ProcessPanel.vue b/src/bpmn/panel/ProcessPanel.vue
new file mode 100644
index 0000000..9e118e2
--- /dev/null
+++ b/src/bpmn/panel/ProcessPanel.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/SequenceFlowPanel.vue b/src/bpmn/panel/SequenceFlowPanel.vue
new file mode 100644
index 0000000..eac8227
--- /dev/null
+++ b/src/bpmn/panel/SequenceFlowPanel.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/StartEndPanel.vue b/src/bpmn/panel/StartEndPanel.vue
new file mode 100644
index 0000000..bde1212
--- /dev/null
+++ b/src/bpmn/panel/StartEndPanel.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/SubProcessPanel.vue b/src/bpmn/panel/SubProcessPanel.vue
new file mode 100644
index 0000000..3490fff
--- /dev/null
+++ b/src/bpmn/panel/SubProcessPanel.vue
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
+ 多实例
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 集合
+
+
+
+ 属性会作为表达式进行解析。如果表达式解析为字符串而不是一个集合,
+ 不论是因为本身配置的就是静态字符串值,还是表达式计算结果为字符串,
+ 这个字符串都会被当做变量名,并从流程变量中用于获取实际的集合。
+
+
+
+
+
+
+
+
+
+ 元素变量
+
+
+
+ 每创建一个用户任务前,先以该元素变量为label,集合中的一项为value,
+ 创建(局部)流程变量,该局部流程变量被用于指派用户任务。
+ 一般来说,该字符串应与指定人员变量相同。
+
+
+
+
+
+
+
+
+
+ 完成条件
+
+
+
+ 多实例活动在所有实例都完成时结束,然而也可以指定一个表达式,在每个实例
+ 结束时进行计算。当表达式计算为true时,将销毁所有剩余的实例,并结束多实例
+ 活动,继续执行流程。例如 ${nrOfCompletedInstances/nrOfInstances >= 0.6 },
+ 表示当任务完成60%时,该节点就算完成
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/TaskPanel.vue b/src/bpmn/panel/TaskPanel.vue
new file mode 100644
index 0000000..a42de8a
--- /dev/null
+++ b/src/bpmn/panel/TaskPanel.vue
@@ -0,0 +1,491 @@
+
+
+
+
+
+
+
+
+
+
+ 常规
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 任务
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择人员
+
+
+
+
+ 选择组
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 多实例
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 集合
+
+
+
+ 属性会作为表达式进行解析。如果表达式解析为字符串而不是一个集合,
+ 不论是因为本身配置的就是静态字符串值,还是表达式计算结果为字符串,
+ 这个字符串都会被当做变量名,并从流程变量中用于获取实际的集合。
+
+
+
+
+
+
+
+
+
+ 元素变量
+
+
+
+ 每创建一个用户任务前,先以该元素变量为label,集合中的一项为value,
+ 创建(局部)流程变量,该局部流程变量被用于指派用户任务。
+ 一般来说,该字符串应与指定人员变量相同。
+
+
+
+
+
+
+
+
+
+ 完成条件
+
+
+
+ 多实例活动在所有实例都完成时结束,然而也可以指定一个表达式,在每个实例
+ 结束时进行计算。当表达式计算为true时,将销毁所有剩余的实例,并结束多实例
+ 活动,继续执行流程。例如 ${nrOfCompletedInstances/nrOfInstances >= 0.6 },
+ 表示当任务完成60%时,该节点就算完成
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 任务监听器
+
+
+
+
+
+
+
+
+
+
+
+
+ 执行监听器
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/index.vue b/src/bpmn/panel/index.vue
new file mode 100644
index 0000000..445571a
--- /dev/null
+++ b/src/bpmn/panel/index.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
diff --git a/src/bpmn/panel/property/DueDate.vue b/src/bpmn/panel/property/DueDate.vue
new file mode 100644
index 0000000..882766b
--- /dev/null
+++ b/src/bpmn/panel/property/DueDate.vue
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/property/ExecutionListener.vue b/src/bpmn/panel/property/ExecutionListener.vue
new file mode 100644
index 0000000..3c584cb
--- /dev/null
+++ b/src/bpmn/panel/property/ExecutionListener.vue
@@ -0,0 +1,308 @@
+
+
+
+
+ 新增
+ 删除
+
+
+
+
+
+
+
+ {{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}
+
+
+
+
+ {{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 类型
+
+
+
+ 类:示例 com.company.MyCustomListener,自定义类必须实现 org.flowable.engine.delegate.TaskListener 接口
+ 表达式:示例 ${myObject.callMethod(task, task.eventName)}
+ 委托表达式:示例 ${myListenerSpringBean} ,该 springBean 需要实现 org.flowable.engine.delegate.TaskListener 接口
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/property/ListenerParam.vue b/src/bpmn/panel/property/ListenerParam.vue
new file mode 100644
index 0000000..21c6de1
--- /dev/null
+++ b/src/bpmn/panel/property/ListenerParam.vue
@@ -0,0 +1,121 @@
+
+
+
+ 新增
+
+
+
+
+
+
+ {{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bpmn/panel/property/TaskListener.vue b/src/bpmn/panel/property/TaskListener.vue
new file mode 100644
index 0000000..9a32c47
--- /dev/null
+++ b/src/bpmn/panel/property/TaskListener.vue
@@ -0,0 +1,310 @@
+
+
+
+
+ 新增
+ 删除
+
+
+
+
+
+
+
+ {{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}
+
+
+
+
+ {{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}
+
+
+
+
+
+
+
+
+
+
+ 事件
+
+
+
+ create(创建):当任务已经创建,并且所有任务参数都已经设置时触发。
+ assignment(指派):当任务已经指派给某人时触发。请注意:当流程执行到达用户任务时,在触发create事件之前,会首先触发assignment事件。
+ complete(完成):当任务已经完成,从运行时数据中删除前触发。
+ delete(删除):在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/BpmnDesign/index.vue b/src/components/BpmnDesign/index.vue
new file mode 100644
index 0000000..1f84516
--- /dev/null
+++ b/src/components/BpmnDesign/index.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
diff --git a/src/components/BpmnView/index.vue b/src/components/BpmnView/index.vue
new file mode 100644
index 0000000..c5e0c7b
--- /dev/null
+++ b/src/components/BpmnView/index.vue
@@ -0,0 +1,411 @@
+
+
+
+
+
+
+
diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue
new file mode 100644
index 0000000..9502e60
--- /dev/null
+++ b/src/components/Breadcrumb/index.vue
@@ -0,0 +1,63 @@
+
+
+
+
+ {{ item.meta?.title }}
+ {{ item.meta?.title }}
+
+
+
+
+
+
+
+
diff --git a/src/components/BuildCode/index.vue b/src/components/BuildCode/index.vue
new file mode 100644
index 0000000..0b8e3f4
--- /dev/null
+++ b/src/components/BuildCode/index.vue
@@ -0,0 +1,61 @@
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/components/BuildCode/render.vue b/src/components/BuildCode/render.vue
new file mode 100644
index 0000000..aeb9312
--- /dev/null
+++ b/src/components/BuildCode/render.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/DictTag/index.vue b/src/components/DictTag/index.vue
new file mode 100644
index 0000000..ad326c2
--- /dev/null
+++ b/src/components/DictTag/index.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+ {{ item.label + ' ' }}
+
+
+ {{ item.label + ' ' }}
+
+
+
+
+ {{ unmatchArray }}
+
+
+
+
+
+
+
diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue
new file mode 100644
index 0000000..ba70fbb
--- /dev/null
+++ b/src/components/Editor/index.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+ $emit('update:modelValue', content)"
+ />
+
+
+
+
+
+
diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue
new file mode 100644
index 0000000..aaaa45c
--- /dev/null
+++ b/src/components/FileUpload/index.vue
@@ -0,0 +1,229 @@
+
+
+
+
+ 选取文件
+
+
+
+ 请上传
+
+ 大小不超过 {{ fileSize }}MB
+
+
+ 格式为 {{ fileType.join('/') }}
+
+ 的文件
+
+
+
+
+
+ {{ getFileName(file.name) }}
+
+
+ 删除
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue
new file mode 100644
index 0000000..f9f5e62
--- /dev/null
+++ b/src/components/Hamburger/index.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue
new file mode 100644
index 0000000..a785958
--- /dev/null
+++ b/src/components/HeaderSearch/index.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
diff --git a/src/components/IconSelect/index.vue b/src/components/IconSelect/index.vue
new file mode 100644
index 0000000..3bfde4d
--- /dev/null
+++ b/src/components/IconSelect/index.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/IconSelect/requireIcons.ts b/src/components/IconSelect/requireIcons.ts
new file mode 100644
index 0000000..9f06d69
--- /dev/null
+++ b/src/components/IconSelect/requireIcons.ts
@@ -0,0 +1,7 @@
+const icons: string[] = [];
+const modules = import.meta.glob('./../../assets/icons/svg/*.svg');
+for (const path in modules) {
+ const p = path.split('assets/icons/svg/')[1].split('.svg')[0];
+ icons.push(p);
+}
+export default icons;
diff --git a/src/components/ImagePreview/index.vue b/src/components/ImagePreview/index.vue
new file mode 100644
index 0000000..98e6479
--- /dev/null
+++ b/src/components/ImagePreview/index.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue
new file mode 100644
index 0000000..1c6dcd1
--- /dev/null
+++ b/src/components/ImageUpload/index.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+ 请上传
+
+ 大小不超过 {{ fileSize }}MB
+
+
+ 格式为 {{ fileType.join('/') }}
+
+ 的文件
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/LangSelect/index.vue b/src/components/LangSelect/index.vue
new file mode 100644
index 0000000..b5fafd3
--- /dev/null
+++ b/src/components/LangSelect/index.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+ 中文
+ English
+
+
+
+
+
+
+
+
diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue
new file mode 100644
index 0000000..ac02193
--- /dev/null
+++ b/src/components/Pagination/index.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ParentView/index.vue b/src/components/ParentView/index.vue
new file mode 100644
index 0000000..98240ae
--- /dev/null
+++ b/src/components/ParentView/index.vue
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/components/Process/approvalRecord.vue b/src/components/Process/approvalRecord.vue
new file mode 100644
index 0000000..bb4ed91
--- /dev/null
+++ b/src/components/Process/approvalRecord.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.nickName || '无' }}
+
+
+
+
+ {{ scope.row.statusName }}
+
+
+
+
+
+
+
+
+
+
+ 附件
+
+
+
+
+
+ 下载
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Process/multiInstanceUser.vue b/src/components/Process/multiInstanceUser.vue
new file mode 100644
index 0000000..d19fb5f
--- /dev/null
+++ b/src/components/Process/multiInstanceUser.vue
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.createTime }}
+
+
+
+
+
+
+
+ {{ user.userName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Process/submitVerify.vue b/src/components/Process/submitVerify.vue
new file mode 100644
index 0000000..09fc82e
--- /dev/null
+++ b/src/components/Process/submitVerify.vue
@@ -0,0 +1,366 @@
+
+
+
+
+
+ 站内信
+ 邮件
+ 短信
+
+
+
+
+
+
+
+
+ {{ user.userName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 站内信
+ 邮件
+ 短信
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RightToolbar/index.vue b/src/components/RightToolbar/index.vue
new file mode 100644
index 0000000..e8c9d65
--- /dev/null
+++ b/src/components/RightToolbar/index.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RoleSelect/index.vue b/src/components/RoleSelect/index.vue
new file mode 100644
index 0000000..6ba2076
--- /dev/null
+++ b/src/components/RoleSelect/index.vue
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+ {{ role.roleName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ parseTime(scope.row.createTime) }}
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
diff --git a/src/components/RuoYiDoc/index.vue b/src/components/RuoYiDoc/index.vue
new file mode 100644
index 0000000..1e27d89
--- /dev/null
+++ b/src/components/RuoYiDoc/index.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/RuoYiGit/index.vue b/src/components/RuoYiGit/index.vue
new file mode 100644
index 0000000..ad27808
--- /dev/null
+++ b/src/components/RuoYiGit/index.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue
new file mode 100644
index 0000000..ce0b373
--- /dev/null
+++ b/src/components/Screenfull/index.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/src/components/SizeSelect/index.vue b/src/components/SizeSelect/index.vue
new file mode 100644
index 0000000..abf72cc
--- /dev/null
+++ b/src/components/SizeSelect/index.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue
new file mode 100644
index 0000000..05dfe87
--- /dev/null
+++ b/src/components/SvgIcon/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue
new file mode 100644
index 0000000..e93e005
--- /dev/null
+++ b/src/components/TopNav/index.vue
@@ -0,0 +1,200 @@
+
+
+
+
+ {{ item.meta?.title }}
+
+
+
+
+ 更多菜单
+
+ {{ item.meta?.title }}
+
+
+
+
+
+
+
+
diff --git a/src/components/TreeSelect/index.vue b/src/components/TreeSelect/index.vue
new file mode 100644
index 0000000..7accd6b
--- /dev/null
+++ b/src/components/TreeSelect/index.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/UserSelect/index.vue b/src/components/UserSelect/index.vue
new file mode 100644
index 0000000..e9865e5
--- /dev/null
+++ b/src/components/UserSelect/index.vue
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ resetQuery()">重置
+
+
+
+
+
+
+
+
+
+ {{ user.userName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.createTime }}
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
+
diff --git a/src/components/iFrame/index.vue b/src/components/iFrame/index.vue
new file mode 100644
index 0000000..98f2224
--- /dev/null
+++ b/src/components/iFrame/index.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/src/directive/common/copyText.ts b/src/directive/common/copyText.ts
new file mode 100644
index 0000000..0e605d3
--- /dev/null
+++ b/src/directive/common/copyText.ts
@@ -0,0 +1,67 @@
+/**
+ * v-copyText 复制文本内容
+ * Copyright (c) 2022 ruoyi
+ */
+import { DirectiveBinding } from 'vue';
+
+export default {
+ beforeMount(el: any, { value, arg }: DirectiveBinding) {
+ if (arg === 'callback') {
+ el.$copyCallback = value;
+ } else {
+ el.$copyValue = value;
+ const handler = () => {
+ copyTextToClipboard(el.$copyValue);
+ if (el.$copyCallback) {
+ el.$copyCallback(el.$copyValue);
+ }
+ };
+ el.addEventListener('click', handler);
+ el.$destroyCopy = () => el.removeEventListener('click', handler);
+ }
+ }
+};
+
+function copyTextToClipboard(input: string, { target = document.body } = {}) {
+ const element = document.createElement('textarea');
+ const previouslyFocusedElement = document.activeElement as HTMLInputElement;
+ element.value = input;
+ // Prevent keyboard from showing on mobile
+ element.setAttribute('readonly', '');
+
+ element.style.contain = 'strict';
+ element.style.position = 'absolute';
+ element.style.left = '-9999px';
+ element.style.fontSize = '12pt'; // Prevent zooming on iOS
+
+ const selection = document.getSelection();
+ let originalRange;
+ if (selection) {
+ originalRange = selection?.rangeCount > 0 && selection.getRangeAt(0);
+ }
+ target.append(element);
+ element.select();
+
+ // Explicit selection workaround for iOS
+ element.selectionStart = 0;
+ element.selectionEnd = input.length;
+
+ let isSuccess = false;
+ try {
+ isSuccess = document.execCommand('copy');
+ } catch (err) {
+ console.error(err);
+ }
+ element.remove();
+
+ if (originalRange) {
+ selection?.removeAllRanges();
+ selection?.addRange(originalRange);
+ }
+
+ // Get the focus back on the previously focused element, if any
+ if (previouslyFocusedElement) {
+ previouslyFocusedElement.focus();
+ }
+ return isSuccess;
+}
diff --git a/src/directive/index.ts b/src/directive/index.ts
new file mode 100644
index 0000000..ef25ee8
--- /dev/null
+++ b/src/directive/index.ts
@@ -0,0 +1,9 @@
+import copyText from './common/copyText';
+import { hasPermi, hasRoles } from './permission';
+import { App } from 'vue';
+
+export default (app: App) => {
+ app.directive('copyText', copyText);
+ app.directive('hasPermi', hasPermi);
+ app.directive('hasRoles', hasRoles);
+};
diff --git a/src/directive/permission/index.ts b/src/directive/permission/index.ts
new file mode 100644
index 0000000..afde332
--- /dev/null
+++ b/src/directive/permission/index.ts
@@ -0,0 +1,44 @@
+import { Directive, DirectiveBinding } from 'vue';
+import useUserStore from '@/store/modules/user';
+/**
+ * 操作权限处理
+ */
+export const hasPermi: Directive = {
+ mounted(el: HTMLElement, binding: DirectiveBinding) {
+ const { permissions } = useUserStore();
+ // 「其他角色」按钮权限校验
+ const { value } = binding;
+ if (value && value instanceof Array && value.length > 0) {
+ const hasPermission = permissions.some((permi: string) => {
+ return permi === '*:*:*' || value.includes(permi);
+ });
+ if (!hasPermission) {
+ el.parentNode && el.parentNode.removeChild(el);
+ return false;
+ }
+ } else {
+ throw new Error("check perms! Like v-has-permi=\"['system:user:add','system:user:edit']\"");
+ }
+ }
+};
+
+/**
+ * 角色权限处理
+ */
+export const hasRoles: Directive = {
+ mounted(el: HTMLElement, binding: DirectiveBinding) {
+ const { value } = binding;
+ const { roles } = useUserStore();
+ if (value && value instanceof Array && value.length > 0) {
+ const hasRole = roles.some((role: string) => {
+ return role === 'admin' || value.includes(role);
+ });
+ if (!hasRole) {
+ el.parentNode && el.parentNode.removeChild(el);
+ return false;
+ }
+ } else {
+ throw new Error("check roles! Like v-has-roles=\"['admin','test']\"");
+ }
+ }
+};
diff --git a/src/enums/LanguageEnum.ts b/src/enums/LanguageEnum.ts
new file mode 100644
index 0000000..c857c43
--- /dev/null
+++ b/src/enums/LanguageEnum.ts
@@ -0,0 +1,5 @@
+export enum LanguageEnum {
+ zh_CN = 'zh_CN',
+
+ en_US = 'en_US'
+}
diff --git a/src/enums/MenuTypeEnum.ts b/src/enums/MenuTypeEnum.ts
new file mode 100644
index 0000000..cecebd2
--- /dev/null
+++ b/src/enums/MenuTypeEnum.ts
@@ -0,0 +1,15 @@
+export enum MenuTypeEnum {
+ /**
+ * 目录
+ */
+ M = 'M',
+ /**
+ * 菜单
+ */
+ C = 'C',
+
+ /**
+ * 按钮
+ */
+ F = 'F'
+}
diff --git a/src/enums/RespEnum.ts b/src/enums/RespEnum.ts
new file mode 100644
index 0000000..ce60a51
--- /dev/null
+++ b/src/enums/RespEnum.ts
@@ -0,0 +1,90 @@
+export enum HttpStatus {
+ /**
+ * 操作成功
+ */
+ SUCCESS = 200,
+ /**
+ * 对象创建成功
+ */
+ CREATED = 201,
+ /**
+ * 请求已经被接受
+ */
+ ACCEPTED = 202,
+ /**
+ * 操作已经执行成功,但是没有返回数据
+ */
+ NO_CONTENT = 204,
+ /**
+ * 资源已经被移除
+ */
+ MOVED_PERM = 301,
+ /**
+ * 重定向
+ */
+ SEE_OTHER = 303,
+ /**
+ * 资源没有被修改
+ */
+ NOT_MODIFIED = 304,
+ /**
+ * 参数列表错误(缺少,格式不匹配)
+ */
+ PARAM_ERROR = 400,
+ /**
+ * 未授权
+ */
+ UNAUTHORIZED = 401,
+ /**
+ * 访问受限,授权过期
+ */
+ FORBIDDEN = 403,
+ /**
+ * 资源,服务未找到
+ */
+ NOT_FOUND = 404,
+ /**
+ * 不允许的http方法
+ */
+ BAD_METHOD = 405,
+ /**
+ * 资源冲突,或者资源被锁
+ */
+ CONFLICT = 409,
+ /**
+ * 不支持的数据,媒体类型
+ */
+ UNSUPPORTED_TYPE = 415,
+ /**
+ * 系统内部错误
+ */
+ SERVER_ERROR = 500,
+ /**
+ * 接口未实现
+ */
+ NOT_IMPLEMENTED = 501,
+ /**
+ * 服务不可用,过载或者维护
+ */
+ BAD_GATEWAY = 502,
+ /**
+ * 网关超时
+ */
+ GATEWAY_TIMEOUT = 504,
+ /**
+ * 未知错误
+ */
+ UNKNOWN_ERROR = 520,
+ /**
+ * 服务未知错误
+ */
+ SERVICE_ERROR = 521,
+ /**
+ * 数据库未知错误
+ */
+ DATABASE_ERROR = 522,
+ /**
+ * 系统警告消息
+ */
+ WARN = 601
+}
diff --git a/src/enums/SettingTypeEnum.ts b/src/enums/SettingTypeEnum.ts
new file mode 100644
index 0000000..bf4ec43
--- /dev/null
+++ b/src/enums/SettingTypeEnum.ts
@@ -0,0 +1,16 @@
+export enum SettingTypeEnum {
+ TITLE = 'title',
+ THEME = 'theme',
+ SIDE_THEME = 'sideTheme',
+ SHOW_SETTINGS = 'showSettings',
+ TOP_NAV = 'topNav',
+ TAGS_VIEW = 'tagsView',
+ FIXED_HEADER = 'fixedHeader',
+ SIDEBAR_LOGO = 'sidebarLogo',
+ DYNAMIC_TITLE = 'dynamicTitle',
+ ANIMATION_ENABLE = 'animationEnable',
+ LAYOUT = 'layout',
+ DARK = 'dark',
+
+ LAYOUT_SETTING = 'layout-setting'
+}
diff --git a/src/enums/SideThemeEnum.ts b/src/enums/SideThemeEnum.ts
new file mode 100644
index 0000000..f172858
--- /dev/null
+++ b/src/enums/SideThemeEnum.ts
@@ -0,0 +1,4 @@
+export enum SideThemeEnum {
+ DARK = 'theme-dark',
+ LIGHT = 'theme-light'
+}
diff --git a/src/enums/bpmn/IndexEnums.ts b/src/enums/bpmn/IndexEnums.ts
new file mode 100644
index 0000000..8c39823
--- /dev/null
+++ b/src/enums/bpmn/IndexEnums.ts
@@ -0,0 +1,17 @@
+export enum AllocationTypeEnum {
+ USER = 'user',
+ CANDIDATE = 'candidate',
+ YOURSELF = 'yourself',
+ SPECIFY = 'specify'
+}
+
+export enum SpecifyDescEnum {
+ SPECIFY_MULTIPLE = 'specifyMultiple',
+ SPECIFY_SINGLE = 'specifySingle'
+}
+
+export enum MultiInstanceTypeEnum {
+ SERIAL = 'serial',
+ PARALLEL = 'parallel',
+ NONE = 'none'
+}
diff --git a/src/enums/layout/LayoutEnum.ts b/src/enums/layout/LayoutEnum.ts
new file mode 100644
index 0000000..0aa601b
--- /dev/null
+++ b/src/enums/layout/LayoutEnum.ts
@@ -0,0 +1,4 @@
+export enum ThemeEnum {
+ DARK = 'theme-dark',
+ LIGHT = 'theme-light'
+}
diff --git a/src/hooks/useDialog.ts b/src/hooks/useDialog.ts
new file mode 100644
index 0000000..547f199
--- /dev/null
+++ b/src/hooks/useDialog.ts
@@ -0,0 +1,31 @@
+import { Ref } from 'vue';
+
+interface Options {
+ title?: string;
+}
+interface Return {
+ title: Ref;
+ visible: Ref;
+ openDialog: () => void;
+ closeDialog: () => void;
+}
+export default (ops?: Options): Return => {
+ const visible = ref(false);
+ const title = ref(ops.title || '');
+
+ const openDialog = () => {
+ visible.value = true;
+ };
+
+ const closeDialog = () => {
+ visible.value = false;
+ };
+
+ return {
+ title,
+ visible,
+
+ openDialog,
+ closeDialog
+ };
+};
diff --git a/src/lang/en_US.json b/src/lang/en_US.json
new file mode 100644
index 0000000..17b472e
--- /dev/null
+++ b/src/lang/en_US.json
@@ -0,0 +1,25 @@
+{
+ "route": {
+ "dashboard": "Dashboard",
+ "document": "Document"
+ },
+ "login": {
+ "username": "Username",
+ "password": "Password",
+ "login": "Login",
+ "code": "Verification Code",
+ "copyright": ""
+ },
+ "navbar": {
+ "full": "Full Screen",
+ "language": "Language",
+ "dashboard": "Dashboard",
+ "document": "Document",
+ "message": "Message",
+ "layoutSize": "Layout Size",
+ "selectTenant": "Select Tenant",
+ "layoutSetting": "Layout Setting",
+ "personalCenter": "Personal Center",
+ "logout": "Logout"
+ }
+}
diff --git a/src/lang/en_US.ts b/src/lang/en_US.ts
new file mode 100644
index 0000000..034ea91
--- /dev/null
+++ b/src/lang/en_US.ts
@@ -0,0 +1,28 @@
+export default {
+ // 路由国际化
+ route: {
+ dashboard: 'Dashboard',
+ document: 'Document'
+ },
+ // 登录页面国际化
+ login: {
+ username: 'Username',
+ password: 'Password',
+ login: 'Login',
+ code: 'Verification Code',
+ copyright: ''
+ },
+ // 导航栏国际化
+ navbar: {
+ full: 'Full Screen',
+ language: 'Language',
+ dashboard: 'Dashboard',
+ document: 'Document',
+ message: 'Message',
+ layoutSize: 'Layout Size',
+ selectTenant: 'Select Tenant',
+ layoutSetting: 'Layout Setting',
+ personalCenter: 'Personal Center',
+ logout: 'Logout'
+ }
+};
diff --git a/src/lang/index.ts b/src/lang/index.ts
new file mode 100644
index 0000000..e4e1d25
--- /dev/null
+++ b/src/lang/index.ts
@@ -0,0 +1,27 @@
+// 自定义国际化配置
+import { createI18n } from 'vue-i18n';
+
+import { LanguageEnum } from '@/enums/LanguageEnum';
+import messages from '@intlify/unplugin-vue-i18n/messages';
+
+/**
+ * 获取当前语言
+ * @returns zh-cn|en ...
+ */
+export const getLanguage = (): LanguageEnum => {
+ const language = useStorage('language', LanguageEnum.zh_CN);
+ if (language.value) {
+ return language.value;
+ }
+ return LanguageEnum.zh_CN;
+};
+
+const i18n = createI18n({
+ globalInjection: true,
+ allowComposition: true,
+ legacy: false,
+ locale: getLanguage(),
+ messages
+});
+
+export default i18n;
diff --git a/src/lang/zh_CN.json b/src/lang/zh_CN.json
new file mode 100644
index 0000000..071598d
--- /dev/null
+++ b/src/lang/zh_CN.json
@@ -0,0 +1,25 @@
+{
+ "route": {
+ "dashboard": "首页",
+ "document": "项目文档"
+ },
+ "login": {
+ "username": "用户名",
+ "password": "密码",
+ "login": "登 录",
+ "code": "请输入验证码",
+ "copyright": ""
+ },
+ "navbar": {
+ "full": "全屏",
+ "language": "语言",
+ "dashboard": "首页",
+ "document": "项目文档",
+ "message": "消息",
+ "layoutSize": "布局大小",
+ "selectTenant": "选择租户",
+ "layoutSetting": "布局设置",
+ "personalCenter": "个人中心",
+ "logout": "退出登录"
+ }
+}
diff --git a/src/lang/zh_CN.ts b/src/lang/zh_CN.ts
new file mode 100644
index 0000000..666a400
--- /dev/null
+++ b/src/lang/zh_CN.ts
@@ -0,0 +1,27 @@
+export default {
+ // 路由国际化
+ route: {
+ dashboard: '首页',
+ document: '项目文档'
+ },
+ // 登录页面国际化
+ login: {
+ username: '用户名',
+ password: '密码',
+ login: '登 录',
+ code: '请输入验证码',
+ copyright: ''
+ },
+ navbar: {
+ full: '全屏',
+ language: '语言',
+ dashboard: '首页',
+ document: '项目文档',
+ message: '消息',
+ layoutSize: '布局大小',
+ selectTenant: '选择租户',
+ layoutSetting: '布局设置',
+ personalCenter: '个人中心',
+ logout: '退出登录'
+ }
+};
diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
new file mode 100644
index 0000000..7f86ef4
--- /dev/null
+++ b/src/layout/components/AppMain.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/IframeToggle/index.vue b/src/layout/components/IframeToggle/index.vue
new file mode 100644
index 0000000..2de529d
--- /dev/null
+++ b/src/layout/components/IframeToggle/index.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
diff --git a/src/layout/components/InnerLink/index.vue b/src/layout/components/InnerLink/index.vue
new file mode 100644
index 0000000..bb6b89b
--- /dev/null
+++ b/src/layout/components/InnerLink/index.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue
new file mode 100644
index 0000000..c2ed0b6
--- /dev/null
+++ b/src/layout/components/Navbar.vue
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/Settings/index.vue b/src/layout/components/Settings/index.vue
new file mode 100644
index 0000000..3082beb
--- /dev/null
+++ b/src/layout/components/Settings/index.vue
@@ -0,0 +1,238 @@
+
+
+ 主题风格设置
+
+
+
+
+
+
+
+
+
+
+
+
+ 主题颜色
+
+
+
+
+
+ 深色模式
+
+
+
+
+
+
+
+ 系统布局配置
+
+
+ 开启 TopNav
+
+
+
+
+
+
+ 开启 Tags-Views
+
+
+
+
+
+
+ 固定 Header
+
+
+
+
+
+
+ 显示 Logo
+
+
+
+
+
+
+ 动态标题
+
+
+
+
+
+
+
+ 保存配置
+ 重置配置
+
+
+
+
+
+
diff --git a/src/layout/components/Sidebar/Link.vue b/src/layout/components/Sidebar/Link.vue
new file mode 100644
index 0000000..fd75f35
--- /dev/null
+++ b/src/layout/components/Sidebar/Link.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue
new file mode 100644
index 0000000..631c261
--- /dev/null
+++ b/src/layout/components/Sidebar/Logo.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
new file mode 100644
index 0000000..3720062
--- /dev/null
+++ b/src/layout/components/Sidebar/SidebarItem.vue
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
new file mode 100644
index 0000000..a4f20d0
--- /dev/null
+++ b/src/layout/components/Sidebar/index.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/SocialCallback/index.vue b/src/layout/components/SocialCallback/index.vue
new file mode 100644
index 0000000..746de20
--- /dev/null
+++ b/src/layout/components/SocialCallback/index.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue
new file mode 100644
index 0000000..3b30043
--- /dev/null
+++ b/src/layout/components/TagsView/ScrollPane.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
new file mode 100644
index 0000000..1e12ca4
--- /dev/null
+++ b/src/layout/components/TagsView/index.vue
@@ -0,0 +1,341 @@
+
+
+
+
+ {{ tag.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/TopBar/search.vue b/src/layout/components/TopBar/search.vue
new file mode 100644
index 0000000..cf4b024
--- /dev/null
+++ b/src/layout/components/TopBar/search.vue
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/components/index.ts b/src/layout/components/index.ts
new file mode 100644
index 0000000..47c83e1
--- /dev/null
+++ b/src/layout/components/index.ts
@@ -0,0 +1,4 @@
+export { default as AppMain } from './AppMain.vue';
+export { default as Navbar } from './Navbar.vue';
+export { default as Settings } from './Settings/index.vue';
+export { default as TagsView } from './TagsView/index.vue';
diff --git a/src/layout/components/notice/index.vue b/src/layout/components/notice/index.vue
new file mode 100644
index 0000000..e43b2b8
--- /dev/null
+++ b/src/layout/components/notice/index.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
{{ v.message }}
+
+
{{ v.time }}
+
+
+
已读
+
未读
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layout/index.vue b/src/layout/index.vue
new file mode 100644
index 0000000..ce47a30
--- /dev/null
+++ b/src/layout/index.vue
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
diff --git a/src/main.ts b/src/main.ts
new file mode 100644
index 0000000..592de58
--- /dev/null
+++ b/src/main.ts
@@ -0,0 +1,57 @@
+import { createApp } from 'vue';
+// global css
+import 'virtual:uno.css';
+import '@/assets/styles/index.scss';
+import 'element-plus/theme-chalk/dark/css-vars.css';
+
+// App、router、store
+import App from './App.vue';
+import store from './store';
+import router from './router';
+
+// 自定义指令
+import directive from './directive';
+
+// 注册插件
+import plugins from './plugins/index'; // plugins
+
+// 高亮组件
+// import 'highlight.js/styles/a11y-light.css';
+import 'highlight.js/styles/atom-one-dark.css';
+import 'highlight.js/lib/common';
+import HighLight from '@highlightjs/vue-plugin';
+
+// svg图标
+import 'virtual:svg-icons-register';
+import ElementIcons from '@/plugins/svgicon';
+
+// permission control
+import './permission';
+
+// 国际化
+import i18n from '@/lang/index';
+
+// vxeTable
+import VXETable from 'vxe-table';
+import 'vxe-table/lib/style.css';
+VXETable.config({
+ zIndex: 999999
+});
+
+// 修改 el-dialog 默认点击遮照为不关闭
+import { ElDialog } from 'element-plus';
+ElDialog.props.closeOnClickModal.default = false;
+
+const app = createApp(App);
+
+app.use(HighLight);
+app.use(ElementIcons);
+app.use(router);
+app.use(store);
+app.use(i18n);
+app.use(VXETable);
+app.use(plugins);
+// 自定义指令
+directive(app);
+
+app.mount('#app');
diff --git a/src/permission.ts b/src/permission.ts
new file mode 100644
index 0000000..125438b
--- /dev/null
+++ b/src/permission.ts
@@ -0,0 +1,65 @@
+import { to as tos } from 'await-to-js';
+import router from './router';
+import NProgress from 'nprogress';
+import 'nprogress/nprogress.css';
+import { getToken } from '@/utils/auth';
+import { isHttp } from '@/utils/validate';
+import { isRelogin } from '@/utils/request';
+import useUserStore from '@/store/modules/user';
+import useSettingsStore from '@/store/modules/settings';
+import usePermissionStore from '@/store/modules/permission';
+
+NProgress.configure({ showSpinner: false });
+const whiteList = ['/login', '/register', '/social-callback'];
+
+router.beforeEach(async (to, from, next) => {
+ NProgress.start();
+ if (getToken()) {
+ to.meta.title && useSettingsStore().setTitle(to.meta.title);
+ /* has token*/
+ if (to.path === '/login') {
+ next({ path: '/' });
+ NProgress.done();
+ } else if (whiteList.indexOf(to.path as string) !== -1) {
+ next();
+ } else {
+ if (useUserStore().roles.length === 0) {
+ isRelogin.show = true;
+ // 判断当前用户是否已拉取完user_info信息
+ const [err] = await tos(useUserStore().getInfo());
+ if (err) {
+ await useUserStore().logout();
+ ElMessage.error(err);
+ next({ path: '/' });
+ } else {
+ isRelogin.show = false;
+ const accessRoutes = await usePermissionStore().generateRoutes();
+ // 根据roles权限生成可访问的路由表
+ accessRoutes.forEach((route) => {
+ if (!isHttp(route.path)) {
+ router.addRoute(route); // 动态添加可访问路由表
+ }
+ });
+ // @ts-ignore
+ next({ path: to.path, replace: true, params: to.params, query: to.query, hash: to.hash, name: to.name as string }); // hack方法 确保addRoutes已完成
+ }
+ } else {
+ next();
+ }
+ }
+ } else {
+ // 没有token
+ if (whiteList.indexOf(to.path as string) !== -1) {
+ // 在免登录白名单,直接进入
+ next();
+ } else {
+ const redirect = encodeURIComponent(to.fullPath || '/');
+ next(`/login?redirect=${redirect}`); // 否则全部重定向到登录页
+ NProgress.done();
+ }
+ }
+});
+
+router.afterEach(() => {
+ NProgress.done();
+});
diff --git a/src/plugins/auth.ts b/src/plugins/auth.ts
new file mode 100644
index 0000000..74c91ee
--- /dev/null
+++ b/src/plugins/auth.ts
@@ -0,0 +1,60 @@
+import useUserStore from '@/store/modules/user';
+
+const authPermission = (permission: string): boolean => {
+ const all_permission = '*:*:*';
+ const permissions: string[] = useUserStore().permissions;
+ if (permission && permission.length > 0) {
+ return permissions.some((v) => {
+ return all_permission === v || v === permission;
+ });
+ } else {
+ return false;
+ }
+};
+
+const authRole = (role: string): boolean => {
+ const super_admin = 'admin';
+ const roles = useUserStore().roles;
+ if (role && role.length > 0) {
+ return roles.some((v) => {
+ return super_admin === v || v === role;
+ });
+ } else {
+ return false;
+ }
+};
+
+export default {
+ // 验证用户是否具备某权限
+ hasPermi(permission: string): boolean {
+ return authPermission(permission);
+ },
+ // 验证用户是否含有指定权限,只需包含其中一个
+ hasPermiOr(permissions: string[]): boolean {
+ return permissions.some((item) => {
+ return authPermission(item);
+ });
+ },
+ // 验证用户是否含有指定权限,必须全部拥有
+ hasPermiAnd(permissions: string[]): boolean {
+ return permissions.every((item) => {
+ return authPermission(item);
+ });
+ },
+ // 验证用户是否具备某角色
+ hasRole(role: string): boolean {
+ return authRole(role);
+ },
+ // 验证用户是否含有指定角色,只需包含其中一个
+ hasRoleOr(roles: string[]): boolean {
+ return roles.some((item) => {
+ return authRole(item);
+ });
+ },
+ // 验证用户是否含有指定角色,必须全部拥有
+ hasRoleAnd(roles: string[]): boolean {
+ return roles.every((item) => {
+ return authRole(item);
+ });
+ }
+};
diff --git a/src/plugins/cache.ts b/src/plugins/cache.ts
new file mode 100644
index 0000000..cf43680
--- /dev/null
+++ b/src/plugins/cache.ts
@@ -0,0 +1,77 @@
+const sessionCache = {
+ set(key: string, value: any) {
+ if (!sessionStorage) {
+ return;
+ }
+ if (key != null && value != null) {
+ sessionStorage.setItem(key, value);
+ }
+ },
+ get(key: string) {
+ if (!sessionStorage) {
+ return null;
+ }
+ if (key == null) {
+ return null;
+ }
+ return sessionStorage.getItem(key);
+ },
+ setJSON(key: string, jsonValue: any) {
+ if (jsonValue != null) {
+ this.set(key, JSON.stringify(jsonValue));
+ }
+ },
+ getJSON(key: string) {
+ const value = this.get(key);
+ if (value != null) {
+ return JSON.parse(value);
+ }
+ },
+ remove(key: string) {
+ sessionStorage.removeItem(key);
+ }
+};
+const localCache = {
+ set(key: string, value: any) {
+ if (!localStorage) {
+ return;
+ }
+ if (key != null && value != null) {
+ localStorage.setItem(key, value);
+ }
+ },
+ get(key: string) {
+ if (!localStorage) {
+ return null;
+ }
+ if (key == null) {
+ return null;
+ }
+ return localStorage.getItem(key);
+ },
+ setJSON(key: string, jsonValue: any) {
+ if (jsonValue != null) {
+ this.set(key, JSON.stringify(jsonValue));
+ }
+ },
+ getJSON(key: string) {
+ const value = this.get(key);
+ if (value != null) {
+ return JSON.parse(value);
+ }
+ },
+ remove(key: string) {
+ localStorage.removeItem(key);
+ }
+};
+
+export default {
+ /**
+ * 会话级缓存
+ */
+ session: sessionCache,
+ /**
+ * 本地缓存
+ */
+ local: localCache
+};
diff --git a/src/plugins/download.ts b/src/plugins/download.ts
new file mode 100644
index 0000000..ef66b3a
--- /dev/null
+++ b/src/plugins/download.ts
@@ -0,0 +1,65 @@
+import axios from 'axios';
+import FileSaver from 'file-saver';
+import errorCode from '@/utils/errorCode';
+import { blobValidate } from '@/utils/ruoyi';
+import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
+import { globalHeaders } from '@/utils/request';
+
+const baseURL = import.meta.env.VITE_APP_BASE_API;
+let downloadLoadingInstance: LoadingInstance;
+export default {
+ async oss(ossId: string | number) {
+ const url = baseURL + '/resource/oss/download/' + ossId;
+ downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
+ try {
+ const res = await axios({
+ method: 'get',
+ url: url,
+ responseType: 'blob',
+ headers: globalHeaders()
+ });
+ const isBlob = blobValidate(res.data);
+ if (isBlob) {
+ const blob = new Blob([res.data], { type: 'application/octet-stream' });
+ FileSaver.saveAs(blob, decodeURIComponent(res.headers['download-filename'] as string));
+ } else {
+ this.printErrMsg(res.data);
+ }
+ downloadLoadingInstance.close();
+ } catch (r) {
+ console.error(r);
+ ElMessage.error('下载文件出现错误,请联系管理员!');
+ downloadLoadingInstance.close();
+ }
+ },
+ async zip(url: string, name: string) {
+ url = baseURL + url;
+ downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
+ try {
+ const res = await axios({
+ method: 'get',
+ url: url,
+ responseType: 'blob',
+ headers: globalHeaders()
+ });
+ const isBlob = blobValidate(res.data);
+ if (isBlob) {
+ const blob = new Blob([res.data], { type: 'application/zip' });
+ FileSaver.saveAs(blob, name);
+ } else {
+ this.printErrMsg(res.data);
+ }
+ downloadLoadingInstance.close();
+ } catch (r) {
+ console.error(r);
+ ElMessage.error('下载文件出现错误,请联系管理员!');
+ downloadLoadingInstance.close();
+ }
+ },
+ async printErrMsg(data: any) {
+ const resText = await data.text();
+ const rspObj = JSON.parse(resText);
+ const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
+ ElMessage.error(errMsg);
+ }
+};
diff --git a/src/plugins/index.ts b/src/plugins/index.ts
new file mode 100644
index 0000000..6c5e0c3
--- /dev/null
+++ b/src/plugins/index.ts
@@ -0,0 +1,43 @@
+import modal from './modal';
+import tab from './tab';
+import download from './download';
+import cache from './cache';
+import auth from './auth';
+// 预设动画
+import animate from '@/animate';
+
+import { download as dl } from '@/utils/request';
+import { useDict } from '@/utils/dict';
+import { getConfigKey, updateConfigByKey } from '@/api/system/config';
+import { parseTime, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi';
+
+import { App } from 'vue';
+
+export default function installPlugin(app: App) {
+ // 页签操作
+ app.config.globalProperties.$tab = tab;
+
+ // 模态框对象
+ app.config.globalProperties.$modal = modal;
+
+ // 缓存对象
+ app.config.globalProperties.$cache = cache;
+
+ // 下载文件
+ app.config.globalProperties.$download = download;
+
+ // 认证对象
+ app.config.globalProperties.$auth = auth;
+
+ // 全局方法挂载
+ app.config.globalProperties.useDict = useDict;
+ app.config.globalProperties.getConfigKey = getConfigKey;
+ app.config.globalProperties.updateConfigByKey = updateConfigByKey;
+ app.config.globalProperties.download = dl;
+ app.config.globalProperties.parseTime = parseTime;
+ app.config.globalProperties.handleTree = handleTree;
+ app.config.globalProperties.addDateRange = addDateRange;
+ app.config.globalProperties.selectDictLabel = selectDictLabel;
+ app.config.globalProperties.selectDictLabels = selectDictLabels;
+ app.config.globalProperties.animate = animate;
+}
diff --git a/src/plugins/modal.ts b/src/plugins/modal.ts
new file mode 100644
index 0000000..a8b0548
--- /dev/null
+++ b/src/plugins/modal.ts
@@ -0,0 +1,81 @@
+import { MessageBoxData } from 'element-plus';
+import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
+let loadingInstance: LoadingInstance;
+export default {
+ // 消息提示
+ msg(content: any) {
+ ElMessage.info(content);
+ },
+ // 错误消息
+ msgError(content: any) {
+ ElMessage.error(content);
+ },
+ // 成功消息
+ msgSuccess(content: any) {
+ ElMessage.success(content);
+ },
+ // 警告消息
+ msgWarning(content: any) {
+ ElMessage.warning(content);
+ },
+ // 弹出提示
+ alert(content: any) {
+ ElMessageBox.alert(content, '系统提示');
+ },
+ // 错误提示
+ alertError(content: any) {
+ ElMessageBox.alert(content, '系统提示', { type: 'error' });
+ },
+ // 成功提示
+ alertSuccess(content: any) {
+ ElMessageBox.alert(content, '系统提示', { type: 'success' });
+ },
+ // 警告提示
+ alertWarning(content: any) {
+ ElMessageBox.alert(content, '系统提示', { type: 'warning' });
+ },
+ // 通知提示
+ notify(content: any) {
+ ElNotification.info(content);
+ },
+ // 错误通知
+ notifyError(content: any) {
+ ElNotification.error(content);
+ },
+ // 成功通知
+ notifySuccess(content: any) {
+ ElNotification.success(content);
+ },
+ // 警告通知
+ notifyWarning(content: any) {
+ ElNotification.warning(content);
+ },
+ // 确认窗体
+ confirm(content: any): Promise {
+ return ElMessageBox.confirm(content, '系统提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ });
+ },
+ // 提交内容
+ prompt(content: any) {
+ return ElMessageBox.prompt(content, '系统提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning'
+ });
+ },
+ // 打开遮罩层
+ loading(content: string) {
+ loadingInstance = ElLoading.service({
+ lock: true,
+ text: content,
+ background: 'rgba(0, 0, 0, 0.7)'
+ });
+ },
+ // 关闭遮罩层
+ closeLoading() {
+ loadingInstance.close();
+ }
+};
diff --git a/src/plugins/svgicon.ts b/src/plugins/svgicon.ts
new file mode 100644
index 0000000..8c68609
--- /dev/null
+++ b/src/plugins/svgicon.ts
@@ -0,0 +1,10 @@
+import * as ElementPlusIconsVue from '@element-plus/icons-vue';
+import { App } from 'vue';
+
+export default {
+ install: (app: App) => {
+ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+ app.component(key, component);
+ }
+ }
+};
diff --git a/src/plugins/tab.ts b/src/plugins/tab.ts
new file mode 100644
index 0000000..86421a8
--- /dev/null
+++ b/src/plugins/tab.ts
@@ -0,0 +1,96 @@
+import router from '@/router';
+import {RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw} from 'vue-router';
+import useTagsViewStore from '@/store/modules/tagsView';
+
+export default {
+ /**
+ * 刷新当前tab页签
+ * @param obj 标签对象
+ */
+ async refreshPage(obj?: RouteLocationNormalized): Promise {
+ const { path, query, matched } = router.currentRoute.value;
+ if (obj === undefined) {
+ matched.forEach((m: RouteLocationMatched) => {
+ if (m.components && m.components.default && m.components.default.name) {
+ if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
+ obj = {
+ name: m.components.default.name,
+ path: path,
+ query: query,
+ matched: undefined,
+ fullPath: undefined,
+ hash: undefined,
+ params: undefined,
+ redirectedFrom: undefined,
+ meta: undefined
+ };
+ }
+ }
+ });
+ }
+ let query1: undefined | {} = {};
+ let path1: undefined | string = '';
+ if (obj) {
+ query1 = obj.query;
+ path1 = obj.path;
+ }
+ await useTagsViewStore().delCachedView(obj);
+ await router.replace({
+ path: '/redirect' + path1,
+ query: query1
+ });
+ },
+ // 关闭当前tab页签,打开新页签
+ closeOpenPage(obj: RouteLocationRaw): void {
+ useTagsViewStore().delView(router.currentRoute.value);
+ if (obj !== undefined) {
+ router.push(obj);
+ }
+ },
+ // 关闭指定tab页签
+ async closePage(obj?: RouteLocationNormalized): Promise<{ visitedViews: RouteLocationNormalized[]; cachedViews: string[] } | any> {
+ if (obj === undefined) {
+ // prettier-ignore
+ const { visitedViews } = await useTagsViewStore().delView(router.currentRoute.value)
+ const latestView = visitedViews.slice(-1)[0];
+ if (latestView) {
+ return router.push(latestView.fullPath);
+ }
+ return router.push('/');
+ }
+ return useTagsViewStore().delView(obj);
+ },
+ // 关闭所有tab页签
+ closeAllPage() {
+ return useTagsViewStore().delAllViews();
+ },
+ // 关闭左侧tab页签
+ closeLeftPage(obj?: RouteLocationNormalized) {
+ return useTagsViewStore().delLeftTags(obj || router.currentRoute.value);
+ },
+ // 关闭右侧tab页签
+ closeRightPage(obj?: RouteLocationNormalized) {
+ return useTagsViewStore().delRightTags(obj || router.currentRoute.value);
+ },
+ // 关闭其他tab页签
+ closeOtherPage(obj?: RouteLocationNormalized) {
+ return useTagsViewStore().delOthersViews(obj || router.currentRoute.value);
+ },
+ /**
+ * 打开tab页签
+ * @param url 路由地址
+ * @param title 标题
+ * @param query 参数
+ */
+ openPage(url: string, title?: string, query?: any) {
+ const obj = { path: url, query: { ...query, title } };
+ return router.push(obj);
+ },
+ /**
+ * 修改tab页签
+ * @param obj 标签对象
+ */
+ updatePage(obj: RouteLocationNormalized) {
+ return useTagsViewStore().updateVisitedView(obj);
+ }
+};
diff --git a/src/router/index.ts b/src/router/index.ts
new file mode 100644
index 0000000..86e0092
--- /dev/null
+++ b/src/router/index.ts
@@ -0,0 +1,198 @@
+import { createWebHistory, createRouter, RouteRecordRaw } from 'vue-router';
+/* Layout */
+import Layout from '@/layout/index.vue';
+
+/**
+ * Note: 路由配置项
+ *
+ * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
+ * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
+ * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
+ * // 若你想不管路由下面的 children 声明的个数都显示你的根路由
+ * // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
+ * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
+ * name:'router-name' // 设定路由的名字,一定要填写不然使用时会出现各种问题
+ * query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
+ * roles: ['admin', 'common'] // 访问路由的角色权限
+ * permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
+ * meta : {
+ noCache: true // 如果设置为true,则不会被 缓存(默认 false)
+ title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
+ icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg
+ breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示
+ activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
+ }
+ */
+
+// 公共路由
+export const constantRoutes: RouteRecordRaw[] = [
+ {
+ path: '/redirect',
+ component: Layout,
+ hidden: true,
+ children: [
+ {
+ path: '/redirect/:path(.*)',
+ component: () => import('@/views/redirect/index.vue')
+ }
+ ]
+ },
+ {
+ path: '/social-callback',
+ hidden: true,
+ component: () => import('@/layout/components/SocialCallback/index.vue')
+ },
+ {
+ path: '/login',
+ component: () => import('@/views/login.vue'),
+ hidden: true
+ },
+ {
+ path: '/register',
+ component: () => import('@/views/register.vue'),
+ hidden: true
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ component: () => import('@/views/error/404.vue'),
+ hidden: true
+ },
+ {
+ path: '/401',
+ component: () => import('@/views/error/401.vue'),
+ hidden: true
+ },
+ {
+ path: '',
+ component: Layout,
+ redirect: '/index',
+ children: [
+ {
+ path: '/index',
+ component: () => import('@/views/index.vue'),
+ name: 'Index',
+ meta: { title: '首页', icon: 'dashboard', affix: true }
+ }
+ ]
+ },
+ {
+ path: '/user',
+ component: Layout,
+ hidden: true,
+ redirect: 'noredirect',
+ children: [
+ {
+ path: 'profile',
+ component: () => import('@/views/system/user/profile/index.vue'),
+ name: 'Profile',
+ meta: { title: '个人中心', icon: 'user' }
+ }
+ ]
+ }
+];
+
+// 动态路由,基于用户权限动态去加载
+export const dynamicRoutes: RouteRecordRaw[] = [
+ {
+ path: '/system/user-auth',
+ component: Layout,
+ hidden: true,
+ permissions: ['system:user:edit'],
+ children: [
+ {
+ path: 'role/:userId(\\d+)',
+ component: () => import('@/views/system/user/authRole.vue'),
+ name: 'AuthRole',
+ meta: { title: '分配角色', activeMenu: '/system/user', icon: '' }
+ }
+ ]
+ },
+ {
+ path: '/system/role-auth',
+ component: Layout,
+ hidden: true,
+ permissions: ['system:role:edit'],
+ children: [
+ {
+ path: 'user/:roleId(\\d+)',
+ component: () => import('@/views/system/role/authUser.vue'),
+ name: 'AuthUser',
+ meta: { title: '分配用户', activeMenu: '/system/role', icon: '' }
+ }
+ ]
+ },
+ {
+ path: '/system/dict-data',
+ component: Layout,
+ hidden: true,
+ permissions: ['system:dict:list'],
+ children: [
+ {
+ path: 'index/:dictId(\\d+)',
+ component: () => import('@/views/system/dict/data.vue'),
+ name: 'Data',
+ meta: { title: '字典数据', activeMenu: '/system/dict', icon: '' }
+ }
+ ]
+ },
+ {
+ path: '/system/oss-config',
+ component: Layout,
+ hidden: true,
+ permissions: ['system:ossConfig:list'],
+ children: [
+ {
+ path: 'index',
+ component: () => import('@/views/system/oss/config.vue'),
+ name: 'OssConfig',
+ meta: { title: '配置管理', activeMenu: '/system/oss', icon: '' }
+ }
+ ]
+ },
+ {
+ path: '/tool/gen-edit',
+ component: Layout,
+ hidden: true,
+ permissions: ['tool:gen:edit'],
+ children: [
+ {
+ path: 'index/:tableId(\\d+)',
+ component: () => import('@/views/tool/gen/editTable.vue'),
+ name: 'GenEdit',
+ meta: { title: '修改生成配置', activeMenu: '/tool/gen', icon: '', noCache: true }
+ }
+ ]
+ },
+ {
+ path: '/workflow/leaveEdit',
+ component: Layout,
+ hidden: true,
+ permissions: ['workflow:leave:edit'],
+ children: [
+ {
+ path: 'index',
+ component: () => import('@/views/workflow/leave/leaveEdit.vue'),
+ name: 'leaveEdit',
+ meta: { title: '请假申请', activeMenu: '/workflow/leave', noCache: true }
+ }
+ ]
+ }
+];
+
+/**
+ * 创建路由
+ */
+const router = createRouter({
+ history: createWebHistory(import.meta.env.VITE_APP_CONTEXT_PATH),
+ routes: constantRoutes,
+ // 刷新时,滚动条位置还原
+ scrollBehavior(to, from, savedPosition) {
+ if (savedPosition) {
+ return savedPosition;
+ } else {
+ return { top: 0 };
+ }
+ }
+});
+
+export default router;
diff --git a/src/settings.ts b/src/settings.ts
new file mode 100644
index 0000000..4b62c75
--- /dev/null
+++ b/src/settings.ts
@@ -0,0 +1,62 @@
+import { LanguageEnum } from '@/enums/LanguageEnum';
+
+const setting: DefaultSettings = {
+ /**
+ * 网页标题
+ */
+ title: import.meta.env.VITE_APP_TITLE,
+
+ theme: '#409EFF',
+
+ /**
+ * 侧边栏主题 深色主题theme-dark,浅色主题theme-light
+ */
+ sideTheme: 'theme-dark',
+ /**
+ * 是否系统布局配置
+ */
+ showSettings: true,
+
+ /**
+ * 是否显示顶部导航
+ */
+ topNav: false,
+
+ /**
+ * 是否显示 tagsView
+ */
+ tagsView: true,
+
+ /**
+ * 是否固定头部
+ */
+ fixedHeader: false,
+
+ /**
+ * 是否显示logo
+ */
+ sidebarLogo: true,
+
+ /**
+ * 是否显示动态标题
+ */
+ dynamicTitle: false,
+
+ /**
+ * @type {string | array} 'production' | ['production', 'development']
+ * @description Need show err logs component.
+ * The default is only used in the production env
+ * If you want to also use it in dev, you can pass ['production', 'development']
+ */
+ errorLog: 'production',
+
+ animationEnable: false,
+
+ dark: false,
+ language: LanguageEnum.zh_CN,
+
+ size: 'default',
+
+ layout: ''
+};
+export default setting;
diff --git a/src/store/index.ts b/src/store/index.ts
new file mode 100644
index 0000000..069d54e
--- /dev/null
+++ b/src/store/index.ts
@@ -0,0 +1,3 @@
+const store = createPinia();
+
+export default store;
diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts
new file mode 100644
index 0000000..0205fab
--- /dev/null
+++ b/src/store/modules/app.ts
@@ -0,0 +1,72 @@
+import zhCN from 'element-plus/es/locale/lang/zh-cn';
+import enUS from 'element-plus/es/locale/lang/en';
+
+export const useAppStore = defineStore('app', () => {
+ const sidebarStatus = useStorage('sidebarStatus', '1');
+ const sidebar = reactive({
+ opened: sidebarStatus.value ? !!+sidebarStatus.value : true,
+ withoutAnimation: false,
+ hide: false
+ });
+ const device = ref('desktop');
+ const size = useStorage<'large' | 'default' | 'small'>('size', 'default');
+
+ // 语言
+ const language = useStorage('language', 'zh_CN');
+ const languageObj: any = {
+ en_US: enUS,
+ zh_CN: zhCN
+ };
+ const locale = computed(() => {
+ return languageObj[language.value];
+ });
+
+ const toggleSideBar = (withoutAnimation: boolean) => {
+ if (sidebar.hide) {
+ return false;
+ }
+
+ sidebar.opened = !sidebar.opened;
+ sidebar.withoutAnimation = withoutAnimation;
+ if (sidebar.opened) {
+ sidebarStatus.value = '1';
+ } else {
+ sidebarStatus.value = '0';
+ }
+ };
+
+ const closeSideBar = ({ withoutAnimation }: any): void => {
+ sidebarStatus.value = '0';
+ sidebar.opened = false;
+ sidebar.withoutAnimation = withoutAnimation;
+ };
+ const toggleDevice = (d: string): void => {
+ device.value = d;
+ };
+ const setSize = (s: 'large' | 'default' | 'small'): void => {
+ size.value = s;
+ };
+ const toggleSideBarHide = (status: boolean): void => {
+ sidebar.hide = status;
+ };
+
+ const changeLanguage = (val: string): void => {
+ language.value = val;
+ };
+
+ return {
+ device,
+ sidebar,
+ language,
+ locale,
+ size,
+ changeLanguage,
+ toggleSideBar,
+ closeSideBar,
+ toggleDevice,
+ setSize,
+ toggleSideBarHide
+ };
+});
+
+export default useAppStore;
diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts
new file mode 100644
index 0000000..2f937b9
--- /dev/null
+++ b/src/store/modules/dict.ts
@@ -0,0 +1,78 @@
+export const useDictStore = defineStore('dict', () => {
+ const dict = ref<
+ Array<{
+ key: string;
+ value: DictDataOption[];
+ }>
+ >([]);
+
+ /**
+ * 获取字典
+ * @param _key 字典key
+ */
+ const getDict = (_key: string): DictDataOption[] | null => {
+ if (_key == null && _key == '') {
+ return null;
+ }
+ try {
+ for (let i = 0; i < dict.value.length; i++) {
+ if (dict.value[i].key == _key) {
+ return dict.value[i].value;
+ }
+ }
+ } catch (e) {
+ return null;
+ }
+ return null;
+ };
+
+ /**
+ * 设置字典
+ * @param _key 字典key
+ * @param _value 字典value
+ */
+ const setDict = (_key: string, _value: DictDataOption[]) => {
+ if (_key !== null && _key !== '') {
+ dict.value.push({
+ key: _key,
+ value: _value
+ });
+ }
+ };
+
+ /**
+ * 删除字典
+ * @param _key
+ */
+ const removeDict = (_key: string): boolean => {
+ let bln = false;
+ try {
+ for (let i = 0; i < dict.value.length; i++) {
+ if (dict.value[i].key == _key) {
+ dict.value.splice(i, 1);
+ return true;
+ }
+ }
+ } catch (e) {
+ bln = false;
+ }
+ return bln;
+ };
+
+ /**
+ * 清空字典
+ */
+ const cleanDict = (): void => {
+ dict.value = [];
+ };
+
+ return {
+ dict,
+ getDict,
+ setDict,
+ removeDict,
+ cleanDict
+ };
+});
+
+export default useDictStore;
diff --git a/src/store/modules/modeler.ts b/src/store/modules/modeler.ts
new file mode 100644
index 0000000..204f450
--- /dev/null
+++ b/src/store/modules/modeler.ts
@@ -0,0 +1,76 @@
+import type { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
+
+type ModelerStore = {
+ modeler: Modeler | undefined;
+ moddle: Moddle | undefined;
+ modeling: Modeling | undefined;
+ canvas: Canvas | undefined;
+ elementRegistry: ElementRegistry | undefined;
+ bpmnFactory: BpmnFactory | undefined;
+ // 流程定义根节点信息
+ procDefId: string | undefined;
+ procDefName: string | undefined;
+};
+
+const defaultState: ModelerStore = {
+ modeler: undefined,
+ moddle: undefined,
+ modeling: undefined,
+ canvas: undefined,
+ elementRegistry: undefined,
+ bpmnFactory: undefined,
+ procDefId: undefined,
+ procDefName: undefined
+};
+export const useModelerStore = defineStore('modeler', () => {
+ let modeler = defaultState.modeler;
+ let moddle = defaultState.moddle;
+ let modeling = defaultState.modeling;
+ let canvas = defaultState.canvas;
+ let elementRegistry = defaultState.elementRegistry;
+ let bpmnFactory = defaultState.bpmnFactory;
+ const procDefId = ref(defaultState.procDefId);
+ const procDefName = ref(defaultState.procDefName);
+
+ const getModeler = () => modeler;
+ const getModdle = () => moddle;
+ const getModeling = (): Modeling | undefined => modeling;
+ const getCanvas = (): Canvas | undefined => canvas;
+ const getElRegistry = (): ElementRegistry | undefined => elementRegistry;
+ const getBpmnFactory = (): BpmnFactory | undefined => bpmnFactory;
+ const getProcDefId = (): string | undefined => procDefId.value;
+ const getProcDefName = (): string | undefined => procDefName.value;
+
+ // 设置根节点
+ const setModeler = (modelers: Modeler | undefined) => {
+ if (modelers) {
+ modeler = modelers;
+ modeling = modelers.get('modeling');
+ moddle = modelers.get('moddle');
+ canvas = modelers.get