commit 3d10a765be8f7f40c14a73a3ccd2094916f98ac3 Author: 赵鹏 Date: Mon Jan 20 16:19:28 2025 +0800 初始化 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..79a12ff --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true +[*.{js,ts,vue}] +charset = utf-8 # 设置文件字符集为 utf-8 +end_of_line = lf # 控制换行类型(lf | cr | crlf) +insert_final_newline = true # 始终在文件末尾插入一个新行 +indent_style = space # 缩进风格(tab | space) +indent_size = 2 # 缩进大小 +max_line_length = 100 # 最大行长度 + +[*.md] # 仅 md 文件适用以下规则 +max_line_length = off # 关闭最大行长度限制 +trim_trailing_whitespace = false # 关闭末尾空格修剪 diff --git a/.env b/.env new file mode 100644 index 0000000..2019f3c --- /dev/null +++ b/.env @@ -0,0 +1,25 @@ +# 标题 +VITE_APP_TITLE=芋道管理系统 + +# 项目本地运行端口号 +VITE_PORT=9980 + +# open 运行 npm run dev 时自动打开浏览器 +VITE_OPEN=true + +# 租户开关 +VITE_APP_TENANT_ENABLE=true + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=true + +# 文档地址的开关 +VITE_APP_DOCALERT_ENABLE=true + +# 百度统计 +VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc + +# 默认账户密码 +VITE_APP_DEFAULT_LOGIN_TENANT = 芋道源码 +VITE_APP_DEFAULT_LOGIN_USERNAME = admin +VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123 diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..dc7d250 --- /dev/null +++ b/.env.dev @@ -0,0 +1,37 @@ +# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP) +NODE_ENV=production + +VITE_DEV=true + +# 请求路径 +VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn' + +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=true + +# 打包路径 +VITE_BASE_PATH=/ + +# 输出路径 +VITE_OUT_DIR=dist + +# 商城H5会员端域名 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn' + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=true + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' \ No newline at end of file diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..3576558 --- /dev/null +++ b/.env.local @@ -0,0 +1,34 @@ +# 本地开发环境:本地启动所有项目(前端、后端、APP)时使用,不依赖外部环境 +NODE_ENV=development + +VITE_DEV=true + +# 请求路径 +VITE_BASE_URL='http://localhost:48080' + +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务 +VITE_UPLOAD_TYPE=server + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=false + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH=/ + +# 商城H5会员端域名 +VITE_MALL_H5_DOMAIN='http://localhost:3000' + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=false + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' \ No newline at end of file diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..ca7cb8e --- /dev/null +++ b/.env.prod @@ -0,0 +1,34 @@ +# 生产环境:只在打包时使用 +NODE_ENV=production + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://localhost:48080' + +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH=/ + +# 输出路径 +VITE_OUT_DIR=dist-prod + +# 商城H5会员端域名 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn' + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' \ No newline at end of file diff --git a/.env.stage b/.env.stage new file mode 100644 index 0000000..084337c --- /dev/null +++ b/.env.stage @@ -0,0 +1,34 @@ +# 预发布环境:只在打包时使用 +NODE_ENV=production + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn' + +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH='http://static-vue3.yudao.iocoder.cn/' + +# 输出路径 +VITE_OUT_DIR=dist-stage + +# 商城H5会员端域名 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn' + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' \ No newline at end of file diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..2252e14 --- /dev/null +++ b/.env.test @@ -0,0 +1,34 @@ +# 测试环境:只在打包时使用 +NODE_ENV=production + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://localhost:48080' + +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务 +VITE_UPLOAD_TYPE=server + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH=/admin-ui-vue3/ + +# 输出路径 +VITE_OUT_DIR=dist-test + +# 商城H5会员端域名 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn' + +# GoView域名 +VITE_GOVIEW_URL='http://127.0.0.1:3000' \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1e85c0f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,8 @@ +/build/ +/config/ +/dist/ +/*.js +/test/unit/coverage/ +/node_modules/* +/dist* +/src/main.ts diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json new file mode 100644 index 0000000..024c96a --- /dev/null +++ b/.eslintrc-auto-import.json @@ -0,0 +1,259 @@ +{ + "globals": { + "EffectScope": true, + "ElMessage": true, + "ElMessageBox": true, + "ElTag": 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, + "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, + "useArrayJoin": true, + "useArrayMap": true, + "useArrayReduce": true, + "useArraySome": true, + "useAsyncQueue": true, + "useAsyncState": true, + "useAttrs": true, + "useBase64": true, + "useBattery": true, + "useBluetooth": true, + "useBreakpoints": true, + "useBroadcastChannel": true, + "useBrowserLocation": true, + "useCached": true, + "useClipboard": 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, + "usePointerSwipe": true, + "usePreferredColorScheme": true, + "usePreferredDark": true, + "usePreferredLanguages": true, + "useRafFn": true, + "useRefHistory": true, + "useResizeObserver": true, + "useRoute": true, + "useRouter": true, + "useScreenOrientation": true, + "useScreenSafeArea": true, + "useScriptTag": true, + "useScroll": true, + "useScrollLock": true, + "useSessionStorage": true, + "useShare": true, + "useSlots": 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, + "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 + } +} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..b28255c --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,75 @@ +// @ts-check +const { defineConfig } = require('eslint-define-config') +module.exports = defineConfig({ + root: true, + env: { + browser: true, + node: true, + es6: true + }, + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true + } + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'plugin:prettier/recommended', + '@unocss' + ], + rules: { + 'vue/no-setup-props-destructure': 'off', + 'vue/script-setup-uses-vars': 'error', + 'vue/no-reserved-component-names': 'off', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + 'vue/custom-event-name-casing': 'off', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': 'off', + 'no-unused-vars': 'off', + 'space-before-function-paren': 'off', + + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/require-explicit-emits': 'off', + 'vue/require-toggle-inside-transition': 'off', + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always' + }, + svg: 'always', + math: 'always' + } + ], + 'vue/multi-word-component-names': 'off', + 'vue/no-v-html': 'off', + 'prettier/prettier': 'off', // 芋艿:默认关闭 prettier 的 ESLint 校验,因为我们使用的是 IDE 的 Prettier 插件 + '@unocss/order': 'off', // 芋艿:禁用 unocss 【css】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐 + '@unocss/order-attributify': 'off' // 芋艿:禁用 unocss 【属性】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐 + } +}) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..848638a --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +node_modules +.DS_Store +dist +dist-ssr +/dist* +pnpm-debug +auto-*.d.ts +.idea +.history diff --git a/.image/Java监控.jpg b/.image/Java监控.jpg new file mode 100644 index 0000000..6ad522a Binary files /dev/null and b/.image/Java监控.jpg differ diff --git a/.image/MySQL.jpg b/.image/MySQL.jpg new file mode 100644 index 0000000..64a1940 Binary files /dev/null and b/.image/MySQL.jpg differ diff --git a/.image/OA请假-列表.jpg b/.image/OA请假-列表.jpg new file mode 100644 index 0000000..787bb73 Binary files /dev/null and b/.image/OA请假-列表.jpg differ diff --git a/.image/OA请假-发起.jpg b/.image/OA请假-发起.jpg new file mode 100644 index 0000000..1a7342d Binary files /dev/null and b/.image/OA请假-发起.jpg differ diff --git a/.image/OA请假-详情.jpg b/.image/OA请假-详情.jpg new file mode 100644 index 0000000..a83e7c1 Binary files /dev/null and b/.image/OA请假-详情.jpg differ diff --git a/.image/Redis.jpg b/.image/Redis.jpg new file mode 100644 index 0000000..9569352 Binary files /dev/null and b/.image/Redis.jpg differ diff --git a/.image/admin-uniapp/01.png b/.image/admin-uniapp/01.png new file mode 100644 index 0000000..0f65d99 Binary files /dev/null and b/.image/admin-uniapp/01.png differ diff --git a/.image/admin-uniapp/02.png b/.image/admin-uniapp/02.png new file mode 100644 index 0000000..05ec781 Binary files /dev/null and b/.image/admin-uniapp/02.png differ diff --git a/.image/admin-uniapp/03.png b/.image/admin-uniapp/03.png new file mode 100644 index 0000000..f400c68 Binary files /dev/null and b/.image/admin-uniapp/03.png differ diff --git a/.image/admin-uniapp/04.png b/.image/admin-uniapp/04.png new file mode 100644 index 0000000..d5d5ea0 Binary files /dev/null and b/.image/admin-uniapp/04.png differ diff --git a/.image/admin-uniapp/05.png b/.image/admin-uniapp/05.png new file mode 100644 index 0000000..1de6d8a Binary files /dev/null and b/.image/admin-uniapp/05.png differ diff --git a/.image/admin-uniapp/06.png b/.image/admin-uniapp/06.png new file mode 100644 index 0000000..400ae90 Binary files /dev/null and b/.image/admin-uniapp/06.png differ diff --git a/.image/admin-uniapp/07.png b/.image/admin-uniapp/07.png new file mode 100644 index 0000000..2ed8c0f Binary files /dev/null and b/.image/admin-uniapp/07.png differ diff --git a/.image/admin-uniapp/08.png b/.image/admin-uniapp/08.png new file mode 100644 index 0000000..090e64a Binary files /dev/null and b/.image/admin-uniapp/08.png differ diff --git a/.image/admin-uniapp/09.png b/.image/admin-uniapp/09.png new file mode 100644 index 0000000..f2032c8 Binary files /dev/null and b/.image/admin-uniapp/09.png differ diff --git a/.image/common/ai-feature.png b/.image/common/ai-feature.png new file mode 100644 index 0000000..b4a55f5 Binary files /dev/null and b/.image/common/ai-feature.png differ diff --git a/.image/common/ai-preview.gif b/.image/common/ai-preview.gif new file mode 100644 index 0000000..5f13ac4 Binary files /dev/null and b/.image/common/ai-preview.gif differ diff --git a/.image/common/bpm-feature.png b/.image/common/bpm-feature.png new file mode 100644 index 0000000..23787fb Binary files /dev/null and b/.image/common/bpm-feature.png differ diff --git a/.image/common/crm-feature.png b/.image/common/crm-feature.png new file mode 100644 index 0000000..e1c9670 Binary files /dev/null and b/.image/common/crm-feature.png differ diff --git a/.image/common/erp-feature.png b/.image/common/erp-feature.png new file mode 100644 index 0000000..d30b30e Binary files /dev/null and b/.image/common/erp-feature.png differ diff --git a/.image/common/infra-feature.png b/.image/common/infra-feature.png new file mode 100644 index 0000000..f5cef50 Binary files /dev/null and b/.image/common/infra-feature.png differ diff --git a/.image/common/mall-feature.png b/.image/common/mall-feature.png new file mode 100644 index 0000000..cca05c0 Binary files /dev/null and b/.image/common/mall-feature.png differ diff --git a/.image/common/mall-preview.png b/.image/common/mall-preview.png new file mode 100644 index 0000000..f939214 Binary files /dev/null and b/.image/common/mall-preview.png differ diff --git a/.image/common/project-vs.png b/.image/common/project-vs.png new file mode 100644 index 0000000..561e092 Binary files /dev/null and b/.image/common/project-vs.png differ diff --git a/.image/common/ruoyi-vue-pro-architecture.png b/.image/common/ruoyi-vue-pro-architecture.png new file mode 100644 index 0000000..7bd7d59 Binary files /dev/null and b/.image/common/ruoyi-vue-pro-architecture.png differ diff --git a/.image/common/ruoyi-vue-pro-biz.png b/.image/common/ruoyi-vue-pro-biz.png new file mode 100644 index 0000000..24a385a Binary files /dev/null and b/.image/common/ruoyi-vue-pro-biz.png differ diff --git a/.image/common/system-feature.png b/.image/common/system-feature.png new file mode 100644 index 0000000..366087c Binary files /dev/null and b/.image/common/system-feature.png differ diff --git a/.image/common/yudao-cloud-architecture.png b/.image/common/yudao-cloud-architecture.png new file mode 100644 index 0000000..59416d8 Binary files /dev/null and b/.image/common/yudao-cloud-architecture.png differ diff --git a/.image/common/yudao-roadmap.png b/.image/common/yudao-roadmap.png new file mode 100644 index 0000000..f4becc9 Binary files /dev/null and b/.image/common/yudao-roadmap.png differ diff --git a/.image/个人中心.jpg b/.image/个人中心.jpg new file mode 100644 index 0000000..ce57f6e Binary files /dev/null and b/.image/个人中心.jpg differ diff --git a/.image/代码生成.jpg b/.image/代码生成.jpg new file mode 100644 index 0000000..751603e Binary files /dev/null and b/.image/代码生成.jpg differ diff --git a/.image/令牌管理.jpg b/.image/令牌管理.jpg new file mode 100644 index 0000000..04abf4d Binary files /dev/null and b/.image/令牌管理.jpg differ diff --git a/.image/任务列表-审批.jpg b/.image/任务列表-审批.jpg new file mode 100644 index 0000000..cba312a Binary files /dev/null and b/.image/任务列表-审批.jpg differ diff --git a/.image/任务列表-已办.jpg b/.image/任务列表-已办.jpg new file mode 100644 index 0000000..7a8d0fb Binary files /dev/null and b/.image/任务列表-已办.jpg differ diff --git a/.image/任务列表-待办.jpg b/.image/任务列表-待办.jpg new file mode 100644 index 0000000..a90323f Binary files /dev/null and b/.image/任务列表-待办.jpg differ diff --git a/.image/任务日志.jpg b/.image/任务日志.jpg new file mode 100644 index 0000000..599e50a Binary files /dev/null and b/.image/任务日志.jpg differ diff --git a/.image/商户信息.jpg b/.image/商户信息.jpg new file mode 100644 index 0000000..483eace Binary files /dev/null and b/.image/商户信息.jpg differ diff --git a/.image/在线用户.jpg b/.image/在线用户.jpg new file mode 100644 index 0000000..b183009 Binary files /dev/null and b/.image/在线用户.jpg differ diff --git a/.image/大屏设计器-列表.jpg b/.image/大屏设计器-列表.jpg new file mode 100644 index 0000000..9a45c3b Binary files /dev/null and b/.image/大屏设计器-列表.jpg differ diff --git a/.image/大屏设计器-编辑.jpg b/.image/大屏设计器-编辑.jpg new file mode 100644 index 0000000..63298a0 Binary files /dev/null and b/.image/大屏设计器-编辑.jpg differ diff --git a/.image/大屏设计器-预览.jpg b/.image/大屏设计器-预览.jpg new file mode 100644 index 0000000..501d9ea Binary files /dev/null and b/.image/大屏设计器-预览.jpg differ diff --git a/.image/字典数据.jpg b/.image/字典数据.jpg new file mode 100644 index 0000000..8298c89 Binary files /dev/null and b/.image/字典数据.jpg differ diff --git a/.image/字典类型.jpg b/.image/字典类型.jpg new file mode 100644 index 0000000..6613392 Binary files /dev/null and b/.image/字典类型.jpg differ diff --git a/.image/定时任务.jpg b/.image/定时任务.jpg new file mode 100644 index 0000000..d5bbd85 Binary files /dev/null and b/.image/定时任务.jpg differ diff --git a/.image/岗位管理.jpg b/.image/岗位管理.jpg new file mode 100644 index 0000000..42b64d2 Binary files /dev/null and b/.image/岗位管理.jpg differ diff --git a/.image/工作流设计器-bpmn.jpg b/.image/工作流设计器-bpmn.jpg new file mode 100644 index 0000000..2a61f60 Binary files /dev/null and b/.image/工作流设计器-bpmn.jpg differ diff --git a/.image/工作流设计器-simple.jpg b/.image/工作流设计器-simple.jpg new file mode 100644 index 0000000..9ef2c9e Binary files /dev/null and b/.image/工作流设计器-simple.jpg differ diff --git a/.image/应用信息-列表.jpg b/.image/应用信息-列表.jpg new file mode 100644 index 0000000..da419a2 Binary files /dev/null and b/.image/应用信息-列表.jpg differ diff --git a/.image/应用信息-编辑.jpg b/.image/应用信息-编辑.jpg new file mode 100644 index 0000000..913cfbc Binary files /dev/null and b/.image/应用信息-编辑.jpg differ diff --git a/.image/应用管理.jpg b/.image/应用管理.jpg new file mode 100644 index 0000000..6e7789f Binary files /dev/null and b/.image/应用管理.jpg differ diff --git a/.image/我的流程-列表.jpg b/.image/我的流程-列表.jpg new file mode 100644 index 0000000..223d17a Binary files /dev/null and b/.image/我的流程-列表.jpg differ diff --git a/.image/我的流程-发起.jpg b/.image/我的流程-发起.jpg new file mode 100644 index 0000000..7a83306 Binary files /dev/null and b/.image/我的流程-发起.jpg differ diff --git a/.image/我的流程-详情.jpg b/.image/我的流程-详情.jpg new file mode 100644 index 0000000..6a01541 Binary files /dev/null and b/.image/我的流程-详情.jpg differ diff --git a/.image/报表设计器-图形报表.jpg b/.image/报表设计器-图形报表.jpg new file mode 100644 index 0000000..681b318 Binary files /dev/null and b/.image/报表设计器-图形报表.jpg differ diff --git a/.image/报表设计器-打印设计.jpg b/.image/报表设计器-打印设计.jpg new file mode 100644 index 0000000..bb86da6 Binary files /dev/null and b/.image/报表设计器-打印设计.jpg differ diff --git a/.image/报表设计器-数据报表.jpg b/.image/报表设计器-数据报表.jpg new file mode 100644 index 0000000..9ca5b9b Binary files /dev/null and b/.image/报表设计器-数据报表.jpg differ diff --git a/.image/操作日志.jpg b/.image/操作日志.jpg new file mode 100644 index 0000000..4a0611a Binary files /dev/null and b/.image/操作日志.jpg differ diff --git a/.image/支付订单.jpg b/.image/支付订单.jpg new file mode 100644 index 0000000..0a56dd7 Binary files /dev/null and b/.image/支付订单.jpg differ diff --git a/.image/敏感词.jpg b/.image/敏感词.jpg new file mode 100644 index 0000000..92a5397 Binary files /dev/null and b/.image/敏感词.jpg differ diff --git a/.image/数据库文档.jpg b/.image/数据库文档.jpg new file mode 100644 index 0000000..a4339d9 Binary files /dev/null and b/.image/数据库文档.jpg differ diff --git a/.image/文件管理.jpg b/.image/文件管理.jpg new file mode 100644 index 0000000..054b19f Binary files /dev/null and b/.image/文件管理.jpg differ diff --git a/.image/文件管理2.jpg b/.image/文件管理2.jpg new file mode 100644 index 0000000..b12e5c3 Binary files /dev/null and b/.image/文件管理2.jpg differ diff --git a/.image/文件配置.jpg b/.image/文件配置.jpg new file mode 100644 index 0000000..e618049 Binary files /dev/null and b/.image/文件配置.jpg differ diff --git a/.image/日志中心.jpg b/.image/日志中心.jpg new file mode 100644 index 0000000..27c1c6c Binary files /dev/null and b/.image/日志中心.jpg differ diff --git a/.image/流程模型-列表.jpg b/.image/流程模型-列表.jpg new file mode 100644 index 0000000..ffdc584 Binary files /dev/null and b/.image/流程模型-列表.jpg differ diff --git a/.image/流程模型-定义.jpg b/.image/流程模型-定义.jpg new file mode 100644 index 0000000..18b316c Binary files /dev/null and b/.image/流程模型-定义.jpg differ diff --git a/.image/流程模型-设计.jpg b/.image/流程模型-设计.jpg new file mode 100644 index 0000000..9614969 Binary files /dev/null and b/.image/流程模型-设计.jpg differ diff --git a/.image/流程表单.jpg b/.image/流程表单.jpg new file mode 100644 index 0000000..60669c1 Binary files /dev/null and b/.image/流程表单.jpg differ diff --git a/.image/生成效果.jpg b/.image/生成效果.jpg new file mode 100644 index 0000000..98ff2cc Binary files /dev/null and b/.image/生成效果.jpg differ diff --git a/.image/用户分组.jpg b/.image/用户分组.jpg new file mode 100644 index 0000000..39af1cd Binary files /dev/null and b/.image/用户分组.jpg differ diff --git a/.image/用户管理.jpg b/.image/用户管理.jpg new file mode 100644 index 0000000..844604a Binary files /dev/null and b/.image/用户管理.jpg differ diff --git a/.image/登录.jpg b/.image/登录.jpg new file mode 100644 index 0000000..b782b98 Binary files /dev/null and b/.image/登录.jpg differ diff --git a/.image/登录日志.jpg b/.image/登录日志.jpg new file mode 100644 index 0000000..25662d9 Binary files /dev/null and b/.image/登录日志.jpg differ diff --git a/.image/短信日志.jpg b/.image/短信日志.jpg new file mode 100644 index 0000000..ada8e56 Binary files /dev/null and b/.image/短信日志.jpg differ diff --git a/.image/短信模板.jpg b/.image/短信模板.jpg new file mode 100644 index 0000000..09381cc Binary files /dev/null and b/.image/短信模板.jpg differ diff --git a/.image/短信渠道.jpg b/.image/短信渠道.jpg new file mode 100644 index 0000000..df3a5c3 Binary files /dev/null and b/.image/短信渠道.jpg differ diff --git a/.image/租户套餐.png b/.image/租户套餐.png new file mode 100644 index 0000000..9663167 Binary files /dev/null and b/.image/租户套餐.png differ diff --git a/.image/租户管理.jpg b/.image/租户管理.jpg new file mode 100644 index 0000000..647416a Binary files /dev/null and b/.image/租户管理.jpg differ diff --git a/.image/系统接口.jpg b/.image/系统接口.jpg new file mode 100644 index 0000000..6d39d42 Binary files /dev/null and b/.image/系统接口.jpg differ diff --git a/.image/菜单管理.jpg b/.image/菜单管理.jpg new file mode 100644 index 0000000..ad3b797 Binary files /dev/null and b/.image/菜单管理.jpg differ diff --git a/.image/表单构建.jpg b/.image/表单构建.jpg new file mode 100644 index 0000000..81f0374 Binary files /dev/null and b/.image/表单构建.jpg differ diff --git a/.image/角色管理.jpg b/.image/角色管理.jpg new file mode 100644 index 0000000..eed776e Binary files /dev/null and b/.image/角色管理.jpg differ diff --git a/.image/访问日志.jpg b/.image/访问日志.jpg new file mode 100644 index 0000000..ef301aa Binary files /dev/null and b/.image/访问日志.jpg differ diff --git a/.image/退款订单.jpg b/.image/退款订单.jpg new file mode 100644 index 0000000..2c6c6c9 Binary files /dev/null and b/.image/退款订单.jpg differ diff --git a/.image/通知公告.jpg b/.image/通知公告.jpg new file mode 100644 index 0000000..97bb42f Binary files /dev/null and b/.image/通知公告.jpg differ diff --git a/.image/部门管理.jpg b/.image/部门管理.jpg new file mode 100644 index 0000000..6eab233 Binary files /dev/null and b/.image/部门管理.jpg differ diff --git a/.image/配置管理.jpg b/.image/配置管理.jpg new file mode 100644 index 0000000..0abaec9 Binary files /dev/null and b/.image/配置管理.jpg differ diff --git a/.image/链路追踪.jpg b/.image/链路追踪.jpg new file mode 100644 index 0000000..12f7aa8 Binary files /dev/null and b/.image/链路追踪.jpg differ diff --git a/.image/错误日志.jpg b/.image/错误日志.jpg new file mode 100644 index 0000000..eb615ea Binary files /dev/null and b/.image/错误日志.jpg differ diff --git a/.image/错误码管理.jpg b/.image/错误码管理.jpg new file mode 100644 index 0000000..ea91dde Binary files /dev/null and b/.image/错误码管理.jpg differ diff --git a/.image/首页.jpg b/.image/首页.jpg new file mode 100644 index 0000000..10a7fde Binary files /dev/null and b/.image/首页.jpg differ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f68ea86 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +/node_modules/** +/dist/ +/dist* +/public/* +/docs/* +/vite.config.ts +/src/types/env.d.ts +/src/types/auto-components.d.ts +/src/types/auto-imports.d.ts +/docs/**/* +CHANGELOG diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..aa605b4 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,6 @@ +/dist/* +/public/* +public/* +/dist* +/src/types/env.d.ts +/docs/**/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9861118 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-present Archer + +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..6ca2dbf --- /dev/null +++ b/README.md @@ -0,0 +1,266 @@ +**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!** + +**「我喜欢写代码,乐此不疲」** +**「我喜欢做开源,以此为乐」** + +我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。 + +如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 + +## 🐶 新手必读 + +* nodejs > 16.18.0 && pnpm > 8.6.0 (强制使用pnpm) +* 演示地址【Vue3 + element-plus】: +* 演示地址【Vue3 + vben(ant-design-vue)】: +* 演示地址【Vue2 + element-ui】: +* 启动文档: +* 视频教程: + +## 🐯 平台简介 + +**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。 + +* 采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) 实现 +* 改换 saas,自动引入等功能 +* 使用 Element Plus 免费开源的中后台模版,具备如下特性: + +![首页](public/home.png) + +* **最新技术栈**:使用 Vue3、Vite4 等前端前沿技术开发 +* **TypeScript**: 应用程序级 JavaScript 的语言 +* **主题**: 可配置的主题 +* **国际化**:内置完善的国际化方案 +* **权限**:内置完善的动态路由权限生成方案 +* **组件**:二次封装了多个常用的组件 +* **示例**:内置丰富的示例 + +## 技术栈 + +| 框架 | 说明 | 版本 | +|----------------------------------------------------------------------|------------------|--------| +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.3.8 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.5.0 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.4.2 | +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 5.2.2 | +| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.1.7 | +| [vueuse](https://vueuse.org/) | 常用工具集 | 10.6.1 | +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.6.5 | +| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.2.5 | +| [unocss](https://uno.antfu.me/) | 原子 css | 0.57.4 | +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.1.1 | +| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 | + +## 开发工具 + +推荐 VS Code 开发,配合插件如下: + +| 插件名 | 功能 | +|-------------------------------|---------------------| +| Vue - Official | Vue 与 TypeScript 支持 | +| unocss | unocss for vscode | +| Iconify IntelliSense | Iconify 预览和搜索 | +| i18n Ally | 国际化智能提示 | +| Stylelint | Css 格式化 | +| Prettier | 代码格式化 | +| ESLint | 脚本代码检查 | +| DotENV | env 文件高亮 | + +## 🔥 后端架构 + +支持 Spring Boot、Spring Cloud 两种架构: + +① Spring Boot 单体架构: + +![架构图](/.image/common/ruoyi-vue-pro-architecture.png) + +② Spring Cloud 微服务架构: + +![架构图](/.image/common/yudao-cloud-architecture.png) + +## 内置功能 + +系统内置多种多种业务功能,可以用于快速你的业务系统: + +* 系统功能 +* 基础设施 +* 工作流程 +* 支付系统 +* 会员中心 +* 数据报表 +* 商城系统 +* 微信公众号 +* ERP 系统 +* CRM 系统 + +### 系统功能 + +| | 功能 | 描述 | +|-----|-------|---------------------------------| +| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 | +| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 | +| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | +| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 | +| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | +| | 岗位管理 | 配置系统用户所属担任职务 | +| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 | +| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | +| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | +| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 | +| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 | +| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | +| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | +| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | +| | 通知公告 | 系统通知公告信息发布维护 | +| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 | +| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 | +| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 | + +![功能图](/.image/common/system-feature.png) + +### 工作流程 + +| | 功能 | 描述 | +|----|-------|-----------------------------------------| +| 🚀 | 流程模型 | 配置工作流的流程模型,支持 BPMN 和仿钉钉/飞书设计器 | +| 🚀 | 流程表单 | 拖动表单元素生成相应的工作流表单,覆盖 Element UI 所有的表单组件 | +| 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 | +| 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 | +| 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转派、委派、退回、加减签等操作 | +| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,支持流程预测,展示未来审批人信息 | +| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | + +![功能图](/.image/common/bpm-feature.png) + +| BPMN 设计器 | 钉钉/飞书设计器 | +|------------------------------|--------------------------------| +| ![](/.image/工作流设计器-bpmn.jpg) | ![](/.image/工作流设计器-simple.jpg) | + +### 支付系统 + +| | 功能 | 描述 | +|-----|------|---------------------------| +| 🚀 | 商户信息 | 管理商户信息,支持 Saas 场景下的多商户功能 | +| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 | +| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 | +| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 | + +ps:核心功能已经实现,正在对接微信小程序中... + +### 基础设施 + +| | 功能 | 描述 | +|----|----------|----------------------------------------------| +| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | +| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | +| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | +| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | +| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | +| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | +| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | +| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | +| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | +| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | +| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | +| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | +| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 | +| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | +| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | + +![功能图](/.image/common/infra-feature.png) + +### 数据报表 + +| | 功能 | 描述 | +|-----|-------|--------------------| +| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 | +| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 | + +### 微信公众号 + +| | 功能 | 描述 | +|-----|--------|-------------------------------| +| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 | +| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 | +| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 | +| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 | +| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 | +| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 | +| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 | +| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 | +| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 | +| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 | + +### 商城系统 + +演示地址: + +![功能图](/.image/common/mall-feature.png) + +![功能图](/.image/common/mall-preview.png) + +### ERP 系统 + +演示地址: + +![功能图](/.image/common/erp-feature.png) + +### CRM 系统 + +演示地址: + +![功能图](/.image/common/crm-feature.png) + +## 🐷 演示图 + +### 系统功能 + +| 模块 | biu | biu | biu | +|----------|-----------------------------|---------------------------|--------------------------| +| 登录 & 首页 | ![登录](/.image/登录.jpg) | ![首页](/.image/首页.jpg) | ![个人中心](/.image/个人中心.jpg) | +| 用户 & 应用 | ![用户管理](/.image/用户管理.jpg) | ![令牌管理](/.image/令牌管理.jpg) | ![应用管理](/.image/应用管理.jpg) | +| 租户 & 套餐 | ![租户管理](/.image/租户管理.jpg) | ![租户套餐](/.image/租户套餐.png) | - | +| 部门 & 岗位 | ![部门管理](/.image/部门管理.jpg) | ![岗位管理](/.image/岗位管理.jpg) | - | +| 菜单 & 角色 | ![菜单管理](/.image/菜单管理.jpg) | ![角色管理](/.image/角色管理.jpg) | - | +| 审计日志 | ![操作日志](/.image/操作日志.jpg) | ![登录日志](/.image/登录日志.jpg) | - | +| 短信 | ![短信渠道](/.image/短信渠道.jpg) | ![短信模板](/.image/短信模板.jpg) | ![短信日志](/.image/短信日志.jpg) | +| 字典 & 敏感词 | ![字典类型](/.image/字典类型.jpg) | ![字典数据](/.image/字典数据.jpg) | ![敏感词](/.image/敏感词.jpg) | +| 错误码 & 通知 | ![错误码管理](/.image/错误码管理.jpg) | ![通知公告](/.image/通知公告.jpg) | - | + +### 工作流程 + +| 模块 | biu | biu | biu | +|---------|---------------------------------|---------------------------------|---------------------------------| +| 流程模型 | ![流程模型-列表](/.image/流程模型-列表.jpg) | ![流程模型-设计](/.image/流程模型-设计.jpg) | ![流程模型-定义](/.image/流程模型-定义.jpg) | +| 表单 & 分组 | ![流程表单](/.image/流程表单.jpg) | ![用户分组](/.image/用户分组.jpg) | - | +| 我的流程 | ![我的流程-列表](/.image/我的流程-列表.jpg) | ![我的流程-发起](/.image/我的流程-发起.jpg) | ![我的流程-详情](/.image/我的流程-详情.jpg) | +| 待办 & 已办 | ![任务列表-审批](/.image/任务列表-审批.jpg) | ![任务列表-待办](/.image/任务列表-待办.jpg) | ![任务列表-已办](/.image/任务列表-已办.jpg) | +| OA 请假 | ![OA请假-列表](/.image/OA请假-列表.jpg) | ![OA请假-发起](/.image/OA请假-发起.jpg) | ![OA请假-详情](/.image/OA请假-详情.jpg) | + +### 基础设施 + +| 模块 | biu | biu | biu | +|---------------|-------------------------------|-----------------------------|---------------------------| +| 代码生成 | ![代码生成](/.image/代码生成.jpg) | ![生成效果](/.image/生成效果.jpg) | - | +| 文档 | ![系统接口](/.image/系统接口.jpg) | ![数据库文档](/.image/数据库文档.jpg) | - | +| 文件 & 配置 | ![文件配置](/.image/文件配置.jpg) | ![文件管理](/.image/文件管理2.jpg) | ![配置管理](/.image/配置管理.jpg) | +| 定时任务 | ![定时任务](/.image/定时任务.jpg) | ![任务日志](/.image/任务日志.jpg) | - | +| API 日志 | ![访问日志](/.image/访问日志.jpg) | ![错误日志](/.image/错误日志.jpg) | - | +| MySQL & Redis | ![MySQL](/.image/MySQL.jpg) | ![Redis](/.image/Redis.jpg) | - | +| 监控平台 | ![Java监控](/.image/Java监控.jpg) | ![链路追踪](/.image/链路追踪.jpg) | ![日志中心](/.image/日志中心.jpg) | + +### 支付系统 + +| 模块 | biu | biu | biu | +|---------|---------------------------|---------------------------------|---------------------------------| +| 商家 & 应用 | ![商户信息](/.image/商户信息.jpg) | ![应用信息-列表](/.image/应用信息-列表.jpg) | ![应用信息-编辑](/.image/应用信息-编辑.jpg) | +| 支付 & 退款 | ![支付订单](/.image/支付订单.jpg) | ![退款订单](/.image/退款订单.jpg) | --- | + +### 数据报表 + +| 模块 | biu | biu | biu | +|-------|---------------------------------|---------------------------------|---------------------------------------| +| 报表设计器 | ![数据报表](/.image/报表设计器-数据报表.jpg) | ![图形报表](/.image/报表设计器-图形报表.jpg) | ![报表设计器-打印设计](/.image/报表设计器-打印设计.jpg) | +| 大屏设计器 | ![大屏列表](/.image/大屏设计器-列表.jpg) | ![大屏预览](/.image/大屏设计器-预览.jpg) | ![大屏编辑](/.image/大屏设计器-编辑.jpg) | diff --git a/build/vite/index.ts b/build/vite/index.ts new file mode 100644 index 0000000..585759f --- /dev/null +++ b/build/vite/index.ts @@ -0,0 +1,100 @@ +import { resolve } from 'path' +import Vue from '@vitejs/plugin-vue' +import VueJsx from '@vitejs/plugin-vue-jsx' +import progress from 'vite-plugin-progress' +import EslintPlugin from 'vite-plugin-eslint' +import PurgeIcons from 'vite-plugin-purge-icons' +import { ViteEjsPlugin } from 'vite-plugin-ejs' +// @ts-ignore +import ElementPlus from 'unplugin-element-plus/vite' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import viteCompression from 'vite-plugin-compression' +import topLevelAwait from 'vite-plugin-top-level-await' +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import UnoCSS from 'unocss/vite' + +export function createVitePlugins() { + const root = process.cwd() + + // 路径查找 + function pathResolve(dir: string) { + return resolve(root, '.', dir) + } + + return [ + Vue(), + VueJsx(), + UnoCSS(), + progress(), + PurgeIcons(), + ElementPlus({}), + AutoImport({ + include: [ + /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx + /\.vue$/, + /\.vue\?vue/, // .vue + /\.md$/ // .md + ], + imports: [ + 'vue', + 'vue-router', + // 可额外添加需要 autoImport 的组件 + { + '@/hooks/web/useI18n': ['useI18n'], + '@/hooks/web/useMessage': ['useMessage'], + '@/hooks/web/useTable': ['useTable'], + '@/hooks/web/useCrudSchemas': ['useCrudSchemas'], + '@/utils/formRules': ['required'], + '@/utils/dict': ['DICT_TYPE'] + } + ], + dts: 'src/types/auto-imports.d.ts', + resolvers: [ElementPlusResolver()], + eslintrc: { + enabled: false, // Default `false` + filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json` + globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') + } + }), + Components({ + // 生成自定义 `auto-components.d.ts` 全局声明 + dts: 'src/types/auto-components.d.ts', + // 自定义组件的解析器 + resolvers: [ElementPlusResolver()], + globs: ["src/components/**/**.{vue, md}", '!src/components/DiyEditor/components/mobile/**'] + }), + EslintPlugin({ + cache: false, + include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件 + }), + VueI18nPlugin({ + runtimeOnly: true, + compositionOnly: true, + include: [resolve(__dirname, 'src/locales/**')] + }), + createSvgIconsPlugin({ + iconDirs: [pathResolve('src/assets/svgs')], + symbolId: 'icon-[dir]-[name]', + svgoOptions: true + }), + viteCompression({ + verbose: true, // 是否在控制台输出压缩结果 + disable: false, // 是否禁用 + threshold: 10240, // 体积大于 threshold 才会被压缩,单位 b + algorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw'] + ext: '.gz', // 生成的压缩包后缀 + deleteOriginFile: false //压缩后是否删除源文件 + }), + ViteEjsPlugin(), + topLevelAwait({ + // https://juejin.cn/post/7152191742513512485 + // The export name of top-level await promise for each chunk module + promiseExportName: '__tla', + // The function to generate import names of top-level await promise in each chunk module + promiseImportName: (i) => `__tla_${i}` + }) + ] +} diff --git a/build/vite/optimize.ts b/build/vite/optimize.ts new file mode 100644 index 0000000..aa7e68c --- /dev/null +++ b/build/vite/optimize.ts @@ -0,0 +1,122 @@ +const include = [ + 'qs', + 'url', + 'vue', + 'sass', + 'mitt', + 'axios', + 'pinia', + 'dayjs', + 'qrcode', + 'unocss', + 'vue-router', + 'vue-types', + 'vue-i18n', + 'crypto-js', + 'cropperjs', + 'lodash-es', + 'nprogress', + 'web-storage-cache', + '@iconify/iconify', + '@vueuse/core', + '@zxcvbn-ts/core', + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'echarts-wordcloud', + '@wangeditor/editor', + '@wangeditor/editor-for-vue', + '@microsoft/fetch-event-source', + 'markdown-it', + 'markmap-view', + 'markmap-lib', + 'markmap-toolbar', + 'highlight.js', + 'element-plus', + 'element-plus/es', + 'element-plus/es/locale/lang/zh-cn', + 'element-plus/es/locale/lang/en', + 'element-plus/es/components/avatar/style/css', + 'element-plus/es/components/space/style/css', + 'element-plus/es/components/backtop/style/css', + 'element-plus/es/components/form/style/css', + 'element-plus/es/components/radio-group/style/css', + 'element-plus/es/components/radio/style/css', + 'element-plus/es/components/checkbox/style/css', + 'element-plus/es/components/checkbox-group/style/css', + 'element-plus/es/components/switch/style/css', + 'element-plus/es/components/time-picker/style/css', + 'element-plus/es/components/date-picker/style/css', + 'element-plus/es/components/descriptions/style/css', + 'element-plus/es/components/descriptions-item/style/css', + 'element-plus/es/components/link/style/css', + 'element-plus/es/components/tooltip/style/css', + 'element-plus/es/components/drawer/style/css', + 'element-plus/es/components/dialog/style/css', + 'element-plus/es/components/checkbox-button/style/css', + 'element-plus/es/components/option-group/style/css', + 'element-plus/es/components/radio-button/style/css', + 'element-plus/es/components/cascader/style/css', + 'element-plus/es/components/color-picker/style/css', + 'element-plus/es/components/input-number/style/css', + 'element-plus/es/components/rate/style/css', + 'element-plus/es/components/select-v2/style/css', + 'element-plus/es/components/tree-select/style/css', + 'element-plus/es/components/slider/style/css', + 'element-plus/es/components/time-select/style/css', + 'element-plus/es/components/autocomplete/style/css', + 'element-plus/es/components/image-viewer/style/css', + 'element-plus/es/components/upload/style/css', + 'element-plus/es/components/col/style/css', + 'element-plus/es/components/form-item/style/css', + 'element-plus/es/components/alert/style/css', + 'element-plus/es/components/breadcrumb/style/css', + 'element-plus/es/components/select/style/css', + 'element-plus/es/components/input/style/css', + 'element-plus/es/components/breadcrumb-item/style/css', + 'element-plus/es/components/tag/style/css', + 'element-plus/es/components/pagination/style/css', + 'element-plus/es/components/table/style/css', + 'element-plus/es/components/table-v2/style/css', + 'element-plus/es/components/table-column/style/css', + 'element-plus/es/components/card/style/css', + 'element-plus/es/components/row/style/css', + 'element-plus/es/components/button/style/css', + 'element-plus/es/components/menu/style/css', + 'element-plus/es/components/sub-menu/style/css', + 'element-plus/es/components/menu-item/style/css', + 'element-plus/es/components/option/style/css', + 'element-plus/es/components/dropdown/style/css', + 'element-plus/es/components/dropdown-menu/style/css', + 'element-plus/es/components/dropdown-item/style/css', + 'element-plus/es/components/skeleton/style/css', + 'element-plus/es/components/skeleton/style/css', + 'element-plus/es/components/backtop/style/css', + 'element-plus/es/components/menu/style/css', + 'element-plus/es/components/sub-menu/style/css', + 'element-plus/es/components/menu-item/style/css', + 'element-plus/es/components/dropdown/style/css', + 'element-plus/es/components/tree/style/css', + 'element-plus/es/components/dropdown-menu/style/css', + 'element-plus/es/components/dropdown-item/style/css', + 'element-plus/es/components/badge/style/css', + 'element-plus/es/components/breadcrumb/style/css', + 'element-plus/es/components/breadcrumb-item/style/css', + 'element-plus/es/components/image/style/css', + 'element-plus/es/components/collapse-transition/style/css', + 'element-plus/es/components/timeline/style/css', + 'element-plus/es/components/timeline-item/style/css', + 'element-plus/es/components/collapse/style/css', + 'element-plus/es/components/collapse-item/style/css', + 'element-plus/es/components/button-group/style/css', + 'element-plus/es/components/text/style/css', + 'element-plus/es/components/segmented/style/css', + '@element-plus/icons-vue', + 'element-plus/es/components/footer/style/css', + 'element-plus/es/components/empty/style/css' +] + +const exclude = ['@iconify/json'] + +export { include, exclude } diff --git a/index.html b/index.html new file mode 100644 index 0000000..8cfcbef --- /dev/null +++ b/index.html @@ -0,0 +1,151 @@ + + + + + + + + + + %VITE_APP_TITLE% + + +
+ +
+
+
+ +
%VITE_APP_TITLE%
+
+
+
+
+
+
+
+
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..ff94abd --- /dev/null +++ b/package.json @@ -0,0 +1,152 @@ +{ + "name": "yudao-ui-admin-vue3", + "version": "2.4.0-snapshot", + "description": "基于vue3、vite4、element-plus、typesScript", + "author": "xingyu", + "private": false, + "scripts": { + "i": "pnpm install", + "dev": "vite --mode env.local", + "dev-server": "vite --mode dev", + "ts:check": "vue-tsc --noEmit", + "build:local": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build", + "build:dev": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode dev", + "build:test": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode test", + "build:stage": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode stage", + "build:prod": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode prod", + "serve:dev": "vite preview --mode dev", + "serve:prod": "vite preview --mode prod", + "preview": "pnpm build:local && vite preview", + "clean": "npx rimraf node_modules", + "clean:cache": "npx rimraf node_modules/.cache", + "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src", + "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"", + "lint:style": "stylelint --fix \"./src/**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", + "lint:lint-staged": "lint-staged -c " + }, + "dependencies": { + "@element-plus/icons-vue": "^2.1.0", + "@form-create/designer": "^3.2.6", + "@form-create/element-ui": "^3.2.11", + "@iconify/iconify": "^3.1.1", + "@microsoft/fetch-event-source": "^2.0.1", + "@videojs-player/vue": "^1.0.0", + "@vueuse/core": "^10.9.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.10", + "@zxcvbn-ts/core": "^3.0.4", + "animate.css": "^4.1.1", + "axios": "^1.6.8", + "benz-amr-recorder": "^1.1.5", + "bpmn-js-token-simulation": "^0.36.0", + "camunda-bpmn-moddle": "^7.0.1", + "cropperjs": "^1.6.1", + "crypto-js": "^4.2.0", + "dayjs": "^1.11.10", + "diagram-js": "^12.8.0", + "driver.js": "^1.3.1", + "echarts": "^5.5.0", + "echarts-wordcloud": "^2.1.0", + "element-plus": "2.9.1", + "fast-xml-parser": "^4.3.2", + "highlight.js": "^11.9.0", + "jsencrypt": "^3.3.2", + "lodash-es": "^4.17.21", + "markdown-it": "^14.1.0", + "markmap-common": "^0.16.0", + "markmap-lib": "^0.16.1", + "markmap-toolbar": "^0.17.0", + "markmap-view": "^0.16.0", + "min-dash": "^4.1.1", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "qrcode": "^1.5.3", + "qs": "^6.12.0", + "sortablejs": "^1.15.3", + "steady-xml": "^0.1.0", + "url": "^0.11.3", + "video.js": "^7.21.5", + "vue": "3.5.12", + "vue-dompurify-html": "^4.1.4", + "vue-i18n": "9.10.2", + "vue-router": "4.4.5", + "vue-types": "^5.1.1", + "vuedraggable": "^4.1.0", + "web-storage-cache": "^1.1.1", + "xml-js": "^1.6.11" + }, + "devDependencies": { + "@commitlint/cli": "^19.0.1", + "@commitlint/config-conventional": "^19.0.0", + "@iconify/json": "^2.2.187", + "@intlify/unplugin-vue-i18n": "^2.0.0", + "@purge-icons/generated": "^0.9.0", + "@types/lodash-es": "^4.17.12", + "@types/node": "^20.11.21", + "@types/nprogress": "^0.2.3", + "@types/qrcode": "^1.5.5", + "@types/qs": "^6.9.12", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", + "@unocss/eslint-config": "^0.57.4", + "@unocss/transformer-variant-group": "^0.58.5", + "@vitejs/plugin-legacy": "^5.3.1", + "@vitejs/plugin-vue": "^5.0.4", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "autoprefixer": "^10.4.17", + "bpmn-js": "^17.9.2", + "bpmn-js-properties-panel": "5.23.0", + "consola": "^3.2.3", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-define-config": "^2.1.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-vue": "^9.22.0", + "lint-staged": "^15.2.2", + "postcss": "^8.4.35", + "postcss-html": "^1.6.0", + "postcss-scss": "^4.0.9", + "prettier": "^3.2.5", + "prettier-eslint": "^16.3.0", + "rimraf": "^5.0.5", + "rollup": "^4.12.0", + "sass": "^1.69.5", + "stylelint": "^16.2.1", + "stylelint-config-html": "^1.1.0", + "stylelint-config-recommended": "^14.0.0", + "stylelint-config-standard": "^36.0.0", + "stylelint-order": "^6.0.4", + "terser": "^5.28.1", + "typescript": "5.3.3", + "unocss": "^0.58.5", + "unplugin-auto-import": "^0.16.7", + "unplugin-element-plus": "^0.8.0", + "unplugin-vue-components": "^0.25.2", + "vite": "5.1.4", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-ejs": "^1.7.0", + "vite-plugin-eslint": "^1.8.1", + "vite-plugin-progress": "^0.0.7", + "vite-plugin-purge-icons": "^0.10.0", + "vite-plugin-svg-icons": "^2.0.1", + "vite-plugin-top-level-await": "^1.4.4", + "vue-eslint-parser": "^9.3.2", + "vue-tsc": "^1.8.27" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://gitee.com/yudaocode/yudao-ui-admin-vue3" + }, + "bugs": { + "url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues" + }, + "homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3", + "web-types": "./web-types.json", + "engines": { + "node": ">= 16.0.0", + "pnpm": ">=8.6.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..e765514 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10559 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@element-plus/icons-vue': + specifier: ^2.1.0 + version: 2.3.1(vue@3.5.12) + '@form-create/designer': + specifier: ^3.2.6 + version: 3.2.8(vue@3.5.12) + '@form-create/element-ui': + specifier: ^3.2.11 + version: 3.2.14(vue@3.5.12) + '@iconify/iconify': + specifier: ^3.1.1 + version: 3.1.1 + '@microsoft/fetch-event-source': + specifier: ^2.0.1 + version: 2.0.1 + '@videojs-player/vue': + specifier: ^1.0.0 + version: 1.0.0(@types/video.js@7.3.58)(video.js@7.21.6)(vue@3.5.12) + '@vueuse/core': + specifier: ^10.9.0 + version: 10.11.1(vue@3.5.12) + '@wangeditor/editor': + specifier: ^5.1.23 + version: 5.1.23 + '@wangeditor/editor-for-vue': + specifier: ^5.1.10 + version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.12) + '@zxcvbn-ts/core': + specifier: ^3.0.4 + version: 3.0.4 + animate.css: + specifier: ^4.1.1 + version: 4.1.1 + axios: + specifier: ^1.6.8 + version: 1.7.8 + benz-amr-recorder: + specifier: ^1.1.5 + version: 1.1.5 + bpmn-js-token-simulation: + specifier: ^0.36.0 + version: 0.36.0 + camunda-bpmn-moddle: + specifier: ^7.0.1 + version: 7.0.1 + cropperjs: + specifier: ^1.6.1 + version: 1.6.2 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + dayjs: + specifier: ^1.11.10 + version: 1.11.13 + diagram-js: + specifier: ^12.8.0 + version: 12.8.1 + driver.js: + specifier: ^1.3.1 + version: 1.3.1 + echarts: + specifier: ^5.5.0 + version: 5.5.1 + echarts-wordcloud: + specifier: ^2.1.0 + version: 2.1.0(echarts@5.5.1) + element-plus: + specifier: 2.9.1 + version: 2.9.1(vue@3.5.12) + fast-xml-parser: + specifier: ^4.3.2 + version: 4.5.0 + highlight.js: + specifier: ^11.9.0 + version: 11.10.0 + jsencrypt: + specifier: ^3.3.2 + version: 3.3.2 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + markdown-it: + specifier: ^14.1.0 + version: 14.1.0 + markmap-common: + specifier: ^0.16.0 + version: 0.16.0 + markmap-lib: + specifier: ^0.16.1 + version: 0.16.1(markmap-common@0.16.0) + markmap-toolbar: + specifier: ^0.17.0 + version: 0.17.2(markmap-common@0.16.0) + markmap-view: + specifier: ^0.16.0 + version: 0.16.0(markmap-common@0.16.0) + min-dash: + specifier: ^4.1.1 + version: 4.2.2 + mitt: + specifier: ^3.0.1 + version: 3.0.1 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + pinia: + specifier: ^2.1.7 + version: 2.2.8(typescript@5.3.3)(vue@3.5.12) + pinia-plugin-persistedstate: + specifier: ^3.2.1 + version: 3.2.3(pinia@2.2.8) + qrcode: + specifier: ^1.5.3 + version: 1.5.4 + qs: + specifier: ^6.12.0 + version: 6.13.1 + sortablejs: + specifier: ^1.15.3 + version: 1.15.6 + steady-xml: + specifier: ^0.1.0 + version: 0.1.0 + url: + specifier: ^0.11.3 + version: 0.11.4 + video.js: + specifier: ^7.21.5 + version: 7.21.6 + vue: + specifier: 3.5.12 + version: 3.5.12(typescript@5.3.3) + vue-dompurify-html: + specifier: ^4.1.4 + version: 4.1.4(vue@3.5.12) + vue-i18n: + specifier: 9.10.2 + version: 9.10.2(vue@3.5.12) + vue-router: + specifier: 4.4.5 + version: 4.4.5(vue@3.5.12) + vue-types: + specifier: ^5.1.1 + version: 5.1.3(vue@3.5.12) + vuedraggable: + specifier: ^4.1.0 + version: 4.1.0(vue@3.5.12) + web-storage-cache: + specifier: ^1.1.1 + version: 1.1.1 + xml-js: + specifier: ^1.6.11 + version: 1.6.11 + +devDependencies: + '@commitlint/cli': + specifier: ^19.0.1 + version: 19.6.0(@types/node@20.17.9)(typescript@5.3.3) + '@commitlint/config-conventional': + specifier: ^19.0.0 + version: 19.6.0 + '@iconify/json': + specifier: ^2.2.187 + version: 2.2.277 + '@intlify/unplugin-vue-i18n': + specifier: ^2.0.0 + version: 2.0.0(rollup@4.27.4)(vue-i18n@9.10.2) + '@purge-icons/generated': + specifier: ^0.9.0 + version: 0.9.0 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/node': + specifier: ^20.11.21 + version: 20.17.9 + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 + '@types/qrcode': + specifier: ^1.5.5 + version: 1.5.5 + '@types/qs': + specifier: ^6.9.12 + version: 6.9.17 + '@typescript-eslint/eslint-plugin': + specifier: ^7.1.0 + version: 7.18.0(@typescript-eslint/parser@7.18.0)(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: ^7.1.0 + version: 7.18.0(eslint@8.57.1)(typescript@5.3.3) + '@unocss/eslint-config': + specifier: ^0.57.4 + version: 0.57.7(eslint@8.57.1)(typescript@5.3.3) + '@unocss/transformer-variant-group': + specifier: ^0.58.5 + version: 0.58.9 + '@vitejs/plugin-legacy': + specifier: ^5.3.1 + version: 5.4.3(terser@5.36.0)(vite@5.1.4) + '@vitejs/plugin-vue': + specifier: ^5.0.4 + version: 5.2.1(vite@5.1.4)(vue@3.5.12) + '@vitejs/plugin-vue-jsx': + specifier: ^3.1.0 + version: 3.1.0(vite@5.1.4)(vue@3.5.12) + autoprefixer: + specifier: ^10.4.17 + version: 10.4.20(postcss@8.4.49) + bpmn-js: + specifier: ^17.9.2 + version: 17.11.1 + bpmn-js-properties-panel: + specifier: 5.23.0 + version: 5.23.0(@bpmn-io/properties-panel@3.25.0)(bpmn-js@17.11.1)(camunda-bpmn-js-behaviors@1.7.2)(diagram-js@12.8.1) + consola: + specifier: ^3.2.3 + version: 3.2.3 + eslint: + specifier: ^8.57.0 + version: 8.57.1 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.1) + eslint-define-config: + specifier: ^2.1.0 + version: 2.1.0 + eslint-plugin-prettier: + specifier: ^5.1.3 + version: 5.2.1(eslint-config-prettier@9.1.0)(eslint@8.57.1)(prettier@3.4.1) + eslint-plugin-vue: + specifier: ^9.22.0 + version: 9.31.0(eslint@8.57.1) + lint-staged: + specifier: ^15.2.2 + version: 15.2.10 + postcss: + specifier: ^8.4.35 + version: 8.4.49 + postcss-html: + specifier: ^1.6.0 + version: 1.7.0 + postcss-scss: + specifier: ^4.0.9 + version: 4.0.9(postcss@8.4.49) + prettier: + specifier: ^3.2.5 + version: 3.4.1 + prettier-eslint: + specifier: ^16.3.0 + version: 16.3.0 + rimraf: + specifier: ^5.0.5 + version: 5.0.10 + rollup: + specifier: ^4.12.0 + version: 4.27.4 + sass: + specifier: ^1.69.5 + version: 1.81.0 + stylelint: + specifier: ^16.2.1 + version: 16.11.0(typescript@5.3.3) + stylelint-config-html: + specifier: ^1.1.0 + version: 1.1.0(postcss-html@1.7.0)(stylelint@16.11.0) + stylelint-config-recommended: + specifier: ^14.0.0 + version: 14.0.1(stylelint@16.11.0) + stylelint-config-standard: + specifier: ^36.0.0 + version: 36.0.1(stylelint@16.11.0) + stylelint-order: + specifier: ^6.0.4 + version: 6.0.4(stylelint@16.11.0) + terser: + specifier: ^5.28.1 + version: 5.36.0 + typescript: + specifier: 5.3.3 + version: 5.3.3 + unocss: + specifier: ^0.58.5 + version: 0.58.9(postcss@8.4.49)(rollup@4.27.4)(vite@5.1.4) + unplugin-auto-import: + specifier: ^0.16.7 + version: 0.16.7(@vueuse/core@10.11.1)(rollup@4.27.4) + unplugin-element-plus: + specifier: ^0.8.0 + version: 0.8.0(rollup@4.27.4) + unplugin-vue-components: + specifier: ^0.25.2 + version: 0.25.2(rollup@4.27.4)(vue@3.5.12) + vite: + specifier: 5.1.4 + version: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1(vite@5.1.4) + vite-plugin-ejs: + specifier: ^1.7.0 + version: 1.7.0(vite@5.1.4) + vite-plugin-eslint: + specifier: ^1.8.1 + version: 1.8.1(eslint@8.57.1)(vite@5.1.4) + vite-plugin-progress: + specifier: ^0.0.7 + version: 0.0.7(vite@5.1.4) + vite-plugin-purge-icons: + specifier: ^0.10.0 + version: 0.10.0(vite@5.1.4) + vite-plugin-svg-icons: + specifier: ^2.0.1 + version: 2.0.1(vite@5.1.4) + vite-plugin-top-level-await: + specifier: ^1.4.4 + version: 1.4.4(rollup@4.27.4)(vite@5.1.4) + vue-eslint-parser: + specifier: ^9.3.2 + version: 9.4.3(eslint@8.57.1) + vue-tsc: + specifier: ^1.8.27 + version: 1.8.27(typescript@5.3.3) + +packages: + + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@antfu/install-pkg@0.4.1: + resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} + dependencies: + package-manager-detector: 0.2.5 + tinyexec: 0.3.1 + dev: true + + /@antfu/utils@0.7.10: + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + dev: true + + /@babel/code-frame@7.26.2: + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + dev: true + + /@babel/compat-data@7.26.2: + resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.26.0: + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + convert-source-map: 2.0.0 + debug: 4.3.7 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.26.2: + resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 + dev: true + + /@babel/helper-annotate-as-pure@7.25.9: + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.26.0 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.25.9: + resolution: {integrity: sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-compilation-targets@7.25.9: + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.26.2 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.25.9 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + dev: true + + /@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.0): + resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + debug: 4.3.7 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-member-expression-to-functions@7.25.9: + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-module-imports@7.25.9: + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-optimise-call-expression@7.25.9: + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.26.0 + dev: true + + /@babel/helper-plugin-utils@7.25.9: + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access@7.25.9: + resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.25.9: + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-string-parser@7.25.9: + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier@7.25.9: + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.25.9: + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.25.9: + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helpers@7.26.0: + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + dev: true + + /@babel/parser@7.26.2: + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.26.0 + + /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0): + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + dev: true + + /@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0): + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/traverse': 7.25.9 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/template': 7.25.9 + dev: true + + /@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-simple-access': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) + dev: true + + /@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + regenerator-transform: 0.15.2 + dev: true + + /@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-typescript@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0): + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + dev: true + + /@babel/preset-env@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.26.2 + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0) + babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.0) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.0) + core-js-compat: 3.39.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0): + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/types': 7.26.0 + esutils: 2.0.3 + dev: true + + /@babel/preset-typescript@7.26.0(@babel/core@7.26.0): + resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/runtime-corejs3@7.26.0: + resolution: {integrity: sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.39.0 + regenerator-runtime: 0.14.1 + dev: false + + /@babel/runtime@7.26.0: + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + + /@babel/template@7.25.9: + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + dev: true + + /@babel/traverse@7.25.9: + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + debug: 4.3.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.26.0: + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + /@bpmn-io/cm-theme@0.1.0-alpha.2: + resolution: {integrity: sha512-ZILgiYzxk3KMvxplUXmdRFQo45/JehDPg5k9tWfehmzUOSE13ssyLPil8uCloMQnb3yyzyOWTjb/wzKXTHlFQw==} + dependencies: + '@codemirror/language': 6.10.6 + '@codemirror/view': 6.35.0 + '@lezer/highlight': 1.2.1 + dev: true + + /@bpmn-io/diagram-js-ui@0.2.3: + resolution: {integrity: sha512-OGyjZKvGK8tHSZ0l7RfeKhilGoOGtFDcoqSGYkX0uhFlo99OVZ9Jn1K7TJGzcE9BdKwvA5Y5kGqHEhdTxHvFfw==} + dependencies: + htm: 3.1.1 + preact: 10.25.0 + + /@bpmn-io/extract-process-variables@0.8.0: + resolution: {integrity: sha512-yAS7ZYX+D56K+luC36u96eRMLb4VHcPUwTUqMZ/Z/Je2gou2DJLRbuBTHAB4jjKt4wFCHSG4B8Y+TrBciEYf4w==} + dependencies: + min-dash: 4.2.2 + dev: true + + /@bpmn-io/feel-editor@1.9.1(@lezer/common@1.2.3): + resolution: {integrity: sha512-UxSORdh5cwKM4fib4f9ov6J1/BHGpQVNtA+wPyEdKQyCyz3wqwE2/xe5wneVR1j5QFC5m2Na8nTy4a1TDFvZTw==} + engines: {node: '>= 16'} + dependencies: + '@bpmn-io/feel-lint': 1.3.1 + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3) + '@codemirror/commands': 6.7.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/highlight': 1.2.1 + lang-feel: 2.2.0 + min-dom: 4.2.1 + transitivePeerDependencies: + - '@lezer/common' + dev: true + + /@bpmn-io/feel-lint@1.3.1: + resolution: {integrity: sha512-wcFkJKhOm/iqCt5bzkKvxL5Dr9wKwUD+t164bQYbJsTYouAqmkkxiGsoqck42hXwdIhMSguZ+vqQ3hj5QdiYCA==} + dependencies: + '@codemirror/language': 6.10.6 + lezer-feel: 1.4.0 + dev: true + + /@bpmn-io/properties-panel@3.25.0(@lezer/common@1.2.3): + resolution: {integrity: sha512-SRGgj8uJc1Yyjcht2g36Q+xKR7sTx5VZXvcwDrdmQKlx5Y3nRmvmMjDGzeGDJDb7pNU1DSlaBJic84uISDBMWg==} + dependencies: + '@bpmn-io/feel-editor': 1.9.1(@lezer/common@1.2.3) + '@codemirror/view': 6.35.0 + classnames: 2.5.1 + feelers: 1.4.0 + focus-trap: 7.6.2 + min-dash: 4.2.2 + min-dom: 4.2.1 + transitivePeerDependencies: + - '@lezer/common' + dev: true + + /@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3): + resolution: {integrity: sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/common': ^1.0.0 + dependencies: + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/common': 1.2.3 + dev: true + + /@codemirror/commands@6.7.1: + resolution: {integrity: sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==} + dependencies: + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/common': 1.2.3 + dev: true + + /@codemirror/language@6.10.6: + resolution: {integrity: sha512-KrsbdCnxEztLVbB5PycWXFxas4EOyk/fPAfruSOnDDppevQgid2XZ+KbJ9u+fDikP/e7MW7HPBTvTb8JlZK9vA==} + dependencies: + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + style-mod: 4.1.2 + dev: true + + /@codemirror/lint@6.8.4: + resolution: {integrity: sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==} + dependencies: + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + crelt: 1.0.6 + dev: true + + /@codemirror/state@6.4.1: + resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==} + dev: true + + /@codemirror/view@6.35.0: + resolution: {integrity: sha512-I0tYy63q5XkaWsJ8QRv5h6ves7kvtrBWjBcnf/bzohFJQc5c14a1AQRdE8QpPF9eMp5Mq2FMm59TCj1gDfE7kw==} + dependencies: + '@codemirror/state': 6.4.1 + style-mod: 4.1.2 + w3c-keyname: 2.2.8 + dev: true + + /@commitlint/cli@19.6.0(@types/node@20.17.9)(typescript@5.3.3): + resolution: {integrity: sha512-v17BgGD9w5KnthaKxXnEg6KLq6DYiAxyiN44TpiRtqyW8NSq+Kx99mkEG8Qo6uu6cI5eMzMojW2muJxjmPnF8w==} + engines: {node: '>=v18'} + hasBin: true + dependencies: + '@commitlint/format': 19.5.0 + '@commitlint/lint': 19.6.0 + '@commitlint/load': 19.5.0(@types/node@20.17.9)(typescript@5.3.3) + '@commitlint/read': 19.5.0 + '@commitlint/types': 19.5.0 + tinyexec: 0.3.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + + /@commitlint/config-conventional@19.6.0: + resolution: {integrity: sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + conventional-changelog-conventionalcommits: 7.0.2 + dev: true + + /@commitlint/config-validator@19.5.0: + resolution: {integrity: sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + ajv: 8.17.1 + dev: true + + /@commitlint/ensure@19.5.0: + resolution: {integrity: sha512-Kv0pYZeMrdg48bHFEU5KKcccRfKmISSm9MvgIgkpI6m+ohFTB55qZlBW6eYqh/XDfRuIO0x4zSmvBjmOwWTwkg==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + dev: true + + /@commitlint/execute-rule@19.5.0: + resolution: {integrity: sha512-aqyGgytXhl2ejlk+/rfgtwpPexYyri4t8/n4ku6rRJoRhGZpLFMqrZ+YaubeGysCP6oz4mMA34YSTaSOKEeNrg==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/format@19.5.0: + resolution: {integrity: sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + chalk: 5.3.0 + dev: true + + /@commitlint/is-ignored@19.6.0: + resolution: {integrity: sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + semver: 7.6.3 + dev: true + + /@commitlint/lint@19.6.0: + resolution: {integrity: sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/is-ignored': 19.6.0 + '@commitlint/parse': 19.5.0 + '@commitlint/rules': 19.6.0 + '@commitlint/types': 19.5.0 + dev: true + + /@commitlint/load@19.5.0(@types/node@20.17.9)(typescript@5.3.3): + resolution: {integrity: sha512-INOUhkL/qaKqwcTUvCE8iIUf5XHsEPCLY9looJ/ipzi7jtGhgmtH7OOFiNvwYgH7mA8osUWOUDV8t4E2HAi4xA==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/config-validator': 19.5.0 + '@commitlint/execute-rule': 19.5.0 + '@commitlint/resolve-extends': 19.5.0 + '@commitlint/types': 19.5.0 + chalk: 5.3.0 + cosmiconfig: 9.0.0(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.1.0(@types/node@20.17.9)(cosmiconfig@9.0.0)(typescript@5.3.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + + /@commitlint/message@19.5.0: + resolution: {integrity: sha512-R7AM4YnbxN1Joj1tMfCyBryOC5aNJBdxadTZkuqtWi3Xj0kMdutq16XQwuoGbIzL2Pk62TALV1fZDCv36+JhTQ==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/parse@19.5.0: + resolution: {integrity: sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.5.0 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + dev: true + + /@commitlint/read@19.5.0: + resolution: {integrity: sha512-TjS3HLPsLsxFPQj6jou8/CZFAmOP2y+6V4PGYt3ihbQKTY1Jnv0QG28WRKl/d1ha6zLODPZqsxLEov52dhR9BQ==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/top-level': 19.5.0 + '@commitlint/types': 19.5.0 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 0.3.1 + dev: true + + /@commitlint/resolve-extends@19.5.0: + resolution: {integrity: sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/config-validator': 19.5.0 + '@commitlint/types': 19.5.0 + global-directory: 4.0.1 + import-meta-resolve: 4.1.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + dev: true + + /@commitlint/rules@19.6.0: + resolution: {integrity: sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/ensure': 19.5.0 + '@commitlint/message': 19.5.0 + '@commitlint/to-lines': 19.5.0 + '@commitlint/types': 19.5.0 + dev: true + + /@commitlint/to-lines@19.5.0: + resolution: {integrity: sha512-R772oj3NHPkodOSRZ9bBVNq224DOxQtNef5Pl8l2M8ZnkkzQfeSTr4uxawV2Sd3ui05dUVzvLNnzenDBO1KBeQ==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/top-level@19.5.0: + resolution: {integrity: sha512-IP1YLmGAk0yWrImPRRc578I3dDUI5A2UBJx9FbSOjxe9sTlzFiwVJ+zeMLgAtHMtGZsC8LUnzmW1qRemkFU4ng==} + engines: {node: '>=v18'} + dependencies: + find-up: 7.0.0 + dev: true + + /@commitlint/types@19.5.0: + resolution: {integrity: sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==} + engines: {node: '>=v18'} + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.3.0 + dev: true + + /@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3): + resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.3 + dependencies: + '@csstools/css-tokenizer': 3.0.3 + dev: true + + /@csstools/css-tokenizer@3.0.3: + resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + engines: {node: '>=18'} + dev: true + + /@csstools/media-query-list-parser@4.0.2(@csstools/css-parser-algorithms@3.0.4)(@csstools/css-tokenizer@3.0.3): + resolution: {integrity: sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 + dependencies: + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + dev: true + + /@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.0.0): + resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} + engines: {node: '>=18'} + peerDependencies: + postcss-selector-parser: ^7.0.0 + dependencies: + postcss-selector-parser: 7.0.0 + dev: true + + /@ctrl/tinycolor@3.6.1: + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + dev: false + + /@dual-bundle/import-meta-resolve@4.1.0: + resolution: {integrity: sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==} + dev: true + + /@element-plus/icons-vue@2.3.1(vue@3.5.12): + resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} + peerDependencies: + vue: ^3.2.0 + dependencies: + vue: 3.5.12(typescript@5.3.3) + dev: false + + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.1(eslint@8.57.1): + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.12.1: + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.57.1: + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@floating-ui/core@1.6.8: + resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==} + dependencies: + '@floating-ui/utils': 0.2.8 + dev: false + + /@floating-ui/dom@1.6.12: + resolution: {integrity: sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==} + dependencies: + '@floating-ui/core': 1.6.8 + '@floating-ui/utils': 0.2.8 + dev: false + + /@floating-ui/utils@0.2.8: + resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} + dev: false + + /@form-create/component-elm-checkbox@3.2.14: + resolution: {integrity: sha512-VtjRvNxbKpjp0bNYQ2BuLRVIQHZdPpYn3Hy0xSuzv6QjEDnffMdmawHImPSlp8wAW3b94wZdHMLMqpyMew8bBw==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-frame@3.2.14: + resolution: {integrity: sha512-JR7F8rEK4rC87ofjndRWaCNirUJTBGIINkP2GGbB5n8dH5wrkXi1QPemXBGaEgXoaxOQPRgMdc/GgZERgl6l/w==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-group@3.2.14: + resolution: {integrity: sha512-fK0Gw+mTuypFqOqXLT3PK+/lhUd/Qv8EJzjgl0hfy9A2SoR1g1t2HBz2E70MK9CtZ5i4Zcf118NjQM0cDAPkIw==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-radio@3.2.14: + resolution: {integrity: sha512-bNtMhDlWMpBHBFjkITGwDpYH/hZQDJ/q1SqsO5aWw+fxonWEod9ZgFaxUfNeqCKyo8loqu3tzivd5ZL77TsGFw==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-select@3.2.14: + resolution: {integrity: sha512-yUX0uZQHakIVngV/0D54tchhytApKsuuJcsxSrdIqTRBd83XtEC9UO4fPDX8O+M53DpSX6YEUduRvqSPmUfKgQ==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-tree@3.2.14: + resolution: {integrity: sha512-zZWsSmPqVzA8p31di1QmpPaknd7NXuyNDMJ8L6kwCo/ipzJwvToAVtj0fnTbQbdMVvGQlREs+Hwy9gJBkCoiFA==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-elm-upload@3.2.14: + resolution: {integrity: sha512-QtfzjPdSDuEUh4gfIInnNBFQB+qZvIJ/mKTz0r7wTVvZUOJbvnnEiaB0/1QzJ4z9ZfqYswdlahO9+hBW18ioCA==} + dependencies: + '@form-create/utils': 3.2.14 + dev: false + + /@form-create/component-subform@3.1.34: + resolution: {integrity: sha512-OJcFH/7MTHx7JLEjDK/weS27qfuFWAI+OK+gXTJ2jIt9aZkGWF/EWkjetiJLt5a0KMw4Z15wOS2XCY9pVK9vlA==} + dev: false + + /@form-create/component-wangeditor@3.2.14: + resolution: {integrity: sha512-N/U/hFBdBu2OIguxoKe1Kslq5fW6XmtyhKDImLfKLn1xI6X5WUtt3r7QTaUPcVUl2vntpM9wJ/FBdG17RzF/Dg==} + dependencies: + wangeditor: 4.7.15 + dev: false + + /@form-create/core@3.2.14(vue@3.5.12): + resolution: {integrity: sha512-z2YFhsru4PP/5AIwW2uBWW/Abn0ZtTMb52MqpJOedWulGRSS+zSvzsMMXB18EZPsug2OG1plQUkK79wlR6Y5JA==} + peerDependencies: + vue: ^3.1.0 + dependencies: + '@form-create/utils': 3.2.14 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /@form-create/designer@3.2.8(vue@3.5.12): + resolution: {integrity: sha512-SgrGiWOFaQTARAmysepHDtFyRi97rERrlkv1joz+DCOAzZME3RKRTXVqA7ALzJ2jI3psiCosGAK4rPSLh6EvgA==} + peerDependencies: + vue: ^3.1.5 + dependencies: + '@form-create/component-wangeditor': 3.2.14 + '@form-create/element-ui': 3.2.14(vue@3.5.12) + '@form-create/utils': 3.2.14 + codemirror: 6.65.7 + element-plus: 2.9.1(vue@3.5.12) + vue: 3.5.12(typescript@5.3.3) + vuedraggable: 4.1.0(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + dev: false + + /@form-create/element-ui@3.2.14(vue@3.5.12): + resolution: {integrity: sha512-xd+DNxS4ZBuE0gH/o+br/Lyn5kJQq7RonTykUXagfSxPq+iMnN2vmOSqHYQ0+uXNNu151PfRlZcsujNXgK1t/w==} + peerDependencies: + vue: ^3.1.0 + dependencies: + '@form-create/component-elm-checkbox': 3.2.14 + '@form-create/component-elm-frame': 3.2.14 + '@form-create/component-elm-group': 3.2.14 + '@form-create/component-elm-radio': 3.2.14 + '@form-create/component-elm-select': 3.2.14 + '@form-create/component-elm-tree': 3.2.14 + '@form-create/component-elm-upload': 3.2.14 + '@form-create/component-subform': 3.1.34 + '@form-create/core': 3.2.14(vue@3.5.12) + '@form-create/utils': 3.2.14 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /@form-create/utils@3.2.14: + resolution: {integrity: sha512-LDr2uao4qM68C4BXXAQkaMErxRvy3ZFda9992n1frXG8Ry2sbXXxOaY20ZWQoFY6HQP8ABJuJFVfM9p0KVSFLQ==} + dev: false + + /@gera2ld/jsx-dom@2.2.2: + resolution: {integrity: sha512-EOqf31IATRE6zS1W1EoWmXZhGfLAoO9FIlwTtHduSrBdud4npYBxYAkv8dZ5hudDPwJeeSjn40kbCL4wAzr8dA==} + dependencies: + '@babel/runtime': 7.26.0 + dev: false + + /@humanwhocodes/config-array@0.13.0: + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + dev: true + + /@iconify/iconify@2.1.2: + resolution: {integrity: sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==} + deprecated: no longer maintained, switch to modern iconify-icon web component + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + dev: true + + /@iconify/iconify@3.1.1: + resolution: {integrity: sha512-1nemfyD/OJzh9ALepH7YfuuP8BdEB24Skhd8DXWh0hzcOxImbb1ZizSZkpCzAwSZSGcJFmscIBaBQu+yLyWaxQ==} + deprecated: no longer maintained, switch to modern iconify-icon web component + dependencies: + '@iconify/types': 2.0.0 + + /@iconify/json@2.2.277: + resolution: {integrity: sha512-hNBnGD2djNgsdB4Yq5dBhP2CI0PLt+4EamozKSAD+hsbFAzVUN6sMj5FUiBFu8BKUOBIYcrX8ri7C7Qe3K10ew==} + dependencies: + '@iconify/types': 2.0.0 + pathe: 1.1.2 + dev: true + + /@iconify/types@2.0.0: + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + /@iconify/utils@2.1.33: + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7 + kolorist: 1.8.0 + local-pkg: 0.5.1 + mlly: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@intlify/bundle-utils@7.5.1(vue-i18n@9.10.2): + resolution: {integrity: sha512-UovJl10oBIlmYEcWw+VIHdKY5Uv5sdPG0b/b6bOYxGLln3UwB75+2dlc0F3Fsa0RhoznQ5Rp589/BZpABpE4Xw==} + engines: {node: '>= 14.16'} + peerDependencies: + petite-vue-i18n: '*' + vue-i18n: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + dependencies: + '@intlify/message-compiler': 9.14.2 + '@intlify/shared': 9.14.2 + acorn: 8.14.0 + escodegen: 2.1.0 + estree-walker: 2.0.2 + jsonc-eslint-parser: 2.4.0 + magic-string: 0.30.14 + mlly: 1.7.3 + source-map-js: 1.2.1 + vue-i18n: 9.10.2(vue@3.5.12) + yaml-eslint-parser: 1.2.3 + dev: true + + /@intlify/core-base@9.10.2: + resolution: {integrity: sha512-HGStVnKobsJL0DoYIyRCGXBH63DMQqEZxDUGrkNI05FuTcruYUtOAxyL3zoAZu/uDGO6mcUvm3VXBaHG2GdZCg==} + engines: {node: '>= 16'} + dependencies: + '@intlify/message-compiler': 9.10.2 + '@intlify/shared': 9.10.2 + + /@intlify/message-compiler@9.10.2: + resolution: {integrity: sha512-ntY/kfBwQRtX5Zh6wL8cSATujPzWW2ZQd1QwKyWwAy5fMqJyyixHMeovN4fmEyCqSu+hFfYOE63nU94evsy4YA==} + engines: {node: '>= 16'} + dependencies: + '@intlify/shared': 9.10.2 + source-map-js: 1.2.1 + + /@intlify/message-compiler@9.14.2: + resolution: {integrity: sha512-YsKKuV4Qv4wrLNsvgWbTf0E40uRv+Qiw1BeLQ0LAxifQuhiMe+hfTIzOMdWj/ZpnTDj4RSZtkXjJM7JDiiB5LQ==} + engines: {node: '>= 16'} + dependencies: + '@intlify/shared': 9.14.2 + source-map-js: 1.2.1 + dev: true + + /@intlify/shared@9.10.2: + resolution: {integrity: sha512-ttHCAJkRy7R5W2S9RVnN9KYQYPIpV2+GiS79T4EE37nrPyH6/1SrOh3bmdCRC1T3ocL8qCDx7x2lBJ0xaITU7Q==} + engines: {node: '>= 16'} + + /@intlify/shared@9.14.2: + resolution: {integrity: sha512-uRAHAxYPeF+G5DBIboKpPgC/Waecd4Jz8ihtkpJQD5ycb5PwXp0k/+hBGl5dAjwF7w+l74kz/PKA8r8OK//RUw==} + engines: {node: '>= 16'} + dev: true + + /@intlify/unplugin-vue-i18n@2.0.0(rollup@4.27.4)(vue-i18n@9.10.2): + resolution: {integrity: sha512-1oKvm92L9l2od2H9wKx2ZvR4tzn7gUtd7bPLI7AWUmm7U9H1iEypndt5d985ypxGsEs0gToDaKTrytbBIJwwSg==} + engines: {node: '>= 14.16'} + peerDependencies: + petite-vue-i18n: '*' + vue-i18n: '*' + vue-i18n-bridge: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + vue-i18n-bridge: + optional: true + dependencies: + '@intlify/bundle-utils': 7.5.1(vue-i18n@9.10.2) + '@intlify/shared': 9.14.2 + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@vue/compiler-sfc': 3.5.13 + debug: 4.3.7 + fast-glob: 3.3.2 + js-yaml: 4.1.0 + json5: 2.2.3 + pathe: 1.1.2 + picocolors: 1.1.1 + source-map-js: 1.2.1 + unplugin: 1.16.0 + vue-i18n: 9.10.2(vue@3.5.12) + transitivePeerDependencies: + - rollup + - supports-color + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.6: + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/sourcemap-codec@1.5.0: + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + dev: true + + /@lezer/common@1.2.3: + resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} + dev: true + + /@lezer/highlight@1.2.1: + resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} + dependencies: + '@lezer/common': 1.2.3 + dev: true + + /@lezer/lr@1.4.2: + resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} + dependencies: + '@lezer/common': 1.2.3 + dev: true + + /@lezer/markdown@1.3.2: + resolution: {integrity: sha512-Wu7B6VnrKTbBEohqa63h5vxXjiC4pO5ZQJ/TDbhJxPQaaIoRD/6UVDhSDtVsCwVZV12vvN9KxuLL3ATMnlG0oQ==} + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + dev: true + + /@microsoft/fetch-event-source@2.0.1: + resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==} + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + + /@parcel/watcher-android-arm64@2.5.0: + resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-darwin-arm64@2.5.0: + resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-darwin-x64@2.5.0: + resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-freebsd-x64@2.5.0: + resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-arm-glibc@2.5.0: + resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-arm-musl@2.5.0: + resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-arm64-glibc@2.5.0: + resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-arm64-musl@2.5.0: + resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-x64-glibc@2.5.0: + resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-linux-x64-musl@2.5.0: + resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-win32-arm64@2.5.0: + resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-win32-ia32@2.5.0: + resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher-win32-x64@2.5.0: + resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@parcel/watcher@2.5.0: + resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} + engines: {node: '>= 10.0.0'} + requiresBuild: true + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.0 + '@parcel/watcher-darwin-arm64': 2.5.0 + '@parcel/watcher-darwin-x64': 2.5.0 + '@parcel/watcher-freebsd-x64': 2.5.0 + '@parcel/watcher-linux-arm-glibc': 2.5.0 + '@parcel/watcher-linux-arm-musl': 2.5.0 + '@parcel/watcher-linux-arm64-glibc': 2.5.0 + '@parcel/watcher-linux-arm64-musl': 2.5.0 + '@parcel/watcher-linux-x64-glibc': 2.5.0 + '@parcel/watcher-linux-x64-musl': 2.5.0 + '@parcel/watcher-win32-arm64': 2.5.0 + '@parcel/watcher-win32-ia32': 2.5.0 + '@parcel/watcher-win32-x64': 2.5.0 + dev: true + optional: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@polka/url@1.0.0-next.28: + resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + dev: true + + /@purge-icons/core@0.10.0: + resolution: {integrity: sha512-AtJbZv5Yy+vWX5v32DPTr+CW7AkSK8HJx52orDbrYt/9s4lGM2t4KKAmwaTQEH2HYr2HVh1mlqs54/S1s3WT1g==} + dependencies: + '@iconify/iconify': 2.1.2 + axios: 0.26.1(debug@4.3.7) + debug: 4.3.7 + fast-glob: 3.3.2 + fs-extra: 10.1.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@purge-icons/generated@0.10.0: + resolution: {integrity: sha512-I+1yN7/yDy/eZzfhAZqKF8Z6FM8D/O1vempbPrHJ0m9HlZwvf8sWXOArPJ2qRQGB6mJUVSpaXkoGBuoz1GQX5A==} + dependencies: + '@iconify/iconify': 3.1.1 + dev: true + + /@purge-icons/generated@0.9.0: + resolution: {integrity: sha512-s2t+1oVtGDV6KtqfCXtUOhxfeYvOdDF90IVm+nMs/6bUP0HeGZLslguuL/AibpwtfL4FA/oCsIu/RhwapgAdJw==} + dependencies: + '@iconify/iconify': 3.1.1 + dev: true + + /@rollup/plugin-virtual@3.0.2(rollup@4.27.4): + resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + rollup: 4.27.4 + dev: true + + /@rollup/pluginutils@4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/pluginutils@5.1.3(rollup@4.27.4): + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + rollup: 4.27.4 + dev: true + + /@rollup/rollup-android-arm-eabi@4.27.4: + resolution: {integrity: sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.27.4: + resolution: {integrity: sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.27.4: + resolution: {integrity: sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.27.4: + resolution: {integrity: sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-arm64@4.27.4: + resolution: {integrity: sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-x64@4.27.4: + resolution: {integrity: sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.27.4: + resolution: {integrity: sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==} + cpu: [arm] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-musleabihf@4.27.4: + resolution: {integrity: sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==} + cpu: [arm] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.27.4: + resolution: {integrity: sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.27.4: + resolution: {integrity: sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==} + cpu: [arm64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.27.4: + resolution: {integrity: sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.27.4: + resolution: {integrity: sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.27.4: + resolution: {integrity: sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.27.4: + resolution: {integrity: sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==} + cpu: [x64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.27.4: + resolution: {integrity: sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==} + cpu: [x64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.27.4: + resolution: {integrity: sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.27.4: + resolution: {integrity: sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.27.4: + resolution: {integrity: sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@swc/core-darwin-arm64@1.9.3: + resolution: {integrity: sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-x64@1.9.3: + resolution: {integrity: sha512-IaRq05ZLdtgF5h9CzlcgaNHyg4VXuiStnOFpfNEMuI5fm5afP2S0FHq8WdakUz5WppsbddTdplL+vpeApt/WCQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm-gnueabihf@1.9.3: + resolution: {integrity: sha512-Pbwe7xYprj/nEnZrNBvZfjnTxlBIcfApAGdz2EROhjpPj+FBqBa3wOogqbsuGGBdCphf8S+KPprL1z+oDWkmSQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-gnu@1.9.3: + resolution: {integrity: sha512-AQ5JZiwNGVV/2K2TVulg0mw/3LYfqpjZO6jDPtR2evNbk9Yt57YsVzS+3vHSlUBQDRV9/jqMuZYVU3P13xrk+g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-musl@1.9.3: + resolution: {integrity: sha512-tzVH480RY6RbMl/QRgh5HK3zn1ZTFsThuxDGo6Iuk1MdwIbdFYUY034heWUTI4u3Db97ArKh0hNL0xhO3+PZdg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-gnu@1.9.3: + resolution: {integrity: sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-musl@1.9.3: + resolution: {integrity: sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-arm64-msvc@1.9.3: + resolution: {integrity: sha512-e+XmltDVIHieUnNJHtspn6B+PCcFOMYXNJB1GqoCcyinkEIQNwC8KtWgMqUucUbEWJkPc35NHy9k8aCXRmw9Kg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-ia32-msvc@1.9.3: + resolution: {integrity: sha512-rqpzNfpAooSL4UfQnHhkW8aL+oyjqJniDP0qwZfGnjDoJSbtPysHg2LpcOBEdSnEH+uIZq6J96qf0ZFD8AGfXA==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-x64-msvc@1.9.3: + resolution: {integrity: sha512-3YJJLQ5suIEHEKc1GHtqVq475guiyqisKSoUnoaRtxkDaW5g1yvPt9IoSLOe2mRs7+FFhGGU693RsBUSwOXSdQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core@1.9.3: + resolution: {integrity: sha512-oRj0AFePUhtatX+BscVhnzaAmWjpfAeySpM1TCbxA1rtBDeH/JDhi5yYzAKneDYtVtBvA7ApfeuzhMC9ye4xSg==} + engines: {node: '>=10'} + requiresBuild: true + peerDependencies: + '@swc/helpers': '*' + peerDependenciesMeta: + '@swc/helpers': + optional: true + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.17 + optionalDependencies: + '@swc/core-darwin-arm64': 1.9.3 + '@swc/core-darwin-x64': 1.9.3 + '@swc/core-linux-arm-gnueabihf': 1.9.3 + '@swc/core-linux-arm64-gnu': 1.9.3 + '@swc/core-linux-arm64-musl': 1.9.3 + '@swc/core-linux-x64-gnu': 1.9.3 + '@swc/core-linux-x64-musl': 1.9.3 + '@swc/core-win32-arm64-msvc': 1.9.3 + '@swc/core-win32-ia32-msvc': 1.9.3 + '@swc/core-win32-x64-msvc': 1.9.3 + dev: true + + /@swc/counter@0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + dev: true + + /@swc/types@0.1.17: + resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==} + dependencies: + '@swc/counter': 0.1.3 + dev: true + + /@sxzz/popperjs-es@2.11.7: + resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} + dev: false + + /@transloadit/prettier-bytes@0.0.7: + resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==} + dev: false + + /@trysound/sax@0.2.0: + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + dev: true + + /@types/conventional-commits-parser@5.0.1: + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + dependencies: + '@types/node': 20.17.9 + dev: true + + /@types/d3-array@3.2.1: + resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + dev: false + + /@types/d3-axis@3.0.6: + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-brush@3.0.6: + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-chord@3.0.6: + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + dev: false + + /@types/d3-color@3.1.3: + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + dev: false + + /@types/d3-contour@3.0.6: + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + dependencies: + '@types/d3-array': 3.2.1 + '@types/geojson': 7946.0.14 + dev: false + + /@types/d3-delaunay@6.0.4: + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + dev: false + + /@types/d3-dispatch@3.0.6: + resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==} + dev: false + + /@types/d3-drag@3.0.7: + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-dsv@3.0.7: + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + dev: false + + /@types/d3-ease@3.0.2: + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + dev: false + + /@types/d3-fetch@3.0.7: + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + dependencies: + '@types/d3-dsv': 3.0.7 + dev: false + + /@types/d3-force@3.0.10: + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + dev: false + + /@types/d3-format@3.0.4: + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + dev: false + + /@types/d3-geo@3.1.0: + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + dependencies: + '@types/geojson': 7946.0.14 + dev: false + + /@types/d3-hierarchy@3.1.7: + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + dev: false + + /@types/d3-interpolate@3.0.4: + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + dependencies: + '@types/d3-color': 3.1.3 + dev: false + + /@types/d3-path@3.1.0: + resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} + dev: false + + /@types/d3-polygon@3.0.2: + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + dev: false + + /@types/d3-quadtree@3.0.6: + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + dev: false + + /@types/d3-random@3.0.3: + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + dev: false + + /@types/d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + dev: false + + /@types/d3-scale@4.0.8: + resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} + dependencies: + '@types/d3-time': 3.0.4 + dev: false + + /@types/d3-selection@3.0.11: + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + dev: false + + /@types/d3-shape@3.1.6: + resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==} + dependencies: + '@types/d3-path': 3.1.0 + dev: false + + /@types/d3-time-format@4.0.3: + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + dev: false + + /@types/d3-time@3.0.4: + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + dev: false + + /@types/d3-timer@3.0.2: + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + dev: false + + /@types/d3-transition@3.0.9: + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + dependencies: + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3-zoom@3.0.8: + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + dev: false + + /@types/d3@7.4.3: + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + dependencies: + '@types/d3-array': 3.2.1 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.6 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.0 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.8 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.6 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + dev: false + + /@types/eslint@8.56.12: + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.6: + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + dev: true + + /@types/event-emitter@0.3.5: + resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==} + dev: false + + /@types/geojson@7946.0.14: + resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} + dev: false + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.17.13 + + /@types/lodash@4.17.13: + resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==} + + /@types/node@10.17.60: + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + dev: true + + /@types/node@20.17.9: + resolution: {integrity: sha512-0JOXkRyLanfGPE2QRCwgxhzlBAvaRdCNMcvbd7jFfpmD4eEXll7LRwy5ymJmyeZqk7Nh7eD2LeUyQ68BbndmXw==} + dependencies: + undici-types: 6.19.8 + dev: true + + /@types/nprogress@0.2.3: + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + dev: true + + /@types/qrcode@1.5.5: + resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} + dependencies: + '@types/node': 20.17.9 + dev: true + + /@types/qs@6.9.17: + resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + + /@types/svgo@2.6.4: + resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + dependencies: + '@types/node': 20.17.9 + dev: true + + /@types/trusted-types@2.0.7: + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + requiresBuild: true + dev: false + optional: true + + /@types/video.js@7.3.58: + resolution: {integrity: sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==} + dev: false + + /@types/web-bluetooth@0.0.16: + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + dev: false + + /@types/web-bluetooth@0.0.20: + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + + /@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0)(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 + eslint: 8.57.1 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.7 + eslint: 8.57.1 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/scope-manager@7.18.0: + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + dev: true + + /@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.3.3) + debug: 4.3.7 + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/types@7.18.0: + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} + engines: {node: ^18.18.0 || >=20.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.3.3): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.3 + ts-api-utils: 1.4.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@7.18.0(typescript@5.3.3): + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.7 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.4.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + eslint: 8.57.1 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@7.18.0: + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@unocss/astro@0.58.9(rollup@4.27.4)(vite@5.1.4): + resolution: {integrity: sha512-VWfHNC0EfawFxLfb3uI+QcMGBN+ju+BYtutzeZTjilLKj31X2UpqIh8fepixL6ljgZzB3fweqg2xtUMC0gMnoQ==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + '@unocss/core': 0.58.9 + '@unocss/reset': 0.58.9 + '@unocss/vite': 0.58.9(rollup@4.27.4)(vite@5.1.4) + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - rollup + dev: true + + /@unocss/cli@0.58.9(rollup@4.27.4): + resolution: {integrity: sha512-q7qlwX3V6UaqljWUQ5gMj36yTA9eLuuRywahdQWt1ioy4aPF/MEEfnMBZf/ntrqf5tIT5TO8fE11nvCco2Q/sA==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@unocss/config': 0.58.9 + '@unocss/core': 0.58.9 + '@unocss/preset-uno': 0.58.9 + cac: 6.7.14 + chokidar: 3.6.0 + colorette: 2.0.20 + consola: 3.2.3 + fast-glob: 3.3.2 + magic-string: 0.30.14 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + transitivePeerDependencies: + - rollup + dev: true + + /@unocss/config@0.57.7: + resolution: {integrity: sha512-UG8G9orWEdk/vyDvGUToXYn/RZy/Qjpx66pLsaf5wQK37hkYsBoReAU5v8Ia/6PL1ueJlkcNXLaNpN6/yVoJvg==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.57.7 + unconfig: 0.3.13 + dev: true + + /@unocss/config@0.58.9: + resolution: {integrity: sha512-90wRXIyGNI8UenWxvHUcH4l4rgq813MsTzYWsf6ZKyLLvkFjV2b2EfGXI27GPvZ7fVE1OAqx+wJNTw8CyQxwag==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.58.9 + unconfig: 0.3.13 + dev: true + + /@unocss/core@0.57.7: + resolution: {integrity: sha512-1d36M0CV3yC80J0pqOa5rH1BX6g2iZdtKmIb3oSBN4AWnMCSrrJEPBrUikyMq2TEQTrYWJIVDzv5A9hBUat3TA==} + dev: true + + /@unocss/core@0.58.9: + resolution: {integrity: sha512-wYpPIPPsOIbIoMIDuH8ihehJk5pAZmyFKXIYO/Kro98GEOFhz6lJoLsy6/PZuitlgp2/TSlubUuWGjHWvp5osw==} + dev: true + + /@unocss/eslint-config@0.57.7(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-EJlI6rV0ZfDCphIiddHSWZVeoHdYDTVohVXGo+NfNOuRuvYWGna3n4hY3VEAiT3mWLK0/0anzHF7X0PNzCR5lQ==} + engines: {node: '>=14'} + dependencies: + '@unocss/eslint-plugin': 0.57.7(eslint@8.57.1)(typescript@5.3.3) + transitivePeerDependencies: + - eslint + - supports-color + - typescript + dev: true + + /@unocss/eslint-plugin@0.57.7(eslint@8.57.1)(typescript@5.3.3): + resolution: {integrity: sha512-nwj7UJF7wCfPVl5B7cUB0xrSk6yuVMdMgABnsy4N5xBlds8cclrUO+boaTB9qzh8Lg9nfJVLB3+cW3po2SJoew==} + engines: {node: '>=14'} + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + '@unocss/config': 0.57.7 + '@unocss/core': 0.57.7 + magic-string: 0.30.14 + synckit: 0.8.8 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + dev: true + + /@unocss/extractor-arbitrary-variants@0.58.9: + resolution: {integrity: sha512-M/BvPdbEEMdhcFQh/z2Bf9gylO1Ky/ZnpIvKWS1YJPLt4KA7UWXSUf+ZNTFxX+X58Is5qAb5hNh/XBQmL3gbXg==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/inspector@0.58.9: + resolution: {integrity: sha512-uRzqkCNeBmEvFePXcfIFcQPMlCXd9/bLwa5OkBthiOILwQdH1uRIW3GWAa2SWspu+kZLP0Ly3SjZ9Wqi+5ZtTw==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/rule-utils': 0.58.9 + gzip-size: 6.0.0 + sirv: 2.0.4 + dev: true + + /@unocss/postcss@0.58.9(postcss@8.4.49): + resolution: {integrity: sha512-PnKmH6Qhimw35yO6u6yx9SHaX2NmvbRNPDvMDHA/1xr3M8L0o8U88tgKbWfm65NEGF3R1zJ9A8rjtZn/LPkgPA==} + engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 + dependencies: + '@unocss/config': 0.58.9 + '@unocss/core': 0.58.9 + '@unocss/rule-utils': 0.58.9 + css-tree: 2.3.1 + fast-glob: 3.3.2 + magic-string: 0.30.14 + postcss: 8.4.49 + dev: true + + /@unocss/preset-attributify@0.58.9: + resolution: {integrity: sha512-ucP+kXRFcwmBmHohUVv31bE/SejMAMo7Hjb0QcKVLyHlzRWUJsfNR+jTAIGIUSYxN7Q8MeigYsongGo3nIeJnQ==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/preset-icons@0.58.9: + resolution: {integrity: sha512-9dS48+yAunsbS0ylOW2Wisozwpn3nGY1CqTiidkUnrMnrZK3al579A7srUX9NyPWWDjprO7eU/JkWbdDQSmFFA==} + dependencies: + '@iconify/utils': 2.1.33 + '@unocss/core': 0.58.9 + ofetch: 1.4.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/preset-mini@0.58.9: + resolution: {integrity: sha512-m4aDGYtueP8QGsU3FsyML63T/w5Mtr4htme2jXy6m50+tzC1PPHaIBstMTMQfLc6h8UOregPJyGHB5iYQZGEvQ==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/extractor-arbitrary-variants': 0.58.9 + '@unocss/rule-utils': 0.58.9 + dev: true + + /@unocss/preset-tagify@0.58.9: + resolution: {integrity: sha512-obh75XrRmxYwrQMflzvhQUMeHwd/R9bEDhTWUW9aBTolBy4eNypmQwOhHCKh5Xi4Dg6o0xj6GWC/jcCj1SPLog==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/preset-typography@0.58.9: + resolution: {integrity: sha512-hrsaqKlcZni3Vh4fwXC+lP9e92FQYbqtmlZw2jpxlVwwH5aLzwk4d4MiFQGyhCfzuSDYm0Zd52putFVV02J7bA==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/preset-mini': 0.58.9 + dev: true + + /@unocss/preset-uno@0.58.9: + resolution: {integrity: sha512-Fze+X2Z/EegCkRdDRgwwvFBmXBenNR1AG8KxAyz8iPeWbhOBaRra2sn2ScryrfH6SbJHpw26ZyJXycAdS0Fq3A==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/preset-mini': 0.58.9 + '@unocss/preset-wind': 0.58.9 + '@unocss/rule-utils': 0.58.9 + dev: true + + /@unocss/preset-web-fonts@0.58.9: + resolution: {integrity: sha512-XtiO+Z+RYnNYomNkS2XxaQiY++CrQZKOfNGw5htgIrb32QtYVQSkyYQ3jDw7JmMiCWlZ4E72cV/zUb++WrZLxg==} + dependencies: + '@unocss/core': 0.58.9 + ofetch: 1.4.1 + dev: true + + /@unocss/preset-wind@0.58.9: + resolution: {integrity: sha512-7l+7Vx5UoN80BmJKiqDXaJJ6EUqrnUQYv8NxCThFi5lYuHzxsYWZPLU3k3XlWRUQt8XL+6rYx7mMBmD7EUSHyw==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/preset-mini': 0.58.9 + '@unocss/rule-utils': 0.58.9 + dev: true + + /@unocss/reset@0.58.9: + resolution: {integrity: sha512-nA2pg3tnwlquq+FDOHyKwZvs20A6iBsKPU7Yjb48JrNnzoaXqE+O9oN6782IG2yKVW4AcnsAnAnM4cxXhGzy1w==} + dev: true + + /@unocss/rule-utils@0.58.9: + resolution: {integrity: sha512-45bDa+elmlFLthhJmKr2ltKMAB0yoXnDMQ6Zp5j3OiRB7dDMBkwYRPvHLvIe+34Ey7tDt/kvvDPtWMpPl2quUQ==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.58.9 + magic-string: 0.30.14 + dev: true + + /@unocss/scope@0.58.9: + resolution: {integrity: sha512-BIwcpx0R3bE0rYa9JVDJTk0GX32EBvnbvufBpNkWfC5tb7g+B7nMkVq9ichanksYCCxrIQQo0mrIz5PNzu9sGA==} + dev: true + + /@unocss/transformer-attributify-jsx-babel@0.58.9: + resolution: {integrity: sha512-UGaQoGZg+3QrsPtnGHPECmsGn4EQb2KSdZ4eGEn2YssjKv+CcQhzRvpEUgnuF/F+jGPkCkS/G/YEQBHRWBY54Q==} + dependencies: + '@babel/core': 7.26.0 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/preset-typescript': 7.26.0(@babel/core@7.26.0) + '@unocss/core': 0.58.9 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/transformer-attributify-jsx@0.58.9: + resolution: {integrity: sha512-jpL3PRwf8t43v1agUdQn2EHGgfdWfvzsMxFtoybO88xzOikzAJaaouteNtojc/fQat2T9iBduDxVj5egdKmhdQ==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/transformer-compile-class@0.58.9: + resolution: {integrity: sha512-l2VpCqelJ6Tgc1kfSODxBtg7fCGPVRr2EUzTg1LrGYKa2McbKuc/wV/2DWKHGxL6+voWi7a2C9XflqGDXXutuQ==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/transformer-directives@0.58.9: + resolution: {integrity: sha512-pLOUsdoY2ugVntJXg0xuGjO9XZ2xCiMxTPRtpZ4TsEzUtdEzMswR06Y8VWvNciTB/Zqxcz9ta8rD0DKePOfSuw==} + dependencies: + '@unocss/core': 0.58.9 + '@unocss/rule-utils': 0.58.9 + css-tree: 2.3.1 + dev: true + + /@unocss/transformer-variant-group@0.58.9: + resolution: {integrity: sha512-3A6voHSnFcyw6xpcZT6oxE+KN4SHRnG4z862tdtWvRGcN+jGyNr20ylEZtnbk4xj0VNMeGHHQRZ0WLvmrAwvOQ==} + dependencies: + '@unocss/core': 0.58.9 + dev: true + + /@unocss/vite@0.58.9(rollup@4.27.4)(vite@5.1.4): + resolution: {integrity: sha512-mmppBuulAHCal+sC0Qz36Y99t0HicAmznpj70Kzwl7g/yvXwm58/DW2OnpCWw+uA8/JBft/+z3zE+XvrI+T1HA==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + dependencies: + '@ampproject/remapping': 2.3.0 + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@unocss/config': 0.58.9 + '@unocss/core': 0.58.9 + '@unocss/inspector': 0.58.9 + '@unocss/scope': 0.58.9 + '@unocss/transformer-directives': 0.58.9 + chokidar: 3.6.0 + fast-glob: 3.3.2 + magic-string: 0.30.14 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - rollup + dev: true + + /@uppy/companion-client@2.2.2: + resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==} + dependencies: + '@uppy/utils': 4.1.3 + namespace-emitter: 2.0.1 + dev: false + + /@uppy/core@2.3.4: + resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==} + dependencies: + '@transloadit/prettier-bytes': 0.0.7 + '@uppy/store-default': 2.1.1 + '@uppy/utils': 4.1.3 + lodash.throttle: 4.1.1 + mime-match: 1.0.2 + namespace-emitter: 2.0.1 + nanoid: 3.3.8 + preact: 10.25.0 + dev: false + + /@uppy/store-default@2.1.1: + resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==} + dev: false + + /@uppy/utils@4.1.3: + resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==} + dependencies: + lodash.throttle: 4.1.1 + dev: false + + /@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4): + resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==} + peerDependencies: + '@uppy/core': ^2.3.3 + dependencies: + '@uppy/companion-client': 2.2.2 + '@uppy/core': 2.3.4 + '@uppy/utils': 4.1.3 + nanoid: 3.3.8 + dev: false + + /@videojs-player/vue@1.0.0(@types/video.js@7.3.58)(video.js@7.21.6)(vue@3.5.12): + resolution: {integrity: sha512-WonTezRfKu3fYdQLt/ta+nuKH6gMZUv8l40Jke/j4Lae7IqeO/+lLAmBnh3ni88bwR+vkFXIlZ2Ci7VKInIYJg==} + peerDependencies: + '@types/video.js': 7.x + video.js: 7.x + vue: 3.x + dependencies: + '@types/video.js': 7.3.58 + video.js: 7.21.6 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /@videojs/http-streaming@2.16.3(video.js@7.21.6): + resolution: {integrity: sha512-91CJv5PnFBzNBvyEjt+9cPzTK/xoVixARj2g7ZAvItA+5bx8VKdk5RxCz/PP2kdzz9W+NiDUMPkdmTsosmy69Q==} + engines: {node: '>=8', npm: '>=5'} + peerDependencies: + video.js: ^6 || ^7 + dependencies: + '@babel/runtime': 7.26.0 + '@videojs/vhs-utils': 3.0.5 + aes-decrypter: 3.1.3 + global: 4.4.0 + m3u8-parser: 4.8.0 + mpd-parser: 0.22.1 + mux.js: 6.0.1 + video.js: 7.21.6 + dev: false + + /@videojs/vhs-utils@3.0.5: + resolution: {integrity: sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==} + engines: {node: '>=8', npm: '>=5'} + dependencies: + '@babel/runtime': 7.26.0 + global: 4.4.0 + url-toolkit: 2.2.5 + dev: false + + /@videojs/xhr@2.6.0: + resolution: {integrity: sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==} + dependencies: + '@babel/runtime': 7.26.0 + global: 4.4.0 + is-function: 1.0.2 + dev: false + + /@vitejs/plugin-legacy@5.4.3(terser@5.36.0)(vite@5.1.4): + resolution: {integrity: sha512-wsyXK9mascyplcqvww1gA1xYiy29iRHfyciw+a0t7qRNdzX6PdfSWmOoCi74epr87DujM+5J+rnnSv+4PazqVg==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + terser: ^5.4.0 + vite: ^5.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/preset-env': 7.26.0(@babel/core@7.26.0) + browserslist: 4.24.2 + browserslist-to-esbuild: 2.1.1(browserslist@4.24.2) + core-js: 3.39.0 + magic-string: 0.30.14 + regenerator-runtime: 0.14.1 + systemjs: 6.15.1 + terser: 5.36.0 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitejs/plugin-vue-jsx@3.1.0(vite@5.1.4)(vue@3.5.12): + resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 || ^5.0.0 + vue: ^3.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) + '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0) + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + vue: 3.5.12(typescript@5.3.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitejs/plugin-vue@5.2.1(vite@5.1.4)(vue@3.5.12): + resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + dependencies: + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + vue: 3.5.12(typescript@5.3.3) + dev: true + + /@volar/language-core@1.11.1: + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + dependencies: + '@volar/source-map': 1.11.1 + dev: true + + /@volar/source-map@1.11.1: + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + dependencies: + muggle-string: 0.3.1 + dev: true + + /@volar/typescript@1.11.1: + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + dev: true + + /@vue/babel-helper-vue-transform-on@1.2.5: + resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==} + dev: true + + /@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.0): + resolution: {integrity: sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + '@vue/babel-helper-vue-transform-on': 1.2.5 + '@vue/babel-plugin-resolve-type': 1.2.5(@babel/core@7.26.0) + html-tags: 3.3.1 + svg-tags: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@vue/babel-plugin-resolve-type@1.2.5(@babel/core@7.26.0): + resolution: {integrity: sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/parser': 7.26.2 + '@vue/compiler-sfc': 3.5.13 + transitivePeerDependencies: + - supports-color + dev: true + + /@vue/compiler-core@3.5.12: + resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/shared': 3.5.12 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + /@vue/compiler-core@3.5.13: + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + dev: true + + /@vue/compiler-dom@3.5.12: + resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==} + dependencies: + '@vue/compiler-core': 3.5.12 + '@vue/shared': 3.5.12 + + /@vue/compiler-dom@3.5.13: + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + dev: true + + /@vue/compiler-sfc@3.5.12: + resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/compiler-core': 3.5.12 + '@vue/compiler-dom': 3.5.12 + '@vue/compiler-ssr': 3.5.12 + '@vue/shared': 3.5.12 + estree-walker: 2.0.2 + magic-string: 0.30.14 + postcss: 8.4.49 + source-map-js: 1.2.1 + + /@vue/compiler-sfc@3.5.13: + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.14 + postcss: 8.4.49 + source-map-js: 1.2.1 + dev: true + + /@vue/compiler-ssr@3.5.12: + resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==} + dependencies: + '@vue/compiler-dom': 3.5.12 + '@vue/shared': 3.5.12 + + /@vue/compiler-ssr@3.5.13: + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + dev: true + + /@vue/devtools-api@6.6.4: + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + /@vue/language-core@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + computeds: 0.0.1 + minimatch: 9.0.5 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.3.3 + vue-template-compiler: 2.7.16 + dev: true + + /@vue/reactivity@3.5.12: + resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==} + dependencies: + '@vue/shared': 3.5.12 + + /@vue/runtime-core@3.5.12: + resolution: {integrity: sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==} + dependencies: + '@vue/reactivity': 3.5.12 + '@vue/shared': 3.5.12 + + /@vue/runtime-dom@3.5.12: + resolution: {integrity: sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==} + dependencies: + '@vue/reactivity': 3.5.12 + '@vue/runtime-core': 3.5.12 + '@vue/shared': 3.5.12 + csstype: 3.1.3 + + /@vue/server-renderer@3.5.12(vue@3.5.12): + resolution: {integrity: sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==} + peerDependencies: + vue: 3.5.12 + dependencies: + '@vue/compiler-ssr': 3.5.12 + '@vue/shared': 3.5.12 + vue: 3.5.12(typescript@5.3.3) + + /@vue/shared@3.5.12: + resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==} + + /@vue/shared@3.5.13: + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + dev: true + + /@vueuse/core@10.11.1(vue@3.5.12): + resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==} + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.11.1 + '@vueuse/shared': 10.11.1(vue@3.5.12) + vue-demi: 0.14.10(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + /@vueuse/core@9.13.0(vue@3.5.12): + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.5.12) + vue-demi: 0.14.10(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /@vueuse/metadata@10.11.1: + resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==} + + /@vueuse/metadata@9.13.0: + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + dev: false + + /@vueuse/shared@10.11.1(vue@3.5.12): + resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==} + dependencies: + vue-demi: 0.14.10(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + /@vueuse/shared@9.13.0(vue@3.5.12): + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + dependencies: + vue-demi: 0.14.10(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-url: 1.2.4 + lodash.throttle: 4.1.1 + nanoid: 3.3.8 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + prismjs: 1.29.0 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==} + peerDependencies: + '@uppy/core': ^2.1.1 + '@uppy/xhr-upload': ^2.0.3 + dom7: ^3.0.0 + is-hotkey: ^0.2.0 + lodash.camelcase: ^4.3.0 + lodash.clonedeep: ^4.5.0 + lodash.debounce: ^4.0.8 + lodash.foreach: ^4.5.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + lodash.toarray: ^4.4.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@types/event-emitter': 0.3.5 + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + dom7: 3.0.0 + event-emitter: 0.3.5 + html-void-elements: 2.0.1 + i18next: 20.6.1 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.8 + scroll-into-view-if-needed: 2.2.31 + slate: 0.72.8 + slate-history: 0.66.0(slate@0.72.8) + snabbdom: 3.6.2 + dev: false + + /@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.12): + resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==} + peerDependencies: + '@wangeditor/editor': '>=5.1.0' + vue: ^3.0.5 + dependencies: + '@wangeditor/editor': 5.1.23 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /@wangeditor/editor@5.1.23: + resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==} + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/basic-modules@1.1.7)(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/core@1.1.19)(dom7@3.0.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.8 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19)(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + nanoid: 3.3.8 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/basic-modules@1.1.7)(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==} + peerDependencies: + '@uppy/core': ^2.0.3 + '@uppy/xhr-upload': ^2.0.3 + '@wangeditor/basic-modules': 1.x + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.foreach: ^4.5.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19)(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.foreach: 4.5.0 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(@wangeditor/core@1.1.19)(dom7@3.0.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2): + resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==} + peerDependencies: + '@uppy/core': ^2.1.4 + '@uppy/xhr-upload': ^2.0.7 + '@wangeditor/core': 1.x + dom7: ^3.0.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3)(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.8)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + nanoid: 3.3.8 + slate: 0.72.8 + snabbdom: 3.6.2 + dev: false + + /@xmldom/xmldom@0.8.10: + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + dev: false + + /@zxcvbn-ts/core@3.0.4: + resolution: {integrity: sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==} + dependencies: + fastest-levenshtein: 1.0.16 + dev: false + + /JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + + /acorn-jsx@5.3.2(acorn@8.14.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.14.0 + dev: true + + /acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /aes-decrypter@3.1.3: + resolution: {integrity: sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==} + dependencies: + '@babel/runtime': 7.26.0 + '@videojs/vhs-utils': 3.0.5 + global: 4.4.0 + pkcs7: 1.0.4 + dev: false + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + dev: true + + /animate.css@4.1.1: + resolution: {integrity: sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==} + dev: false + + /ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + dependencies: + environment: 1.1.0 + dev: true + + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + /arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + dev: true + + /array-move@4.0.0: + resolution: {integrity: sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + dev: true + + /arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + dev: true + + /assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + dev: true + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false + + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: true + + /autolinker@3.16.2: + resolution: {integrity: sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==} + dependencies: + tslib: 2.8.1 + dev: false + + /autoprefixer@10.4.20(postcss@8.4.49): + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001684 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + dev: true + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /axios@0.26.1(debug@4.3.7): + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} + dependencies: + follow-redirects: 1.15.9(debug@4.3.7) + transitivePeerDependencies: + - debug + dev: true + + /axios@1.7.8: + resolution: {integrity: sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==} + dependencies: + follow-redirects: 1.15.9(debug@4.3.7) + form-data: 4.0.1 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.0): + resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.26.2 + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0): + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) + core-js-compat: 3.39.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.0): + resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + dev: true + + /base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + dev: true + + /benz-amr-recorder@1.1.5: + resolution: {integrity: sha512-NepctcNTsZHK8NxBb5uKO5p8S+xkbm+vD6GLSkCYdJeEsriexvgumLHpDkanX4QJBcLRMVtg16buWMs+gUPB3g==} + dependencies: + benz-recorderjs: 1.0.5 + dev: false + + /benz-recorderjs@1.0.5: + resolution: {integrity: sha512-EwedOQo9KLti7HxDi/eZY51PSRbAXnOdEZmLvJ6ro3QQSoF9Y3AXBt57MIllGvVz5vtFYMeikG+GD7qTm3+p9w==} + dev: false + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + /bpmn-js-properties-panel@5.23.0(@bpmn-io/properties-panel@3.25.0)(bpmn-js@17.11.1)(camunda-bpmn-js-behaviors@1.7.2)(diagram-js@12.8.1): + resolution: {integrity: sha512-4B27LM8oV14A2QWRvazV17h4NxbkNERcqU+AGJmxKImMlLhu9893MWR+pCdTQCTphBdBkuD8ksWm+1wVCedJ7g==} + peerDependencies: + '@bpmn-io/properties-panel': '>= 3.7' + bpmn-js: '>= 11.5' + camunda-bpmn-js-behaviors: '>= 0.4' + diagram-js: '>= 11.9' + dependencies: + '@bpmn-io/extract-process-variables': 0.8.0 + '@bpmn-io/properties-panel': 3.25.0(@lezer/common@1.2.3) + array-move: 4.0.0 + bpmn-js: 17.11.1 + camunda-bpmn-js-behaviors: 1.7.2(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.7.0) + diagram-js: 12.8.1 + ids: 1.0.5 + min-dash: 4.2.2 + min-dom: 4.2.1 + dev: true + + /bpmn-js-token-simulation@0.36.0: + resolution: {integrity: sha512-vz+RHlbZCev/6dzk6FhJRz8M0aZ1GL7Xrza0ecWqeg4tHbgPozgyOm3tXTz75XdtOwRVVBzmCjcciXQX7A55wQ==} + engines: {node: '>= 16'} + dependencies: + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + randomcolor: 0.6.2 + dev: false + + /bpmn-js@17.11.1: + resolution: {integrity: sha512-ywCeTg5kvN8lYkU+fHE+YXTGlfKc55lRBn7zW3k1//toeMNPy/PS/uQiujRWdFhMrH5dbtDvlwWukNw2pjWw8Q==} + dependencies: + bpmn-moddle: 8.1.0 + diagram-js: 14.11.3 + diagram-js-direct-editing: 3.2.0(diagram-js@14.11.3) + ids: 1.0.5 + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + tiny-svg: 3.1.3 + dev: true + + /bpmn-moddle@8.1.0: + resolution: {integrity: sha512-yI5OAFfYVJwViKTsTsonVfCBPtB3MlefADUORwNIxxBOMp21vnoxuxsdgUWlPH/dvAEZh/+mr8UtqOBNu8NC5Q==} + dependencies: + min-dash: 4.2.2 + moddle: 6.2.3 + moddle-xml: 10.1.0 + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + dev: true + + /browserslist-to-esbuild@2.1.1(browserslist@4.24.2): + resolution: {integrity: sha512-KN+mty6C3e9AN8Z5dI1xeN15ExcRNeISoC3g7V0Kax/MMF9MSoYA2G7lkTTcVUFntiEjkpI0HNgqJC1NjdyNUw==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + browserslist: '*' + dependencies: + browserslist: 4.24.2 + meow: 13.2.0 + dev: true + + /browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001684 + electron-to-chromium: 1.5.67 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + dev: true + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: false + + /camunda-bpmn-js-behaviors@1.7.2(bpmn-js@17.11.1)(camunda-bpmn-moddle@7.0.1)(zeebe-bpmn-moddle@1.7.0): + resolution: {integrity: sha512-xjLJHc18T40tcYu4JCeYDo1wR5i9+ZqcVnXVP6c4ooAe2gKISbBvFc07gqGpqiwm7TpEBvUfDj3PrRr+ofaf4w==} + peerDependencies: + bpmn-js: '>= 9' + camunda-bpmn-moddle: '>= 7' + zeebe-bpmn-moddle: '>= 0.18' + dependencies: + bpmn-js: 17.11.1 + camunda-bpmn-moddle: 7.0.1 + ids: 1.0.5 + min-dash: 4.2.2 + zeebe-bpmn-moddle: 1.7.0 + dev: true + + /camunda-bpmn-moddle@7.0.1: + resolution: {integrity: sha512-Br8Diu6roMpziHdpl66Dhnm0DTnCFMrSD9zwLV08LpD52QA0UsXxU87XfHf08HjuB7ly0Hd1bvajZRpf9hbmYQ==} + + /caniuse-lite@1.0.30001684: + resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==} + dev: true + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + dev: false + + /cheerio@1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} + engines: {node: '>= 6'} + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.1.0 + htmlparser2: 8.0.2 + parse5: 7.2.1 + parse5-htmlparser2-tree-adapter: 7.1.0 + dev: false + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + dependencies: + readdirp: 4.0.2 + dev: true + + /class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + dev: true + + /classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + dev: true + + /cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + dependencies: + restore-cursor: 5.1.0 + dev: true + + /cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + dev: true + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + dev: true + + /clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + /codemirror@6.65.7: + resolution: {integrity: sha512-HcfnUFJwI2FvH73YWVbbMh7ObWxZiHIycEhv9ZEXy6e8ZKDjtZKbbYFUtsLN46HFXPvU5V2Uvc2d55Z//oFW5A==} + deprecated: This is an accidentally mis-tagged instance of 5.65.7 + dev: false + + /collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: false + + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: true + + /compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + dev: true + + /component-event@0.2.1: + resolution: {integrity: sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==} + + /compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false + + /computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + dev: true + + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: true + + /conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + dev: true + + /core-js-compat@3.39.0: + resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} + dependencies: + browserslist: 4.24.2 + dev: true + + /core-js-pure@3.39.0: + resolution: {integrity: sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==} + requiresBuild: true + dev: false + + /core-js@3.39.0: + resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} + requiresBuild: true + dev: true + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + + /cosmiconfig-typescript-loader@5.1.0(@types/node@20.17.9)(cosmiconfig@9.0.0)(typescript@5.3.3): + resolution: {integrity: sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==} + engines: {node: '>=v16'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=8.2' + typescript: '>=4' + dependencies: + '@types/node': 20.17.9 + cosmiconfig: 9.0.0(typescript@5.3.3) + jiti: 1.21.6 + typescript: 5.3.3 + dev: true + + /cosmiconfig@9.0.0(typescript@5.3.3): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 5.3.3 + dev: true + + /crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + dev: true + + /cropperjs@1.6.2: + resolution: {integrity: sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==} + dev: false + + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + + /cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: false + + /css-functions-list@3.2.3: + resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==} + engines: {node: '>=12 || >=16'} + dev: true + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: true + + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: false + + /css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + dev: true + + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + dev: true + + /css-tree@3.0.1: + resolution: {integrity: sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.12.1 + source-map-js: 1.2.1 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + dependencies: + css-tree: 1.1.3 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + dependencies: + internmap: 2.0.3 + dev: false + + /d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + dev: false + + /d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: false + + /d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: false + + /d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + dev: false + + /d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + dependencies: + delaunator: 5.0.1 + dev: false + + /d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + dev: false + + /d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + dev: false + + /d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + dev: false + + /d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + dev: false + + /d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + dependencies: + d3-dsv: 3.0.1 + dev: false + + /d3-flextree@2.1.2: + resolution: {integrity: sha512-gJiHrx5uTTHq44bjyIb3xpbmmdZcWLYPKeO9EPVOq8EylMFOiH2+9sWqKAiQ4DcFuOZTAxPOQyv0Rnmji/g15A==} + dependencies: + d3-hierarchy: 1.1.9 + dev: false + + /d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + dev: false + + /d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + dev: false + + /d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-hierarchy@1.1.9: + resolution: {integrity: sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==} + dev: false + + /d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + dev: false + + /d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + dev: false + + /d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + dev: false + + /d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + dev: false + + /d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + dev: false + + /d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + dev: false + + /d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + dev: false + + /d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + dev: false + + /d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + dev: false + + /d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + dependencies: + d3-path: 3.1.0 + dev: false + + /d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + dependencies: + d3-time: 3.1.0 + dev: false + + /d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + dev: false + + /d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + dev: false + + /d3-transition@3.0.1(d3-selection@3.0.0): + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + dev: false + + /d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: false + + /d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + dev: false + + /d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + dev: false + + /dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + dev: true + + /data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dev: false + + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: false + + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.7 + dev: true + + /define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + dev: true + + /define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + dev: true + + /defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + dev: true + + /delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + dependencies: + robust-predicates: 3.0.2 + dev: false + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + dev: true + + /detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /diagram-js-direct-editing@3.2.0(diagram-js@14.11.3): + resolution: {integrity: sha512-+pyxeQGBSdLiZX0/tmmsm2qZSvm9YtVzod5W3RMHSTR7VrkUMD6E7EX/W9JQv3ebxO7oIdqFmytmNDDpSHnYEw==} + peerDependencies: + diagram-js: '*' + dependencies: + diagram-js: 14.11.3 + min-dash: 4.2.2 + min-dom: 4.2.1 + dev: true + + /diagram-js@12.8.1: + resolution: {integrity: sha512-LF9BiwjbOPpZd0ez5VSlYRbdbEA59YQX43bWvNDp1rLMv0xwZ5yIg4oaYDK82nIQ0kH1tjvoQRpNevMTCgQVyw==} + dependencies: + '@bpmn-io/diagram-js-ui': 0.2.3 + clsx: 2.1.1 + didi: 9.0.2 + hammerjs: 2.0.8 + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + object-refs: 0.3.0 + path-intersection: 2.2.1 + tiny-svg: 3.1.3 + + /diagram-js@14.11.3: + resolution: {integrity: sha512-Seq9BHAXfzKS60L4v4Gvgvv72wOtvrfJQAyyPm9pntSZDMzjoodPSXnEUPud1G2zVCMGEUUW++s0reEdaWgkXA==} + dependencies: + '@bpmn-io/diagram-js-ui': 0.2.3 + clsx: 2.1.1 + didi: 10.2.2 + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + object-refs: 0.4.0 + path-intersection: 3.1.0 + tiny-svg: 3.1.3 + dev: true + + /didi@10.2.2: + resolution: {integrity: sha512-l8NYkYFXV1izHI65EyT8EXOjUZtKmQkHLTT89cSP7HU5J/G7AOj0dXKtLc04EXYlga99PBY18IPjOeZ+c3DI4w==} + engines: {node: '>= 16'} + dev: true + + /didi@9.0.2: + resolution: {integrity: sha512-q2+aj+lnJcUweV7A9pdUrwFr4LHVmRPwTmQLtHPFz4aT7IBoryN6Iy+jmFku+oIzr5ebBkvtBCOb87+dJhb7bg==} + + /dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dev: false + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: true + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + /dom-walk@0.1.2: + resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + dev: false + + /dom7@3.0.0: + resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==} + dependencies: + ssr-window: 3.0.0 + dev: false + + /domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + /domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + dependencies: + domelementtype: 1.3.1 + dev: true + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + + /domify@1.4.2: + resolution: {integrity: sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA==} + + /domify@2.0.0: + resolution: {integrity: sha512-rmvrrmWQPD/X1A/nPBfIVg4r05792QdG9Z4Prk6oQG0F9zBMDkr0GKAdds1wjb2dq1rTz/ywc4ZxpZbgz0tttg==} + engines: {node: '>=18'} + dev: true + + /dompurify@3.2.1: + resolution: {integrity: sha512-NBHEsc0/kzRYQd+AY6HR6B/IgsqzBABrqJbpCDQII/OK6h7B7LXzweZTDsqSW2LkTRpoxf18YUP+YjGySk6B3w==} + optionalDependencies: + '@types/trusted-types': 2.0.7 + dev: false + + /domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + dev: true + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: true + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + /dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /driver.js@1.3.1: + resolution: {integrity: sha512-MvUdXbqSgEsgS/H9KyWb5Rxy0aE6BhOVT4cssi2x2XjmXea6qQfgdx32XKVLLSqTaIw7q/uxU5Xl3NV7+cN6FQ==} + dev: false + + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /echarts-wordcloud@2.1.0(echarts@5.5.1): + resolution: {integrity: sha512-Kt1JmbcROgb+3IMI48KZECK2AP5lG6bSsOEs+AsuwaWJxQom31RTNd6NFYI01E/YaI1PFZeueaupjlmzSQasjQ==} + peerDependencies: + echarts: ^5.0.1 + dependencies: + echarts: 5.5.1 + dev: false + + /echarts@5.5.1: + resolution: {integrity: sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==} + dependencies: + tslib: 2.3.0 + zrender: 5.6.0 + dev: false + + /ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.9.2 + dev: true + + /electron-to-chromium@1.5.67: + resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==} + dev: true + + /element-plus@2.9.1(vue@3.5.12): + resolution: {integrity: sha512-9Agqf/jt4Ugk7EZ6C5LME71sgkvauPCsnvJN12Xid2XVobjufxMGpRE4L7pS4luJMOmFAH3J0NgYEGZT5r+NDg==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.5.12) + '@floating-ui/dom': 1.6.12 + '@popperjs/core': /@sxzz/popperjs-es@2.11.7 + '@types/lodash': 4.17.13 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.12) + async-validator: 4.2.5 + dayjs: 1.11.13 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.12(typescript@5.3.3) + transitivePeerDependencies: + - '@vue/composition-api' + dev: false + + /emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + dev: true + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.23.5: + resolution: {integrity: sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.3 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.3 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.3 + typed-array-length: 1.0.7 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.16 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + /es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + dev: true + + /es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + dev: false + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + dev: false + + /es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + dependencies: + d: 1.0.2 + ext: 1.7.0 + dev: false + + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + + /escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.57.1): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.57.1 + dev: true + + /eslint-define-config@2.1.0: + resolution: {integrity: sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==} + engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>=8.6.0'} + dev: true + + /eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0)(eslint@8.57.1)(prettier@3.4.1): + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.57.1 + eslint-config-prettier: 9.1.0(eslint@8.57.1) + prettier: 3.4.1 + prettier-linter-helpers: 1.0.0 + synckit: 0.9.2 + dev: true + + /eslint-plugin-vue@9.31.0(eslint@8.57.1): + resolution: {integrity: sha512-aYMUCgivhz1o4tLkRHj5oq9YgYPM4/EJc0M7TAKRLCUA5OYxRLAhYEVD2nLtTwLyixEFI+/QXSvKU9ESZFgqjQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + eslint: 8.57.1 + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.6.3 + vue-eslint-parser: 9.4.3(eslint@8.57.1) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.1 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.3.7 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + dev: false + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 3.4.3 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.6 + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.3 + dev: false + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + dev: true + + /extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + dev: true + + /fast-xml-parser@4.5.0: + resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + hasBin: true + dependencies: + strnum: 1.0.5 + dev: false + + /fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /fdir@6.4.2(picomatch@4.0.2): + resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + dependencies: + picomatch: 4.0.2 + dev: true + + /feelers@1.4.0: + resolution: {integrity: sha512-CGa/7ILuqoqTaeYeoKsg/4tzu2es9sEEJTmSjdu0lousZBw4V9gcYhHYFNmbrSrKmbAVfOzj6/DsymGJWFIOeg==} + dependencies: + '@bpmn-io/cm-theme': 0.1.0-alpha.2 + '@bpmn-io/feel-lint': 1.3.1 + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3) + '@codemirror/commands': 6.7.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + '@lezer/markdown': 1.3.2 + feelin: 3.2.0 + lezer-feel: 1.4.0 + min-dom: 5.1.1 + dev: true + + /feelin@3.2.0: + resolution: {integrity: sha512-GFDbHsTYk7YXO1tyw1dOjb7IODeAZvNIosdGZThUwPx5XcD/XhO0hnPZXsIbAzSsIdrgGlTEEdby9fZ2gixysA==} + dependencies: + '@lezer/lr': 1.4.2 + lezer-feel: 1.4.0 + luxon: 3.5.0 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /file-entry-cache@9.1.0: + resolution: {integrity: sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==} + engines: {node: '>=18'} + dependencies: + flat-cache: 5.0.0 + dev: true + + /filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + dependencies: + minimatch: 5.1.6 + dev: true + + /fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + dev: true + + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flat-cache@5.0.0: + resolution: {integrity: sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==} + engines: {node: '>=18'} + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + dev: true + + /flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + dev: true + + /focus-trap@7.6.2: + resolution: {integrity: sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==} + dependencies: + tabbable: 6.2.0 + dev: true + + /follow-redirects@1.15.9(debug@4.3.7): + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dependencies: + debug: 4.3.7 + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: true + + /foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + dev: true + + /form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: true + + /fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + dev: true + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + /get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + dev: true + + /get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + dev: true + + /git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + dependencies: + ini: 4.1.1 + dev: true + + /global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: true + + /global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /global@4.4.0: + resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} + dependencies: + min-document: 2.19.0 + process: 0.11.10 + dev: false + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + dependencies: + duplexer: 0.1.2 + dev: true + + /hammerjs@2.0.8: + resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} + engines: {node: '>=0.8.0'} + + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + dev: true + + /has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + dev: true + + /has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + dev: true + + /has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /highlight.js@11.10.0: + resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==} + engines: {node: '>=12.0.0'} + dev: false + + /htm@3.1.1: + resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==} + + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + + /html-void-elements@2.0.1: + resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} + dev: false + + /htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /i18next@20.6.1: + resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} + dependencies: + '@babel/runtime': 7.26.0 + dev: false + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ids@1.0.5: + resolution: {integrity: sha512-XQ0yom/4KWTL29sLG+tyuycy7UmeaM/79GRtSJq6IG9cJGIPeBz5kwDCguie3TwxaMNIc3WtPi0cTa1XYHicpw==} + dev: true + + /ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + dev: true + + /ignore@6.0.2: + resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==} + engines: {node: '>= 4'} + dev: true + + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true + + /immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + dev: false + + /immutable@5.0.3: + resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /individual@2.0.0: + resolution: {integrity: sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==} + dev: false + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits-browser@0.1.0: + resolution: {integrity: sha512-CJHHvW3jQ6q7lzsXPpapLdMx5hDpSF3FSh45pwsj6bKxJJ8Nl8v43i5yXnr3BdfOimGHKyniewQtnAIp3vyJJw==} + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + dev: false + + /is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + dependencies: + hasown: 2.0.2 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + dev: true + + /is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.2 + dev: true + + /is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + dependencies: + is-typed-array: 1.1.13 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-finalizationregistry@1.1.0: + resolution: {integrity: sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + + /is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + dependencies: + get-east-asian-width: 1.3.0 + dev: true + + /is-function@1.0.2: + resolution: {integrity: sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==} + dev: false + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-hotkey@0.2.0: + resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} + dev: false + + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + dependencies: + text-extensions: 2.4.0 + dev: true + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.16 + dev: true + + /is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + dev: false + + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + + /jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + dev: true + + /js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /jsencrypt@3.3.2: + resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==} + dev: false + + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.14.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.6.3 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /katex@0.16.11: + resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: false + + /keycode@2.2.1: + resolution: {integrity: sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==} + dev: false + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /known-css-properties@0.35.0: + resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} + dev: true + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: true + + /lang-feel@2.2.0: + resolution: {integrity: sha512-Ebo5nftYsMfJzB3Ny8Oy4oaDXZXb5x61qtVVmKv6aImvAZUbT76mD60ZbEilizjZQzsR2CcU1iMK5sacIa1NVA==} + dependencies: + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3) + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.35.0 + '@lezer/common': 1.2.3 + lezer-feel: 1.4.0 + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lezer-feel@1.4.0: + resolution: {integrity: sha512-kNxG7O38gwpuYy+C3JCRxQNTCE2qu9uTuH5dE3EGVnRhIQMe6rPDz0S8t3urLEOsMud6HI795m6zX2ujfUaqTw==} + dependencies: + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + min-dash: 4.2.2 + dev: true + + /lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + dependencies: + uc.micro: 2.1.0 + dev: false + + /lint-staged@15.2.10: + resolution: {integrity: sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 12.1.0 + debug: 4.3.7 + execa: 8.0.1 + lilconfig: 3.1.2 + listr2: 8.2.5 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.5.1 + transitivePeerDependencies: + - supports-color + dev: true + + /listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + dev: true + + /loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + dev: true + + /local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + dev: true + + /local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + dependencies: + mlly: 1.7.3 + pkg-types: 1.2.1 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + + /lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + dev: false + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + /lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + dev: false + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + /lodash.foreach@4.5.0: + resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: false + + /lodash.toarray@4.4.0: + resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==} + dev: false + + /lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + dev: true + + /loglevel-colored-level-prefix@1.0.0: + resolution: {integrity: sha512-u45Wcxxc+SdAlh4yeF/uKlC1SPUPCy0gullSNKXod5I4bmifzk+Q4lSLExNEVn19tGaJipbZ4V4jbFn79/6mVA==} + dependencies: + chalk: 1.1.3 + loglevel: 1.9.2 + dev: true + + /loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} + dev: true + + /lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + dev: true + + /m3u8-parser@4.8.0: + resolution: {integrity: sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==} + dependencies: + '@babel/runtime': 7.26.0 + '@videojs/vhs-utils': 3.0.5 + global: 4.4.0 + dev: false + + /magic-string@0.30.14: + resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + dev: true + + /markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + dev: false + + /markmap-common@0.16.0: + resolution: {integrity: sha512-q3nlNDMKuWXTm3VwZFY9V5zteL/+iBLZanUK5vS+e26bUbzTSG5VtAzsyJbmgJm1WhwmIIAxbXEnp6JdvtTduA==} + dependencies: + '@babel/runtime': 7.26.0 + '@gera2ld/jsx-dom': 2.2.2 + npm2url: 0.2.4 + dev: false + + /markmap-html-parser@0.16.1(markmap-common@0.16.0): + resolution: {integrity: sha512-/Mgm4g1qMQ8uEOz8h8K+jPspdgjfw29NqmfTLZSt8yG+vW7fWWduPjGRFc5axAZxCzP7PTzZLEuOxAqOwEg8Bg==} + peerDependencies: + markmap-common: '*' + dependencies: + '@babel/runtime': 7.26.0 + cheerio: 1.0.0-rc.12 + markmap-common: 0.16.0 + dev: false + + /markmap-lib@0.16.1(markmap-common@0.16.0): + resolution: {integrity: sha512-jD8VsB67m677IRehGSwwVJDlC6PS+xzDKsJOwdvjZ+ndfXrHa1lyqfvR6mIwvGGUIciF86YEITSKL9hQTHE4Rw==} + peerDependencies: + markmap-common: '*' + dependencies: + '@babel/runtime': 7.26.0 + highlight.js: 11.10.0 + js-yaml: 4.1.0 + katex: 0.16.11 + markmap-common: 0.16.0 + markmap-html-parser: 0.16.1(markmap-common@0.16.0) + markmap-view: 0.16.0(markmap-common@0.16.0) + prismjs: 1.29.0 + remarkable: 2.0.1 + remarkable-katex: 1.2.1 + dev: false + + /markmap-toolbar@0.17.2(markmap-common@0.16.0): + resolution: {integrity: sha512-WQ05P2xvQmZT0ybRUE0uRzrs30aXlJ6/yEUsA6A9nYEwm8T9jSwBxIM/5zYlkH/XzUcsRRxtCa4k1IWR74gkpQ==} + peerDependencies: + markmap-common: '*' + dependencies: + '@babel/runtime': 7.26.0 + '@gera2ld/jsx-dom': 2.2.2 + markmap-common: 0.16.0 + dev: false + + /markmap-view@0.16.0(markmap-common@0.16.0): + resolution: {integrity: sha512-JOiSEThs8B4bAP9E6rcCWOz2SsMwCBFaR76wLARRVb04C/qLiLmvrm675kNPq4lRBAwtugHCYvjG0otpSlB4Cw==} + peerDependencies: + markmap-common: '*' + dependencies: + '@babel/runtime': 7.26.0 + '@gera2ld/jsx-dom': 2.2.2 + '@types/d3': 7.4.3 + d3: 7.9.0 + d3-flextree: 2.1.2 + markmap-common: 0.16.0 + dev: false + + /mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + dev: true + + /mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: true + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + + /mdn-data@2.12.1: + resolution: {integrity: sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==} + dev: true + + /mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + dev: false + + /memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + dev: false + + /meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + dev: true + + /meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + dev: true + + /merge-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + dependencies: + is-plain-obj: 1.1.0 + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-match@1.0.2: + resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==} + dependencies: + wildcard: 1.1.2 + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + dev: true + + /min-dash@4.2.2: + resolution: {integrity: sha512-qbhSYUxk6mBaF096B3JOQSumXbKWHenmT97cSpdNzgkWwGjhjhE/KZODCoDNhI2I4C9Cb6R/Q13S4BYkUSXoXQ==} + + /min-document@2.19.0: + resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + dependencies: + dom-walk: 0.1.2 + dev: false + + /min-dom@4.2.1: + resolution: {integrity: sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==} + dependencies: + component-event: 0.2.1 + domify: 1.4.2 + min-dash: 4.2.2 + + /min-dom@5.1.1: + resolution: {integrity: sha512-GaKUlguMAofd3OJsB0OkP17i5kucKqErgVCJxPawO9l5NwIPnr28SAr99zzlzMCWWljISBYrnZVWdE2Q92YGFQ==} + dependencies: + domify: 2.0.0 + min-dash: 4.2.2 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: false + + /mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + dev: true + + /mlly@1.7.3: + resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} + dependencies: + acorn: 8.14.0 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + dev: true + + /moddle-xml@10.1.0: + resolution: {integrity: sha512-erWckwLt+dYskewKXJso9u+aAZ5172lOiYxSOqKCPTy7L/xmqH1PoeoA7eVC7oJTt3PqF5TkZzUmbjGH6soQBg==} + dependencies: + min-dash: 4.2.2 + moddle: 6.2.3 + saxen: 8.1.2 + dev: true + + /moddle@6.2.3: + resolution: {integrity: sha512-bLVN+ZHL3aKnhxc19XtjUfvdJsS3EsiEJC7bT6YPD11qYmTzvsxrGgyYz1Ouof7TZuGw0lDJ1OLmEnxcpQWk3Q==} + dependencies: + min-dash: 4.2.2 + dev: true + + /mpd-parser@0.22.1: + resolution: {integrity: sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==} + hasBin: true + dependencies: + '@babel/runtime': 7.26.0 + '@videojs/vhs-utils': 3.0.5 + '@xmldom/xmldom': 0.8.10 + global: 4.4.0 + dev: false + + /mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: true + + /mux.js@6.0.1: + resolution: {integrity: sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==} + engines: {node: '>=8', npm: '>=5'} + hasBin: true + dependencies: + '@babel/runtime': 7.26.0 + global: 4.4.0 + dev: false + + /namespace-emitter@2.0.1: + resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==} + dev: false + + /nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: false + + /node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + requiresBuild: true + dev: true + optional: true + + /node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + dev: false + + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /npm2url@0.2.4: + resolution: {integrity: sha512-arzGp/hQz0Ey+ZGhF64XVH7Xqwd+1Q/po5uGiBbzph8ebX6T0uvt3N7c1nBHQNsQVykQgHhqoRTX7JFcHecGuw==} + dev: false + + /nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + dev: false + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + dev: true + + /object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + engines: {node: '>= 0.4'} + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object-refs@0.3.0: + resolution: {integrity: sha512-eP0ywuoWOaDoiake/6kTJlPJhs+k0qNm4nYRzXLNHj6vh+5M3i9R1epJTdxIPGlhWc4fNRQ7a6XJNCX+/L4FOQ==} + + /object-refs@0.4.0: + resolution: {integrity: sha512-6kJqKWryKZmtte6QYvouas0/EIJKPI1/MMIuRsiBlNuhIMfqYTggzX2F1AJ2+cDs288xyi9GL7FyasHINR98BQ==} + dev: true + + /object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + dependencies: + destr: 2.0.3 + node-fetch-native: 1.6.4 + ufo: 1.5.4 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + dependencies: + mimic-function: 5.0.1 + dev: true + + /optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.1.1 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + + /package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + dev: true + + /package-manager-detector@0.2.5: + resolution: {integrity: sha512-3dS7y28uua+UDbRCLBqltMBrbI+A5U2mI9YuxHRxIWYmLj3DwntEBmERYzIAQ4DMeuCUOBSak7dBHHoXKpOTYQ==} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + dependencies: + domhandler: 5.0.3 + parse5: 7.2.1 + dev: false + + /parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + dependencies: + entities: 4.5.0 + dev: false + + /pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + dev: true + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /path-intersection@2.2.1: + resolution: {integrity: sha512-9u8xvMcSfuOiStv9bPdnRJQhGQXLKurew94n4GPQCdH1nj9QKC9ObbNoIpiRq8skiOBxKkt277PgOoFgAt3/rA==} + + /path-intersection@3.1.0: + resolution: {integrity: sha512-3xS3lvv/vuwm5aH2BVvNRvnvwR2Drde7jQClKpCXTYXIMMjcw/EnMhzCgeHwqbCpzi760PEfAkU53vSIlrNr9A==} + engines: {node: '>= 14.20'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + dev: true + + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: true + + /picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + dev: true + + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /pinia-plugin-persistedstate@3.2.3(pinia@2.2.8): + resolution: {integrity: sha512-Cm819WBj/s5K5DGw55EwbXDtx+EZzM0YR5AZbq9XE3u0xvXwvX2JnWoFpWIcdzISBHqy9H1UiSIUmXyXqWsQRQ==} + peerDependencies: + pinia: ^2.0.0 + dependencies: + pinia: 2.2.8(typescript@5.3.3)(vue@3.5.12) + dev: false + + /pinia@2.2.8(typescript@5.3.3)(vue@3.5.12): + resolution: {integrity: sha512-NRTYy2g+kju5tBRe0oNlriZIbMNvma8ZJrpHsp3qudyiMEA8jMmPPKQ2QMHg0Oc4BkUyQYWagACabrwriCK9HQ==} + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.5.11 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + dependencies: + '@vue/devtools-api': 6.6.4 + typescript: 5.3.3 + vue: 3.5.12(typescript@5.3.3) + vue-demi: 0.14.10(vue@3.5.12) + dev: false + + /pkcs7@1.0.4: + resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==} + hasBin: true + dependencies: + '@babel/runtime': 7.26.0 + dev: false + + /pkg-types@1.2.1: + resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} + dependencies: + confbox: 0.1.8 + mlly: 1.7.3 + pathe: 1.1.2 + dev: true + + /pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + dev: false + + /posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss-html@1.7.0: + resolution: {integrity: sha512-MfcMpSUIaR/nNgeVS8AyvyDugXlADjN9AcV7e5rDfrF1wduIAGSkL4q2+wgrZgA3sHVAHLDO9FuauHhZYW2nBw==} + engines: {node: ^12 || >=14} + dependencies: + htmlparser2: 8.0.2 + js-tokens: 9.0.1 + postcss: 8.4.49 + postcss-safe-parser: 6.0.0(postcss@8.4.49) + dev: true + + /postcss-prefix-selector@1.16.1(postcss@5.2.18): + resolution: {integrity: sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==} + peerDependencies: + postcss: '>4 <9' + dependencies: + postcss: 5.2.18 + dev: true + + /postcss-resolve-nested-selector@0.1.6: + resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} + dev: true + + /postcss-safe-parser@6.0.0(postcss@8.4.49): + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + dependencies: + postcss: 8.4.49 + dev: true + + /postcss-safe-parser@7.0.1(postcss@8.4.49): + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.4.31 + dependencies: + postcss: 8.4.49 + dev: true + + /postcss-scss@4.0.9(postcss@8.4.49): + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + dependencies: + postcss: 8.4.49 + dev: true + + /postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-selector-parser@7.0.0: + resolution: {integrity: sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-sorting@8.0.2(postcss@8.4.49): + resolution: {integrity: sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==} + peerDependencies: + postcss: ^8.4.20 + dependencies: + postcss: 8.4.49 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + dev: true + + /postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + /posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + dev: true + + /posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + dev: true + + /posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + + /posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + + /preact@10.25.0: + resolution: {integrity: sha512-6bYnzlLxXV3OSpUxLdaxBmE7PMOu0aR3pG6lryK/0jmvcDFPlcXGQAt5DpK3RITWiDrfYZRI0druyaK/S9kYLg==} + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-eslint@16.3.0: + resolution: {integrity: sha512-Lh102TIFCr11PJKUMQ2kwNmxGhTsv/KzUg9QYF2Gkw259g/kPgndZDWavk7/ycbRvj2oz4BPZ1gCU8bhfZH/Xg==} + engines: {node: '>=16.10.0'} + peerDependencies: + prettier-plugin-svelte: ^3.0.0 + svelte-eslint-parser: '*' + peerDependenciesMeta: + prettier-plugin-svelte: + optional: true + svelte-eslint-parser: + optional: true + dependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + common-tags: 1.8.2 + dlv: 1.1.3 + eslint: 8.57.1 + indent-string: 4.0.0 + lodash.merge: 4.6.2 + loglevel-colored-level-prefix: 1.0.0 + prettier: 3.4.1 + pretty-format: 29.7.0 + require-relative: 0.8.7 + typescript: 5.3.3 + vue-eslint-parser: 9.4.3(eslint@8.57.1) + transitivePeerDependencies: + - supports-color + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@3.4.1: + resolution: {integrity: sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + dev: true + + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + dev: false + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: false + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + dev: false + + /qs@6.13.1: + resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: false + + /query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /randomcolor@0.6.2: + resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==} + dev: false + + /rd@2.0.1: + resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==} + dependencies: + '@types/node': 10.17.60 + dev: true + + /react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + dev: true + + /reflect.getprototypeof@1.0.7: + resolution: {integrity: sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + which-builtin-type: 1.2.0 + dev: true + + /regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + /regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + dependencies: + '@babel/runtime': 7.26.0 + dev: true + + /regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + dev: true + + /regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + + /regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + dev: true + + /regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + dev: true + + /regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + dependencies: + jsesc: 3.0.2 + dev: true + + /remarkable-katex@1.2.1: + resolution: {integrity: sha512-Y1VquJBZnaVsfsVcKW2hmjT+pDL7mp8l5WAVlvuvViltrdok2m1AIKmJv8SsH+mBY84PoMw67t3kTWw1dIm8+g==} + dev: false + + /remarkable@2.0.1: + resolution: {integrity: sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==} + engines: {node: '>= 6.0.0'} + hasBin: true + dependencies: + argparse: 1.0.10 + autolinker: 3.16.2 + dev: false + + /repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: false + + /require-relative@0.8.7: + resolution: {integrity: sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + dev: true + + /ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + dependencies: + glob: 10.4.5 + dev: true + + /robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + dev: false + + /rollup-plugin-purge-icons@0.10.0: + resolution: {integrity: sha512-GD2ftg4L9G/sagIhtCmBn5vdyzePOisniythubpbywP0Q3ix9rZuDeFvgXTPemOsc22pvH7t22ryYQIl0rwGog==} + engines: {node: '>= 12'} + dependencies: + '@purge-icons/core': 0.10.0 + '@purge-icons/generated': 0.10.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /rollup@4.27.4: + resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.27.4 + '@rollup/rollup-android-arm64': 4.27.4 + '@rollup/rollup-darwin-arm64': 4.27.4 + '@rollup/rollup-darwin-x64': 4.27.4 + '@rollup/rollup-freebsd-arm64': 4.27.4 + '@rollup/rollup-freebsd-x64': 4.27.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.4 + '@rollup/rollup-linux-arm-musleabihf': 4.27.4 + '@rollup/rollup-linux-arm64-gnu': 4.27.4 + '@rollup/rollup-linux-arm64-musl': 4.27.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.4 + '@rollup/rollup-linux-riscv64-gnu': 4.27.4 + '@rollup/rollup-linux-s390x-gnu': 4.27.4 + '@rollup/rollup-linux-x64-gnu': 4.27.4 + '@rollup/rollup-linux-x64-musl': 4.27.4 + '@rollup/rollup-win32-arm64-msvc': 4.27.4 + '@rollup/rollup-win32-ia32-msvc': 4.27.4 + '@rollup/rollup-win32-x64-msvc': 4.27.4 + fsevents: 2.3.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rust-result@1.0.0: + resolution: {integrity: sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==} + dependencies: + individual: 2.0.0 + dev: false + + /rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + dev: false + + /safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-json-parse@4.0.0: + resolution: {integrity: sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==} + dependencies: + rust-result: 1.0.0 + dev: false + + /safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + dev: true + + /safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + dependencies: + ret: 0.1.15 + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /sass@1.81.0: + resolution: {integrity: sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 4.0.1 + immutable: 5.0.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.0 + dev: true + + /sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + dev: false + + /saxen@8.1.2: + resolution: {integrity: sha512-xUOiiFbc3Ow7p8KMxwsGICPx46ZQvy3+qfNVhrkwfz3Vvq45eGt98Ft5IQaA1R/7Tb5B5MKh9fUR9x3c3nDTxw==} + dev: true + + /scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + dependencies: + compute-scroll-into-view: 1.0.20 + dev: false + + /scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.3 + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.28 + mrmime: 2.0.0 + totalist: 3.0.1 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slate-history@0.66.0(slate@0.72.8): + resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==} + peerDependencies: + slate: '>=0.65.3' + dependencies: + is-plain-object: 5.0.0 + slate: 0.72.8 + dev: false + + /slate@0.72.8: + resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==} + dependencies: + immer: 9.0.21 + is-plain-object: 5.0.0 + tiny-warning: 1.0.3 + dev: false + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + + /slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + dev: true + + /snabbdom@3.6.2: + resolution: {integrity: sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==} + engines: {node: '>=12.17.0'} + dev: false + + /snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + dev: true + + /snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /sortablejs@1.14.0: + resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==} + dev: false + + /sortablejs@1.15.6: + resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==} + dev: false + + /source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + /source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + dev: true + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + dev: true + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /ssr-window@3.0.0: + resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==} + dev: false + + /stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + dev: true + + /static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + dev: true + + /steady-xml@0.1.0: + resolution: {integrity: sha512-5sk17qO2wWRtonTNoBhoKAB35OSsGJOa3+NEa6D+1GS+de+ujDWxnflMkXBrviOfkNrPTUqduAdXhrMJs89nAw==} + engines: {node: '>=12.0.0'} + dev: false + + /strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.1.0 + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal@2.1.1: + resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} + dependencies: + js-tokens: 9.0.1 + dev: true + + /strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + dev: false + + /style-mod@4.1.2: + resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} + dev: true + + /stylelint-config-html@1.1.0(postcss-html@1.7.0)(stylelint@16.11.0): + resolution: {integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==} + engines: {node: ^12 || >=14} + peerDependencies: + postcss-html: ^1.0.0 + stylelint: '>=14.0.0' + dependencies: + postcss-html: 1.7.0 + stylelint: 16.11.0(typescript@5.3.3) + dev: true + + /stylelint-config-recommended@14.0.1(stylelint@16.11.0): + resolution: {integrity: sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.1.0 + dependencies: + stylelint: 16.11.0(typescript@5.3.3) + dev: true + + /stylelint-config-standard@36.0.1(stylelint@16.11.0): + resolution: {integrity: sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.1.0 + dependencies: + stylelint: 16.11.0(typescript@5.3.3) + stylelint-config-recommended: 14.0.1(stylelint@16.11.0) + dev: true + + /stylelint-order@6.0.4(stylelint@16.11.0): + resolution: {integrity: sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==} + peerDependencies: + stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1 + dependencies: + postcss: 8.4.49 + postcss-sorting: 8.0.2(postcss@8.4.49) + stylelint: 16.11.0(typescript@5.3.3) + dev: true + + /stylelint@16.11.0(typescript@5.3.3): + resolution: {integrity: sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) + '@csstools/css-tokenizer': 3.0.3 + '@csstools/media-query-list-parser': 4.0.2(@csstools/css-parser-algorithms@3.0.4)(@csstools/css-tokenizer@3.0.3) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.0.0) + '@dual-bundle/import-meta-resolve': 4.1.0 + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 9.0.0(typescript@5.3.3) + css-functions-list: 3.2.3 + css-tree: 3.0.1 + debug: 4.3.7 + fast-glob: 3.3.2 + fastest-levenshtein: 1.0.16 + file-entry-cache: 9.1.0 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 6.0.2 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.35.0 + mathml-tag-names: 2.1.3 + meow: 13.2.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-resolve-nested-selector: 0.1.6 + postcss-safe-parser: 7.0.1(postcss@8.4.49) + postcss-selector-parser: 7.0.0 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + supports-hyperlinks: 3.1.0 + svg-tags: 1.0.0 + table: 6.8.2 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + + /supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + dependencies: + has-flag: 1.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks@3.1.0: + resolution: {integrity: sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==} + engines: {node: '>=14.18'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.1(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.10 + transitivePeerDependencies: + - supports-color + dev: true + + /svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + dev: true + + /svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + stable: 0.1.8 + dev: true + + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.1 + dev: true + + /synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.1 + dev: true + + /systemjs@6.15.1: + resolution: {integrity: sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==} + dev: true + + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: true + + /table@6.8.2: + resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /terser@5.36.0: + resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.0 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tiny-svg@3.1.3: + resolution: {integrity: sha512-9mwnPqXInRsBmH/DO6NMxBE++9LsqpVXQSSTZGc5bomoKKvL5OX/Hlotw7XVXP6XLRcHWIzZpxfovGqWKgCypQ==} + + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + + /tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + dev: true + + /tinyglobby@0.2.10: + resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} + engines: {node: '>=12.0.0'} + dependencies: + fdir: 6.4.2(picomatch@4.0.2) + picomatch: 4.0.2 + dev: true + + /to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + dev: true + + /totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true + + /traverse@0.6.10: + resolution: {integrity: sha512-hN4uFRxbK+PX56DxYiGHsTn2dME3TVr9vbNqlQGcGcPhJAn+tdP126iA+TArMpI4YSgnTkMWyoLl5bf81Hi5TA==} + engines: {node: '>= 0.4'} + dependencies: + gopd: 1.0.1 + typedarray.prototype.slice: 1.0.3 + which-typed-array: 1.1.16 + dev: true + + /ts-api-utils@1.4.3(typescript@5.3.3): + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + dev: false + + /tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + dev: false + + /typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-offset@1.0.3: + resolution: {integrity: sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + reflect.getprototypeof: 1.0.7 + dev: true + + /typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + reflect.getprototypeof: 1.0.7 + dev: true + + /typedarray.prototype.slice@1.0.3: + resolution: {integrity: sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.5 + es-errors: 1.3.0 + typed-array-buffer: 1.0.2 + typed-array-byte-offset: 1.0.3 + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + + /uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + dev: false + + /ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unconfig@0.3.13: + resolution: {integrity: sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==} + dependencies: + '@antfu/utils': 0.7.10 + defu: 6.1.4 + jiti: 1.21.6 + dev: true + + /undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + dev: true + + /unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + + /unimport@3.14.2(rollup@4.27.4): + resolution: {integrity: sha512-FSxhbAylGGanyuTb3K0Ka3T9mnsD0+cRKbwOS11Li4Lh2whWS091e32JH4bIHrTckxlW9GnExAglADlxXjjzFw==} + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + acorn: 8.14.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 0.5.1 + magic-string: 0.30.14 + mlly: 1.7.3 + pathe: 1.1.2 + picomatch: 4.0.2 + pkg-types: 1.2.1 + scule: 1.3.0 + strip-literal: 2.1.1 + tinyglobby: 0.2.10 + unplugin: 1.16.0 + transitivePeerDependencies: + - rollup + dev: true + + /union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /unocss@0.58.9(postcss@8.4.49)(rollup@4.27.4)(vite@5.1.4): + resolution: {integrity: sha512-aqANXXP0RrtN4kSaTLn/7I6wh8o45LUdVgPzGu7Fan2DfH2+wpIs6frlnlHlOymnb+52dp6kXluQinddaUKW1A==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.58.9 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + dependencies: + '@unocss/astro': 0.58.9(rollup@4.27.4)(vite@5.1.4) + '@unocss/cli': 0.58.9(rollup@4.27.4) + '@unocss/core': 0.58.9 + '@unocss/extractor-arbitrary-variants': 0.58.9 + '@unocss/postcss': 0.58.9(postcss@8.4.49) + '@unocss/preset-attributify': 0.58.9 + '@unocss/preset-icons': 0.58.9 + '@unocss/preset-mini': 0.58.9 + '@unocss/preset-tagify': 0.58.9 + '@unocss/preset-typography': 0.58.9 + '@unocss/preset-uno': 0.58.9 + '@unocss/preset-web-fonts': 0.58.9 + '@unocss/preset-wind': 0.58.9 + '@unocss/reset': 0.58.9 + '@unocss/transformer-attributify-jsx': 0.58.9 + '@unocss/transformer-attributify-jsx-babel': 0.58.9 + '@unocss/transformer-compile-class': 0.58.9 + '@unocss/transformer-directives': 0.58.9 + '@unocss/transformer-variant-group': 0.58.9 + '@unocss/vite': 0.58.9(rollup@4.27.4)(vite@5.1.4) + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + dev: true + + /unplugin-auto-import@0.16.7(@vueuse/core@10.11.1)(rollup@4.27.4): + resolution: {integrity: sha512-w7XmnRlchq6YUFJVFGSvG1T/6j8GrdYN6Em9Wf0Ye+HXgD/22kont+WnuCAA0UaUoxtuvRR1u/mXKy63g/hfqQ==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': ^3.2.2 + '@vueuse/core': '*' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@vueuse/core': + optional: true + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@vueuse/core': 10.11.1(vue@3.5.12) + fast-glob: 3.3.2 + local-pkg: 0.5.1 + magic-string: 0.30.14 + minimatch: 9.0.5 + unimport: 3.14.2(rollup@4.27.4) + unplugin: 1.16.0 + transitivePeerDependencies: + - rollup + dev: true + + /unplugin-element-plus@0.8.0(rollup@4.27.4): + resolution: {integrity: sha512-jByUGY3FG2B8RJKFryqxx4eNtSTj+Hjlo8edcOdJymewndDQjThZ1pRUQHRjQsbKhTV2jEctJV7t7RJ405UL4g==} + engines: {node: '>=14.19.0'} + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + es-module-lexer: 1.5.4 + magic-string: 0.30.14 + unplugin: 1.16.0 + transitivePeerDependencies: + - rollup + dev: true + + /unplugin-vue-components@0.25.2(rollup@4.27.4)(vue@3.5.12): + resolution: {integrity: sha512-OVmLFqILH6w+eM8fyt/d/eoJT9A6WO51NZLf1vC5c1FZ4rmq2bbGxTy8WP2Jm7xwFdukaIdv819+UI7RClPyCA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/parser': ^7.15.8 + '@nuxt/kit': ^3.2.2 + vue: 2 || 3 + peerDependenciesMeta: + '@babel/parser': + optional: true + '@nuxt/kit': + optional: true + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + chokidar: 3.6.0 + debug: 4.3.7 + fast-glob: 3.3.2 + local-pkg: 0.4.3 + magic-string: 0.30.14 + minimatch: 9.0.5 + resolve: 1.22.8 + unplugin: 1.16.0 + vue: 3.5.12(typescript@5.3.3) + transitivePeerDependencies: + - rollup + - supports-color + dev: true + + /unplugin@1.16.0: + resolution: {integrity: sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==} + engines: {node: '>=14.0.0'} + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + dev: true + + /unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + dev: true + + /update-browserslist-db@1.1.1(browserslist@4.24.2): + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + dev: true + + /url-toolkit@2.2.5: + resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==} + dev: false + + /url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + dependencies: + punycode: 1.4.1 + qs: 6.13.1 + dev: false + + /use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /video.js@7.21.6: + resolution: {integrity: sha512-m41TbODrUCToVfK1aljVd296CwDQnCRewpIm5tTXMuV87YYSGw1H+VDOaV45HlpcWSsTWWLF++InDgGJfthfUw==} + dependencies: + '@babel/runtime': 7.26.0 + '@videojs/http-streaming': 2.16.3(video.js@7.21.6) + '@videojs/vhs-utils': 3.0.5 + '@videojs/xhr': 2.6.0 + aes-decrypter: 3.1.3 + global: 4.4.0 + keycode: 2.2.1 + m3u8-parser: 4.8.0 + mpd-parser: 0.22.1 + mux.js: 6.0.1 + safe-json-parse: 4.0.0 + videojs-font: 3.2.0 + videojs-vtt.js: 0.15.5 + dev: false + + /videojs-font@3.2.0: + resolution: {integrity: sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==} + dev: false + + /videojs-vtt.js@0.15.5: + resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==} + dependencies: + global: 4.4.0 + dev: false + + /vite-plugin-compression@0.5.1(vite@5.1.4): + resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} + peerDependencies: + vite: '>=2.0.0' + dependencies: + chalk: 4.1.2 + debug: 4.3.7 + fs-extra: 10.1.0 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - supports-color + dev: true + + /vite-plugin-ejs@1.7.0(vite@5.1.4): + resolution: {integrity: sha512-JNP3zQDC4mSbfoJ3G73s5mmZITD8NGjUmLkq4swxyahy/W0xuokK9U9IJGXw7KCggq6UucT6hJ0p+tQrNtqTZw==} + peerDependencies: + vite: '>=5.0.0' + dependencies: + ejs: 3.1.10 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + dev: true + + /vite-plugin-eslint@1.8.1(eslint@8.57.1)(vite@5.1.4): + resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==} + peerDependencies: + eslint: '>=7' + vite: '>=2' + dependencies: + '@rollup/pluginutils': 4.2.1 + '@types/eslint': 8.56.12 + eslint: 8.57.1 + rollup: 2.79.2 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + dev: true + + /vite-plugin-progress@0.0.7(vite@5.1.4): + resolution: {integrity: sha512-zyvKdcc/X+6hnw3J1HVV1TKrlFKC4Rh8GnDnWG/2qhRXjqytTcM++xZ+SAPnoDsSyWl8O93ymK0wZRgHAoglEQ==} + engines: {node: '>=14', pnpm: '>=7.0.0'} + peerDependencies: + vite: '>2.0.0-0' + dependencies: + picocolors: 1.1.1 + progress: 2.0.3 + rd: 2.0.1 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + dev: true + + /vite-plugin-purge-icons@0.10.0(vite@5.1.4): + resolution: {integrity: sha512-4fMJKQuBu9lAPJWjqGEytRaxty1pP9bWgQLA68dwbbaCXu6NBrOUb/3kMaUc7TP09kerEk+qTriCk05OZXpjwA==} + engines: {node: '>= 12'} + peerDependencies: + vite: '>=2' + dependencies: + '@purge-icons/core': 0.10.0 + '@purge-icons/generated': 0.10.0 + rollup-plugin-purge-icons: 0.10.0 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /vite-plugin-svg-icons@2.0.1(vite@5.1.4): + resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} + peerDependencies: + vite: '>=2.0.0' + dependencies: + '@types/svgo': 2.6.4 + cors: 2.8.5 + debug: 4.3.7 + etag: 1.8.1 + fs-extra: 10.1.0 + pathe: 0.2.0 + svg-baker: 1.7.0 + svgo: 2.8.0 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - supports-color + dev: true + + /vite-plugin-top-level-await@1.4.4(rollup@4.27.4)(vite@5.1.4): + resolution: {integrity: sha512-QyxQbvcMkgt+kDb12m2P8Ed35Sp6nXP+l8ptGrnHV9zgYDUpraO0CPdlqLSeBqvY2DToR52nutDG7mIHuysdiw==} + peerDependencies: + vite: '>=2.8' + dependencies: + '@rollup/plugin-virtual': 3.0.2(rollup@4.27.4) + '@swc/core': 1.9.3 + uuid: 10.0.0 + vite: 5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0) + transitivePeerDependencies: + - '@swc/helpers' + - rollup + dev: true + + /vite@5.1.4(@types/node@20.17.9)(sass@1.81.0)(terser@5.36.0): + resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.17.9 + esbuild: 0.19.12 + postcss: 8.4.49 + rollup: 4.27.4 + sass: 1.81.0 + terser: 5.36.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vue-demi@0.14.10(vue@3.5.12): + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.5.12(typescript@5.3.3) + + /vue-dompurify-html@4.1.4(vue@3.5.12): + resolution: {integrity: sha512-K0XDSZA4dmMMvAgW8yaCx1kAYQldmgXeHJaLPS0mlSKOu8B+onE06X4KfB5LGyX4jR3rlVosyWJczRBzR0sZ/g==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + dependencies: + dompurify: 3.2.1 + vue: 3.5.12(typescript@5.3.3) + vue-demi: 0.14.10(vue@3.5.12) + transitivePeerDependencies: + - '@vue/composition-api' + dev: false + + /vue-eslint-parser@9.4.3(eslint@8.57.1): + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.7 + eslint: 8.57.1 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + lodash: 4.17.21 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + dev: true + + /vue-i18n@9.10.2(vue@3.5.12): + resolution: {integrity: sha512-ECJ8RIFd+3c1d3m1pctQ6ywG5Yj8Efy1oYoAKQ9neRdkLbuKLVeW4gaY5HPkD/9ssf1pOnUrmIFjx2/gkGxmEw==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + dependencies: + '@intlify/core-base': 9.10.2 + '@intlify/shared': 9.10.2 + '@vue/devtools-api': 6.6.4 + vue: 3.5.12(typescript@5.3.3) + + /vue-router@4.4.5(vue@3.5.12): + resolution: {integrity: sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: true + + /vue-tsc@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.3.3) + semver: 7.6.3 + typescript: 5.3.3 + dev: true + + /vue-types@5.1.3(vue@3.5.12): + resolution: {integrity: sha512-3Wy6QcZl0VusCCHX3vYrWSILFlrOB2EQDoySnuYmASM5cUp1FivJGfkS5lp1CutDgyRb41g32r/1QCmiBj5i1Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + vue: ^2.0.0 || ^3.0.0 + peerDependenciesMeta: + vue: + optional: true + dependencies: + is-plain-object: 5.0.0 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /vue@3.5.12(typescript@5.3.3): + resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@vue/compiler-dom': 3.5.12 + '@vue/compiler-sfc': 3.5.12 + '@vue/runtime-dom': 3.5.12 + '@vue/server-renderer': 3.5.12(vue@3.5.12) + '@vue/shared': 3.5.12 + typescript: 5.3.3 + + /vuedraggable@4.1.0(vue@3.5.12): + resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==} + peerDependencies: + vue: ^3.0.1 + dependencies: + sortablejs: 1.14.0 + vue: 3.5.12(typescript@5.3.3) + dev: false + + /w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + dev: true + + /wangeditor@4.7.15: + resolution: {integrity: sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==} + dependencies: + '@babel/runtime': 7.26.0 + '@babel/runtime-corejs3': 7.26.0 + tslib: 2.8.1 + dev: false + + /web-storage-cache@1.1.1: + resolution: {integrity: sha512-D0MieGooOs8RpsrK+vnejXnvh4OOv/+lTFB35JRkJJQt+uOjPE08XpaE0QBLMTRu47B1KGT/Nq3Gbag3Orinzw==} + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true + + /webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + dev: true + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type@1.2.0: + resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.1.0 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.16 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: false + + /which-typed-array@1.1.16: + resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wildcard@1.1.2: + resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==} + dev: false + + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + dev: true + + /xml-js@1.6.11: + resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==} + hasBin: true + dependencies: + sax: 1.4.1 + dev: false + + /xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + dev: true + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yaml-eslint-parser@1.2.3: + resolution: {integrity: sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==} + engines: {node: ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.3 + lodash: 4.17.21 + yaml: 2.6.1 + dev: true + + /yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + dev: true + + /yaml@2.6.1: + resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} + engines: {node: '>= 14'} + hasBin: true + dev: true + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + dev: true + + /zeebe-bpmn-moddle@1.7.0: + resolution: {integrity: sha512-eZ6OXSt0c4n9V/oN/46gTlwDIS3GhWQLt9jbM5uS/YryB4yN8wdrrKrtw+TpyNy0SSKWXNDHyC83nCA2blPO3Q==} + dev: true + + /zrender@5.6.0: + resolution: {integrity: sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==} + dependencies: + tslib: 2.3.0 + dev: false diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..961986e --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {} + } +} diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..b014bbf --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,22 @@ +module.exports = { + printWidth: 100, // 每行代码长度(默认80) + tabWidth: 2, // 每个tab相当于多少个空格(默认2)ab进行缩进(默认false) + useTabs: false, // 是否使用tab + semi: false, // 声明结尾使用分号(默认true) + vueIndentScriptAndStyle: false, + singleQuote: true, // 使用单引号(默认false) + quoteProps: 'as-needed', + bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true) + trailingComma: 'none', // 多行使用拖尾逗号(默认none) + jsxSingleQuote: false, + // 箭头函数参数括号 默认avoid 可选 avoid| always + // avoid 能省略括号的时候就省略 例如x => x + // always 总是有括号 + arrowParens: 'always', + insertPragma: false, + requirePragma: false, + proseWrap: 'never', + htmlWhitespaceSensitivity: 'strict', + endOfLine: 'auto', + rangeStart: 0 +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..5a7de08 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/home.png b/public/home.png new file mode 100644 index 0000000..ccd4145 Binary files /dev/null and b/public/home.png differ diff --git a/public/logo.gif b/public/logo.gif new file mode 100644 index 0000000..fdbd32c Binary files /dev/null and b/public/logo.gif differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..7407d97 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/api/ai/chat/conversation/index.ts b/src/api/ai/chat/conversation/index.ts new file mode 100644 index 0000000..6ce4482 --- /dev/null +++ b/src/api/ai/chat/conversation/index.ts @@ -0,0 +1,65 @@ +import request from '@/config/axios' + +// AI 聊天对话 VO +export interface ChatConversationVO { + id: number // ID 编号 + userId: number // 用户编号 + title: string // 对话标题 + pinned: boolean // 是否置顶 + roleId: number // 角色编号 + modelId: number // 模型编号 + model: string // 模型标志 + temperature: number // 温度参数 + maxTokens: number // 单条回复的最大 Token 数量 + maxContexts: number // 上下文的最大 Message 数量 + createTime?: Date // 创建时间 + // 额外字段 + systemMessage?: string // 角色设定 + modelName?: string // 模型名字 + roleAvatar?: string // 角色头像 + modelMaxTokens?: string // 模型的单条回复的最大 Token 数量 + modelMaxContexts?: string // 模型的上下文的最大 Message 数量 +} + +// AI 聊天对话 API +export const ChatConversationApi = { + // 获得【我的】聊天对话 + getChatConversationMy: async (id: number) => { + return await request.get({ url: `/ai/chat/conversation/get-my?id=${id}` }) + }, + + // 新增【我的】聊天对话 + createChatConversationMy: async (data?: ChatConversationVO) => { + return await request.post({ url: `/ai/chat/conversation/create-my`, data }) + }, + + // 更新【我的】聊天对话 + updateChatConversationMy: async (data: ChatConversationVO) => { + return await request.put({ url: `/ai/chat/conversation/update-my`, data }) + }, + + // 删除【我的】聊天对话 + deleteChatConversationMy: async (id: string) => { + return await request.delete({ url: `/ai/chat/conversation/delete-my?id=${id}` }) + }, + + // 删除【我的】所有对话,置顶除外 + deleteChatConversationMyByUnpinned: async () => { + return await request.delete({ url: `/ai/chat/conversation/delete-by-unpinned` }) + }, + + // 获得【我的】聊天对话列表 + getChatConversationMyList: async () => { + return await request.get({ url: `/ai/chat/conversation/my-list` }) + }, + + // 获得对话分页 + getChatConversationPage: async (params: any) => { + return await request.get({ url: `/ai/chat/conversation/page`, params }) + }, + + // 管理员删除消息 + deleteChatConversationByAdmin: async (id: number) => { + return await request.delete({ url: `/ai/chat/conversation/delete-by-admin?id=${id}` }) + } +} diff --git a/src/api/ai/chat/message/index.ts b/src/api/ai/chat/message/index.ts new file mode 100644 index 0000000..ef1196a --- /dev/null +++ b/src/api/ai/chat/message/index.ts @@ -0,0 +1,83 @@ +import request from '@/config/axios' +import { fetchEventSource } from '@microsoft/fetch-event-source' +import { getAccessToken } from '@/utils/auth' +import { config } from '@/config/axios/config' + +// 聊天VO +export interface ChatMessageVO { + id: number // 编号 + conversationId: number // 对话编号 + type: string // 消息类型 + userId: string // 用户编号 + roleId: string // 角色编号 + model: number // 模型标志 + modelId: number // 模型编号 + content: string // 聊天内容 + tokens: number // 消耗 Token 数量 + createTime: Date // 创建时间 + roleAvatar: string // 角色头像 + userAvatar: string // 创建时间 +} + +// AI chat 聊天 +export const ChatMessageApi = { + // 消息列表 + getChatMessageListByConversationId: async (conversationId: number | null) => { + return await request.get({ + url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}` + }) + }, + + // 发送 Stream 消息 + // 为什么不用 axios 呢?因为它不支持 SSE 调用 + sendChatMessageStream: async ( + conversationId: number, + content: string, + ctrl, + enableContext: boolean, + onMessage, + onError, + onClose + ) => { + const token = getAccessToken() + return fetchEventSource(`${config.base_url}/ai/chat/message/send-stream`, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + openWhenHidden: true, + body: JSON.stringify({ + conversationId, + content, + useContext: enableContext + }), + onmessage: onMessage, + onerror: onError, + onclose: onClose, + signal: ctrl.signal + }) + }, + + // 删除消息 + deleteChatMessage: async (id: string) => { + return await request.delete({ url: `/ai/chat/message/delete?id=${id}` }) + }, + + // 删除指定对话的消息 + deleteByConversationId: async (conversationId: number) => { + return await request.delete({ + url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}` + }) + }, + + // 获得消息分页 + getChatMessagePage: async (params: any) => { + return await request.get({ url: '/ai/chat/message/page', params }) + }, + + // 管理员删除消息 + deleteChatMessageByAdmin: async (id: number) => { + return await request.delete({ url: `/ai/chat/message/delete-by-admin?id=${id}` }) + } +} diff --git a/src/api/ai/image/index.ts b/src/api/ai/image/index.ts new file mode 100644 index 0000000..2f276c7 --- /dev/null +++ b/src/api/ai/image/index.ts @@ -0,0 +1,103 @@ +import request from '@/config/axios' + +// AI 绘图 VO +export interface ImageVO { + id: number // 编号 + platform: string // 平台 + model: string // 模型 + prompt: string // 提示词 + width: number // 图片宽度 + height: number // 图片高度 + status: number // 状态 + publicStatus: boolean // 公开状态 + picUrl: string // 任务地址 + errorMessage: string // 错误信息 + options: any // 配置 Map + taskId: number // 任务编号 + buttons: ImageMidjourneyButtonsVO[] // mj 操作按钮 + createTime: Date // 创建时间 + finishTime: Date // 完成时间 +} + +export interface ImageDrawReqVO { + platform: string // 平台 + prompt: string // 提示词 + model: string // 模型 + style: string // 图像生成的风格 + width: string // 图片宽度 + height: string // 图片高度 + options: object // 绘制参数,Map +} + +export interface ImageMidjourneyImagineReqVO { + prompt: string // 提示词 + model: string // 模型 mj nijj + base64Array: string[] // size不能为空 + width: string // 图片宽度 + height: string // 图片高度 + version: string // 版本 +} + +export interface ImageMidjourneyActionVO { + id: number // 图片编号 + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 +} + +export interface ImageMidjourneyButtonsVO { + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 + emoji: string // 图标 emoji + label: string // Make Variations 文本 + style: number // 样式: 2(Primary)、3(Green) +} + +// AI 图片 API +export const ImageApi = { + // 获取【我的】绘图分页 + getImagePageMy: async (params: any) => { + return await request.get({ url: `/ai/image/my-page`, params }) + }, + // 获取【我的】绘图记录 + getImageMy: async (id: number) => { + return await request.get({ url: `/ai/image/get-my?id=${id}` }) + }, + // 获取【我的】绘图记录列表 + getImageListMyByIds: async (ids: number[]) => { + return await request.get({ url: `/ai/image/my-list-by-ids`, params: { ids: ids.join(',') } }) + }, + // 生成图片 + drawImage: async (data: ImageDrawReqVO) => { + return await request.post({ url: `/ai/image/draw`, data }) + }, + // 删除【我的】绘画记录 + deleteImageMy: async (id: number) => { + return await request.delete({ url: `/ai/image/delete-my?id=${id}` }) + }, + + // ================ midjourney 专属 ================ + + // 【Midjourney】生成图片 + midjourneyImagine: async (data: ImageMidjourneyImagineReqVO) => { + return await request.post({ url: `/ai/image/midjourney/imagine`, data }) + }, + // 【Midjourney】Action 操作(二次生成图片) + midjourneyAction: async (data: ImageMidjourneyActionVO) => { + return await request.post({ url: `/ai/image/midjourney/action`, data }) + }, + + // ================ 绘图管理 ================ + + // 查询绘画分页 + getImagePage: async (params: any) => { + return await request.get({ url: `/ai/image/page`, params }) + }, + + // 更新绘画发布状态 + updateImage: async (data: any) => { + return await request.put({ url: '/ai/image/update', data }) + }, + + // 删除绘画 + deleteImage: async (id: number) => { + return await request.delete({ url: `/ai/image/delete?id=` + id }) + } +} diff --git a/src/api/ai/mindmap/index.ts b/src/api/ai/mindmap/index.ts new file mode 100644 index 0000000..59b4fd8 --- /dev/null +++ b/src/api/ai/mindmap/index.ts @@ -0,0 +1,60 @@ +import { getAccessToken } from '@/utils/auth' +import { fetchEventSource } from '@microsoft/fetch-event-source' +import { config } from '@/config/axios/config' +import request from '@/config/axios' // AI 思维导图 VO + +// AI 思维导图 VO +export interface MindMapVO { + id: number // 编号 + userId: number // 用户编号 + prompt: string // 生成内容提示 + generatedContent: string // 生成的思维导图内容 + platform: string // 平台 + model: string // 模型 + errorMessage: string // 错误信息 +} + +// AI 思维导图生成 VO +export interface AiMindMapGenerateReqVO { + prompt: string +} + +export const AiMindMapApi = { + generateMindMap: ({ + data, + onClose, + onMessage, + onError, + ctrl + }: { + data: AiMindMapGenerateReqVO + onMessage?: (res: any) => void + onError?: (...args: any[]) => void + onClose?: (...args: any[]) => void + ctrl: AbortController + }) => { + const token = getAccessToken() + return fetchEventSource(`${config.base_url}/ai/mind-map/generate-stream`, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + openWhenHidden: true, + body: JSON.stringify(data), + onmessage: onMessage, + onerror: onError, + onclose: onClose, + signal: ctrl.signal + }) + }, + + // 查询思维导图分页 + getMindMapPage: async (params: any) => { + return await request.get({ url: `/ai/mind-map/page`, params }) + }, + // 删除思维导图 + deleteMindMap: async (id: number) => { + return await request.delete({ url: `/ai/mind-map/delete?id=` + id }) + } +} diff --git a/src/api/ai/model/apiKey/index.ts b/src/api/ai/model/apiKey/index.ts new file mode 100644 index 0000000..ed94836 --- /dev/null +++ b/src/api/ai/model/apiKey/index.ts @@ -0,0 +1,44 @@ +import request from '@/config/axios' + +// AI API 密钥 VO +export interface ApiKeyVO { + id: number // 编号 + name: string // 名称 + apiKey: string // 密钥 + platform: string // 平台 + url: string // 自定义 API 地址 + status: number // 状态 +} + +// AI API 密钥 API +export const ApiKeyApi = { + // 查询 API 密钥分页 + getApiKeyPage: async (params: any) => { + return await request.get({ url: `/ai/api-key/page`, params }) + }, + + // 获得 API 密钥列表 + getApiKeySimpleList: async () => { + return await request.get({ url: `/ai/api-key/simple-list` }) + }, + + // 查询 API 密钥详情 + getApiKey: async (id: number) => { + return await request.get({ url: `/ai/api-key/get?id=` + id }) + }, + + // 新增 API 密钥 + createApiKey: async (data: ApiKeyVO) => { + return await request.post({ url: `/ai/api-key/create`, data }) + }, + + // 修改 API 密钥 + updateApiKey: async (data: ApiKeyVO) => { + return await request.put({ url: `/ai/api-key/update`, data }) + }, + + // 删除 API 密钥 + deleteApiKey: async (id: number) => { + return await request.delete({ url: `/ai/api-key/delete?id=` + id }) + } +} diff --git a/src/api/ai/model/chatModel/index.ts b/src/api/ai/model/chatModel/index.ts new file mode 100644 index 0000000..c2ef4c8 --- /dev/null +++ b/src/api/ai/model/chatModel/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +// AI 聊天模型 VO +export interface ChatModelVO { + id: number // 编号 + keyId: number // API 秘钥编号 + name: string // 模型名字 + model: string // 模型标识 + platform: string // 模型平台 + sort: number // 排序 + status: number // 状态 + temperature: number // 温度参数 + maxTokens: number // 单条回复的最大 Token 数量 + maxContexts: number // 上下文的最大 Message 数量 +} + +// AI 聊天模型 API +export const ChatModelApi = { + // 查询聊天模型分页 + getChatModelPage: async (params: any) => { + return await request.get({ url: `/ai/chat-model/page`, params }) + }, + + // 获得聊天模型列表 + getChatModelSimpleList: async (status?: number) => { + return await request.get({ + url: `/ai/chat-model/simple-list`, + params: { + status + } + }) + }, + + // 查询聊天模型详情 + getChatModel: async (id: number) => { + return await request.get({ url: `/ai/chat-model/get?id=` + id }) + }, + + // 新增聊天模型 + createChatModel: async (data: ChatModelVO) => { + return await request.post({ url: `/ai/chat-model/create`, data }) + }, + + // 修改聊天模型 + updateChatModel: async (data: ChatModelVO) => { + return await request.put({ url: `/ai/chat-model/update`, data }) + }, + + // 删除聊天模型 + deleteChatModel: async (id: number) => { + return await request.delete({ url: `/ai/chat-model/delete?id=` + id }) + } +} diff --git a/src/api/ai/model/chatRole/index.ts b/src/api/ai/model/chatRole/index.ts new file mode 100644 index 0000000..a9fce13 --- /dev/null +++ b/src/api/ai/model/chatRole/index.ts @@ -0,0 +1,80 @@ +import request from '@/config/axios' + +// AI 聊天角色 VO +export interface ChatRoleVO { + id: number // 角色编号 + modelId: number // 模型编号 + name: string // 角色名称 + avatar: string // 角色头像 + category: string // 角色类别 + sort: number // 角色排序 + description: string // 角色描述 + systemMessage: string // 角色设定 + welcomeMessage: string // 角色设定 + publicStatus: boolean // 是否公开 + status: number // 状态 +} + +// AI 聊天角色 分页请求 vo +export interface ChatRolePageReqVO { + name?: string // 角色名称 + category?: string // 角色类别 + publicStatus: boolean // 是否公开 + pageNo: number // 是否公开 + pageSize: number // 是否公开 +} + +// AI 聊天角色 API +export const ChatRoleApi = { + // 查询聊天角色分页 + getChatRolePage: async (params: any) => { + return await request.get({ url: `/ai/chat-role/page`, params }) + }, + + // 查询聊天角色详情 + getChatRole: async (id: number) => { + return await request.get({ url: `/ai/chat-role/get?id=` + id }) + }, + + // 新增聊天角色 + createChatRole: async (data: ChatRoleVO) => { + return await request.post({ url: `/ai/chat-role/create`, data }) + }, + + // 修改聊天角色 + updateChatRole: async (data: ChatRoleVO) => { + return await request.put({ url: `/ai/chat-role/update`, data }) + }, + + // 删除聊天角色 + deleteChatRole: async (id: number) => { + return await request.delete({ url: `/ai/chat-role/delete?id=` + id }) + }, + + // ======= chat 聊天 + + // 获取 my role + getMyPage: async (params: ChatRolePageReqVO) => { + return await request.get({ url: `/ai/chat-role/my-page`, params}) + }, + + // 获取角色分类 + getCategoryList: async () => { + return await request.get({ url: `/ai/chat-role/category-list`}) + }, + + // 创建角色 + createMy: async (data: ChatRoleVO) => { + return await request.post({ url: `/ai/chat-role/create-my`, data}) + }, + + // 更新角色 + updateMy: async (data: ChatRoleVO) => { + return await request.put({ url: `/ai/chat-role/update-my`, data}) + }, + + // 删除角色 my + deleteMy: async (id: number) => { + return await request.delete({ url: `/ai/chat-role/delete-my?id=` + id }) + }, +} diff --git a/src/api/ai/music/index.ts b/src/api/ai/music/index.ts new file mode 100644 index 0000000..74b8526 --- /dev/null +++ b/src/api/ai/music/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// AI 音乐 VO +export interface MusicVO { + id: number // 编号 + userId: number // 用户编号 + title: string // 音乐名称 + lyric: string // 歌词 + imageUrl: string // 图片地址 + audioUrl: string // 音频地址 + videoUrl: string // 视频地址 + status: number // 音乐状态 + gptDescriptionPrompt: string // 描述词 + prompt: string // 提示词 + platform: string // 模型平台 + model: string // 模型 + generateMode: number // 生成模式 + tags: string // 音乐风格标签 + duration: number // 音乐时长 + publicStatus: boolean // 是否发布 + taskId: string // 任务id + errorMessage: string // 错误信息 +} + +// AI 音乐 API +export const MusicApi = { + // 查询音乐分页 + getMusicPage: async (params: any) => { + return await request.get({ url: `/ai/music/page`, params }) + }, + + // 更新音乐 + updateMusic: async (data: any) => { + return await request.put({ url: '/ai/music/update', data }) + }, + + // 删除音乐 + deleteMusic: async (id: number) => { + return await request.delete({ url: `/ai/music/delete?id=` + id }) + } +} diff --git a/src/api/ai/write/index.ts b/src/api/ai/write/index.ts new file mode 100644 index 0000000..013f998 --- /dev/null +++ b/src/api/ai/write/index.ts @@ -0,0 +1,85 @@ +import { fetchEventSource } from '@microsoft/fetch-event-source' + +import { getAccessToken } from '@/utils/auth' +import { config } from '@/config/axios/config' +import { AiWriteTypeEnum } from '@/views/ai/utils/constants' +import request from '@/config/axios' + +export interface WriteVO { + type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复 + prompt: string // 写作内容提示 1。撰写 2回复 + originalContent: string // 原文 + length: number // 长度 + format: number // 格式 + tone: number // 语气 + language: number // 语言 + userId?: number // 用户编号 + platform?: string // 平台 + model?: string // 模型 + generatedContent?: string // 生成的内容 + errorMessage?: string // 错误信息 + createTime?: Date // 创建时间 +} + +export interface AiWritePageReqVO extends PageParam { + userId?: number // 用户编号 + type?: AiWriteTypeEnum // 写作类型 + platform?: string // 平台 + createTime?: [string, string] // 创建时间 +} + +export interface AiWriteRespVo { + id: number + userId: number + type: number + platform: string + model: string + prompt: string + generatedContent: string + originalContent: string + length: number + format: number + tone: number + language: number + errorMessage: string + createTime: string +} + +export const WriteApi = { + writeStream: ({ + data, + onClose, + onMessage, + onError, + ctrl + }: { + data: WriteVO + onMessage?: (res: any) => void + onError?: (...args: any[]) => void + onClose?: (...args: any[]) => void + ctrl: AbortController + }) => { + const token = getAccessToken() + return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + openWhenHidden: true, + body: JSON.stringify(data), + onmessage: onMessage, + onerror: onError, + onclose: onClose, + signal: ctrl.signal + }) + }, + // 获取写作列表 + getWritePage: (params: AiWritePageReqVO) => { + return request.get>({ url: `/ai/write/page`, params }) + }, + // 删除写作 + deleteWrite(id: number) { + return request.delete({ url: `/ai/write/delete`, params: { id } }) + } +} diff --git a/src/api/bpm/category/index.ts b/src/api/bpm/category/index.ts new file mode 100644 index 0000000..1854f31 --- /dev/null +++ b/src/api/bpm/category/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +// BPM 流程分类 VO +export interface CategoryVO { + id: number // 分类编号 + name: string // 分类名 + code: string // 分类标志 + status: number // 分类状态 + sort: number // 分类排序 +} + +// BPM 流程分类 API +export const CategoryApi = { + // 查询流程分类分页 + getCategoryPage: async (params: any) => { + return await request.get({ url: `/bpm/category/page`, params }) + }, + + // 查询流程分类列表 + getCategorySimpleList: async () => { + return await request.get({ url: `/bpm/category/simple-list` }) + }, + + // 查询流程分类详情 + getCategory: async (id: number) => { + return await request.get({ url: `/bpm/category/get?id=` + id }) + }, + + // 新增流程分类 + createCategory: async (data: CategoryVO) => { + return await request.post({ url: `/bpm/category/create`, data }) + }, + + // 修改流程分类 + updateCategory: async (data: CategoryVO) => { + return await request.put({ url: `/bpm/category/update`, data }) + }, + + // 批量修改流程分类的排序 + updateCategorySortBatch: async (ids: number[]) => { + return await request.put({ + url: `/bpm/category/update-sort-batch`, + params: { + ids: ids.join(',') + } + }) + }, + + // 删除流程分类 + deleteCategory: async (id: number) => { + return await request.delete({ url: `/bpm/category/delete?id=` + id }) + } +} diff --git a/src/api/bpm/definition/index.ts b/src/api/bpm/definition/index.ts new file mode 100644 index 0000000..caedba1 --- /dev/null +++ b/src/api/bpm/definition/index.ts @@ -0,0 +1,22 @@ +import request from '@/config/axios' + +export const getProcessDefinition = async (id?: string, key?: string) => { + return await request.get({ + url: '/bpm/process-definition/get', + params: { id, key } + }) +} + +export const getProcessDefinitionPage = async (params) => { + return await request.get({ + url: '/bpm/process-definition/page', + params + }) +} + +export const getProcessDefinitionList = async (params) => { + return await request.get({ + url: '/bpm/process-definition/list', + params + }) +} diff --git a/src/api/bpm/form/index.ts b/src/api/bpm/form/index.ts new file mode 100644 index 0000000..7fce11f --- /dev/null +++ b/src/api/bpm/form/index.ts @@ -0,0 +1,56 @@ +import request from '@/config/axios' + +export type FormVO = { + id: number + name: string + conf: string + fields: string[] + status: number + remark: string + createTime: string +} + +// 创建工作流的表单定义 +export const createForm = async (data: FormVO) => { + return await request.post({ + url: '/bpm/form/create', + data: data + }) +} + +// 更新工作流的表单定义 +export const updateForm = async (data: FormVO) => { + return await request.put({ + url: '/bpm/form/update', + data: data + }) +} + +// 删除工作流的表单定义 +export const deleteForm = async (id: number) => { + return await request.delete({ + url: '/bpm/form/delete?id=' + id + }) +} + +// 获得工作流的表单定义 +export const getForm = async (id: number) => { + return await request.get({ + url: '/bpm/form/get?id=' + id + }) +} + +// 获得工作流的表单定义分页 +export const getFormPage = async (params) => { + return await request.get({ + url: '/bpm/form/page', + params + }) +} + +// 获得动态表单的精简列表 +export const getFormSimpleList = async () => { + return await request.get({ + url: '/bpm/form/simple-list' + }) +} diff --git a/src/api/bpm/leave/index.ts b/src/api/bpm/leave/index.ts new file mode 100644 index 0000000..4f374b2 --- /dev/null +++ b/src/api/bpm/leave/index.ts @@ -0,0 +1,27 @@ +import request from '@/config/axios' + +export type LeaveVO = { + id: number + status: number + type: number + reason: string + processInstanceId: string + startTime: string + endTime: string + createTime: string +} + +// 创建请假申请 +export const createLeave = async (data: LeaveVO) => { + return await request.post({ url: '/bpm/oa/leave/create', data: data }) +} + +// 获得请假申请 +export const getLeave = async (id: number) => { + return await request.get({ url: '/bpm/oa/leave/get?id=' + id }) +} + +// 获得请假申请分页 +export const getLeavePage = async (params: PageParam) => { + return await request.get({ url: '/bpm/oa/leave/page', params }) +} diff --git a/src/api/bpm/model/index.ts b/src/api/bpm/model/index.ts new file mode 100644 index 0000000..0c499db --- /dev/null +++ b/src/api/bpm/model/index.ts @@ -0,0 +1,74 @@ +import request from '@/config/axios' + +export type ProcessDefinitionVO = { + id: string + version: number + deploymentTIme: string + suspensionState: number + formType?: number +} + +export type ModelVO = { + id: number + formName: string + key: string + name: string + description: string + category: string + formType: number + formId: number + formCustomCreatePath: string + formCustomViewPath: string + processDefinition: ProcessDefinitionVO + status: number + remark: string + createTime: string + bpmnXml: string +} + +export const getModelList = async (name: string | undefined) => { + return await request.get({ url: '/bpm/model/list', params: { name } }) +} + +export const getModel = async (id: string) => { + return await request.get({ url: '/bpm/model/get?id=' + id }) +} + +export const updateModel = async (data: ModelVO) => { + return await request.put({ url: '/bpm/model/update', data: data }) +} + +// 批量修改流程分类的排序 +export const updateModelSortBatch = async (ids: number[]) => { + return await request.put({ + url: `/bpm/model/update-sort-batch`, + params: { + ids: ids.join(',') + } + }) +} + +export const updateModelBpmn = async (data: ModelVO) => { + return await request.put({ url: '/bpm/model/update-bpmn', data: data }) +} + +// 任务状态修改 +export const updateModelState = async (id: number, state: number) => { + const data = { + id: id, + state: state + } + return await request.put({ url: '/bpm/model/update-state', data: data }) +} + +export const createModel = async (data: ModelVO) => { + return await request.post({ url: '/bpm/model/create', data: data }) +} + +export const deleteModel = async (id: number) => { + return await request.delete({ url: '/bpm/model/delete?id=' + id }) +} + +export const deployModel = async (id: number) => { + return await request.post({ url: '/bpm/model/deploy?id=' + id }) +} diff --git a/src/api/bpm/processExpression/index.ts b/src/api/bpm/processExpression/index.ts new file mode 100644 index 0000000..af6a737 --- /dev/null +++ b/src/api/bpm/processExpression/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +// BPM 流程表达式 VO +export interface ProcessExpressionVO { + id: number // 编号 + name: string // 表达式名字 + status: number // 表达式状态 + expression: string // 表达式 +} + +// BPM 流程表达式 API +export const ProcessExpressionApi = { + // 查询BPM 流程表达式分页 + getProcessExpressionPage: async (params: any) => { + return await request.get({ url: `/bpm/process-expression/page`, params }) + }, + + // 查询BPM 流程表达式详情 + getProcessExpression: async (id: number) => { + return await request.get({ url: `/bpm/process-expression/get?id=` + id }) + }, + + // 新增BPM 流程表达式 + createProcessExpression: async (data: ProcessExpressionVO) => { + return await request.post({ url: `/bpm/process-expression/create`, data }) + }, + + // 修改BPM 流程表达式 + updateProcessExpression: async (data: ProcessExpressionVO) => { + return await request.put({ url: `/bpm/process-expression/update`, data }) + }, + + // 删除BPM 流程表达式 + deleteProcessExpression: async (id: number) => { + return await request.delete({ url: `/bpm/process-expression/delete?id=` + id }) + }, + + // 导出BPM 流程表达式 Excel + exportProcessExpression: async (params) => { + return await request.download({ url: `/bpm/process-expression/export-excel`, params }) + } +} \ No newline at end of file diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts new file mode 100644 index 0000000..f97270f --- /dev/null +++ b/src/api/bpm/processInstance/index.ts @@ -0,0 +1,103 @@ +import request from '@/config/axios' +import { ProcessDefinitionVO } from '@/api/bpm/model' +import { NodeType, CandidateStrategy } from '@/components/SimpleProcessDesignerV2/src/consts' +export type Task = { + id: string + name: string +} + +export type ProcessInstanceVO = { + id: number + name: string + processDefinitionId: string + category: string + result: number + tasks: Task[] + fields: string[] + status: number + remark: string + businessKey: string + createTime: string + endTime: string + processDefinition?: ProcessDefinitionVO +} + +// 用户信息 +export type User = { + id: number + nickname: string + avatar: string +} + +// 审批任务信息 +export type ApprovalTaskInfo = { + id: number + ownerUser: User + assigneeUser: User + status: number + reason: string +} + +// 审批节点信息 +export type ApprovalNodeInfo = { + id: number + name: string + nodeType: NodeType + candidateStrategy?: CandidateStrategy + status: number + startTime?: Date + endTime?: Date + candidateUsers?: User[] + tasks: ApprovalTaskInfo[] +} + +export const getProcessInstanceMyPage = async (params: any) => { + return await request.get({ url: '/bpm/process-instance/my-page', params }) +} + +export const getProcessInstanceManagerPage = async (params: any) => { + return await request.get({ url: '/bpm/process-instance/manager-page', params }) +} + +export const createProcessInstance = async (data) => { + return await request.post({ url: '/bpm/process-instance/create', data: data }) +} + +export const cancelProcessInstanceByStartUser = async (id: number, reason: string) => { + const data = { + id: id, + reason: reason + } + return await request.delete({ url: '/bpm/process-instance/cancel-by-start-user', data: data }) +} + +export const cancelProcessInstanceByAdmin = async (id: number, reason: string) => { + const data = { + id: id, + reason: reason + } + return await request.delete({ url: '/bpm/process-instance/cancel-by-admin', data: data }) +} + +export const getProcessInstance = async (id: string) => { + return await request.get({ url: '/bpm/process-instance/get?id=' + id }) +} + +export const getProcessInstanceCopyPage = async (params: any) => { + return await request.get({ url: '/bpm/process-instance/copy/page', params }) +} + +// 获取审批详情 +export const getApprovalDetail = async (params: any) => { + return await request.get({ url: 'bpm/process-instance/get-approval-detail' , params }) +} + +// 获取表单字段权限 +export const getFormFieldsPermission = async (params: any) => { + return await request.get({ url: '/bpm/process-instance/get-form-fields-permission', params }) +} + +// 获取流程实例的 BPMN 模型视图 +export const getProcessInstanceBpmnModelView = async (id: string) => { + return await request.get({ url: '/bpm/process-instance/get-bpmn-model-view?id=' + id }) +} diff --git a/src/api/bpm/processListener/index.ts b/src/api/bpm/processListener/index.ts new file mode 100644 index 0000000..dabaa47 --- /dev/null +++ b/src/api/bpm/processListener/index.ts @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +// BPM 流程监听器 VO +export interface ProcessListenerVO { + id: number // 编号 + name: string // 监听器名字 + type: string // 监听器类型 + status: number // 监听器状态 + event: string // 监听事件 + valueType: string // 监听器值类型 + value: string // 监听器值 +} + +// BPM 流程监听器 API +export const ProcessListenerApi = { + // 查询流程监听器分页 + getProcessListenerPage: async (params: any) => { + return await request.get({ url: `/bpm/process-listener/page`, params }) + }, + + // 查询流程监听器详情 + getProcessListener: async (id: number) => { + return await request.get({ url: `/bpm/process-listener/get?id=` + id }) + }, + + // 新增流程监听器 + createProcessListener: async (data: ProcessListenerVO) => { + return await request.post({ url: `/bpm/process-listener/create`, data }) + }, + + // 修改流程监听器 + updateProcessListener: async (data: ProcessListenerVO) => { + return await request.put({ url: `/bpm/process-listener/update`, data }) + }, + + // 删除流程监听器 + deleteProcessListener: async (id: number) => { + return await request.delete({ url: `/bpm/process-listener/delete?id=` + id }) + } +} diff --git a/src/api/bpm/simple/index.ts b/src/api/bpm/simple/index.ts new file mode 100644 index 0000000..6e1e995 --- /dev/null +++ b/src/api/bpm/simple/index.ts @@ -0,0 +1,15 @@ +import request from '@/config/axios' + + +export const updateBpmSimpleModel = async (data) => { + return await request.post({ + url: '/bpm/model/simple/update', + data: data + }) +} + +export const getBpmSimpleModel = async (id) => { + return await request.get({ + url: '/bpm/model/simple/get?id=' + id + }) +} diff --git a/src/api/bpm/task/index.ts b/src/api/bpm/task/index.ts new file mode 100644 index 0000000..d4c1038 --- /dev/null +++ b/src/api/bpm/task/index.ts @@ -0,0 +1,113 @@ +import request from '@/config/axios' + +/** + * 任务状态枚举 + */ +export enum TaskStatusEnum { + /** + * 未开始 + */ + NOT_START = -1, + + /** + * 待审批 + */ + WAIT = 0, + /** + * 审批中 + */ + RUNNING = 1, + /** + * 审批通过 + */ + APPROVE = 2, + + /** + * 审批不通过 + */ + REJECT = 3, + + /** + * 已取消 + */ + CANCEL = 4, + /** + * 已退回 + */ + RETURN = 5, + /** + * 审批通过中 + */ + APPROVING = 7 +} + +export const getTaskTodoPage = async (params: any) => { + return await request.get({ url: '/bpm/task/todo-page', params }) +} + +export const getTaskDonePage = async (params: any) => { + return await request.get({ url: '/bpm/task/done-page', params }) +} + +export const getTaskManagerPage = async (params: any) => { + return await request.get({ url: '/bpm/task/manager-page', params }) +} + +export const approveTask = async (data: any) => { + return await request.put({ url: '/bpm/task/approve', data }) +} + +export const rejectTask = async (data: any) => { + return await request.put({ url: '/bpm/task/reject', data }) +} + +export const getTaskListByProcessInstanceId = async (processInstanceId: string) => { + return await request.get({ + url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId + }) +} + +// 获取所有可退回的节点 +export const getTaskListByReturn = async (id: string) => { + return await request.get({ url: '/bpm/task/list-by-return', params: { id } }) +} + +// 退回 +export const returnTask = async (data: any) => { + return await request.put({ url: '/bpm/task/return', data }) +} + +// 委派 +export const delegateTask = async (data: any) => { + return await request.put({ url: '/bpm/task/delegate', data }) +} + +// 转派 +export const transferTask = async (data: any) => { + return await request.put({ url: '/bpm/task/transfer', data }) +} + +// 加签 +export const signCreateTask = async (data: any) => { + return await request.put({ url: '/bpm/task/create-sign', data }) +} + +// 减签 +export const signDeleteTask = async (data: any) => { + return await request.delete({ url: '/bpm/task/delete-sign', data }) +} + +// 抄送 +export const copyTask = async (data: any) => { + return await request.put({ url: '/bpm/task/copy', data }) +} + +// 获取我的待办任务 +export const myTodoTask = async (processInstanceId: string) => { + return await request.get({ url: '/bpm/task/my-todo?processInstanceId=' + processInstanceId }) +} + +// 获取减签任务列表 +export const getChildrenTaskList = async (id: string) => { + return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id }) +} diff --git a/src/api/bpm/userGroup/index.ts b/src/api/bpm/userGroup/index.ts new file mode 100644 index 0000000..7d12755 --- /dev/null +++ b/src/api/bpm/userGroup/index.ts @@ -0,0 +1,47 @@ +import request from '@/config/axios' + +export type UserGroupVO = { + id: number + name: string + description: string + userIds: number[] + status: number + remark: string + createTime: string +} + +// 创建用户组 +export const createUserGroup = async (data: UserGroupVO) => { + return await request.post({ + url: '/bpm/user-group/create', + data: data + }) +} + +// 更新用户组 +export const updateUserGroup = async (data: UserGroupVO) => { + return await request.put({ + url: '/bpm/user-group/update', + data: data + }) +} + +// 删除用户组 +export const deleteUserGroup = async (id: number) => { + return await request.delete({ url: '/bpm/user-group/delete?id=' + id }) +} + +// 获得用户组 +export const getUserGroup = async (id: number) => { + return await request.get({ url: '/bpm/user-group/get?id=' + id }) +} + +// 获得用户组分页 +export const getUserGroupPage = async (params) => { + return await request.get({ url: '/bpm/user-group/page', params }) +} + +// 获取用户组精简信息列表 +export const getUserGroupSimpleList = async (): Promise => { + return await request.get({ url: '/bpm/user-group/simple-list' }) +} diff --git a/src/api/crm/business/index.ts b/src/api/crm/business/index.ts new file mode 100644 index 0000000..2420425 --- /dev/null +++ b/src/api/crm/business/index.ts @@ -0,0 +1,98 @@ +import request from '@/config/axios' +import { TransferReqVO } from '@/api/crm/permission' + +export interface BusinessVO { + id: number + name: string + customerId: number + customerName?: string + followUpStatus: boolean + contactLastTime: Date + contactNextTime: Date + ownerUserId: number + ownerUserName?: string // 负责人的用户名称 + ownerUserDept?: string // 负责人的部门名称 + statusTypeId: number + statusTypeName?: string + statusId: number + statusName?: string + endStatus: number + endRemark: string + dealTime: Date + totalProductPrice: number + totalPrice: number + discountPercent: number + remark: string + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 + products?: [ + { + id: number + productId: number + productName: string + productNo: string + productUnit: number + productPrice: number + businessPrice: number + count: number + totalPrice: number + } + ] +} + +// 查询 CRM 商机列表 +export const getBusinessPage = async (params) => { + return await request.get({ url: `/crm/business/page`, params }) +} + +// 查询 CRM 商机列表,基于指定客户 +export const getBusinessPageByCustomer = async (params) => { + return await request.get({ url: `/crm/business/page-by-customer`, params }) +} + +// 查询 CRM 商机详情 +export const getBusiness = async (id: number) => { + return await request.get({ url: `/crm/business/get?id=` + id }) +} + +// 获得 CRM 商机列表(精简) +export const getSimpleBusinessList = async () => { + return await request.get({ url: `/crm/business/simple-all-list` }) +} + +// 新增 CRM 商机 +export const createBusiness = async (data: BusinessVO) => { + return await request.post({ url: `/crm/business/create`, data }) +} + +// 修改 CRM 商机 +export const updateBusiness = async (data: BusinessVO) => { + return await request.put({ url: `/crm/business/update`, data }) +} + +// 修改 CRM 商机状态 +export const updateBusinessStatus = async (data: BusinessVO) => { + return await request.put({ url: `/crm/business/update-status`, data }) +} + +// 删除 CRM 商机 +export const deleteBusiness = async (id: number) => { + return await request.delete({ url: `/crm/business/delete?id=` + id }) +} + +// 导出 CRM 商机 Excel +export const exportBusiness = async (params) => { + return await request.download({ url: `/crm/business/export-excel`, params }) +} + +// 联系人关联商机列表 +export const getBusinessPageByContact = async (params) => { + return await request.get({ url: `/crm/business/page-by-contact`, params }) +} + +// 商机转移 +export const transferBusiness = async (data: TransferReqVO) => { + return await request.put({ url: '/crm/business/transfer', data }) +} diff --git a/src/api/crm/business/status/index.ts b/src/api/crm/business/status/index.ts new file mode 100644 index 0000000..cddaa5a --- /dev/null +++ b/src/api/crm/business/status/index.ts @@ -0,0 +1,68 @@ +import request from '@/config/axios' + +export interface BusinessStatusTypeVO { + id: number + name: string + deptIds: number[] + statuses?: { + id: number + name: string + percent: number + } +} + +export const DEFAULT_STATUSES = [ + { + endStatus: 1, + key: '结束', + name: '赢单', + percent: 100 + }, + { + endStatus: 2, + key: '结束', + name: '输单', + percent: 0 + }, + { + endStatus: 3, + key: '结束', + name: '无效', + percent: 0 + } +] + +// 查询商机状态组列表 +export const getBusinessStatusPage = async (params: any) => { + return await request.get({ url: `/crm/business-status/page`, params }) +} + +// 新增商机状态组 +export const createBusinessStatus = async (data: BusinessStatusTypeVO) => { + return await request.post({ url: `/crm/business-status/create`, data }) +} + +// 修改商机状态组 +export const updateBusinessStatus = async (data: BusinessStatusTypeVO) => { + return await request.put({ url: `/crm/business-status/update`, data }) +} + +// 查询商机状态类型详情 +export const getBusinessStatus = async (id: number) => { + return await request.get({ url: `/crm/business-status/get?id=` + id }) +} + +// 删除商机状态 +export const deleteBusinessStatus = async (id: number) => { + return await request.delete({ url: `/crm/business-status/delete?id=` + id }) +} + +// 获得商机状态组列表 +export const getBusinessStatusTypeSimpleList = async () => { + return await request.get({ url: `/crm/business-status/type-simple-list` }) +} + +// 获得商机阶段列表 +export const getBusinessStatusSimpleList = async (typeId: number) => { + return await request.get({ url: `/crm/business-status/status-simple-list`, params: { typeId } }) +} diff --git a/src/api/crm/clue/index.ts b/src/api/crm/clue/index.ts new file mode 100644 index 0000000..9736514 --- /dev/null +++ b/src/api/crm/clue/index.ts @@ -0,0 +1,78 @@ +import request from '@/config/axios' +import { TransferReqVO } from '@/api/crm/permission' + +export interface ClueVO { + id: number // 编号 + name: string // 线索名称 + followUpStatus: boolean // 跟进状态 + contactLastTime: Date // 最后跟进时间 + contactLastContent: string // 最后跟进内容 + contactNextTime: Date // 下次联系时间 + ownerUserId: number // 负责人的用户编号 + ownerUserName?: string // 负责人的用户名称 + ownerUserDept?: string // 负责人的部门名称 + transformStatus: boolean // 转化状态 + customerId: number // 客户编号 + customerName?: string // 客户名称 + mobile: string // 手机号 + telephone: string // 电话 + qq: string // QQ + wechat: string // wechat + email: string // email + areaId: number // 所在地 + areaName?: string // 所在地名称 + detailAddress: string // 详细地址 + industryId: number // 所属行业 + level: number // 客户等级 + source: number // 客户来源 + remark: string // 备注 + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 +} + +// 查询线索列表 +export const getCluePage = async (params: any) => { + return await request.get({ url: `/crm/clue/page`, params }) +} + +// 查询线索详情 +export const getClue = async (id: number) => { + return await request.get({ url: `/crm/clue/get?id=` + id }) +} + +// 新增线索 +export const createClue = async (data: ClueVO) => { + return await request.post({ url: `/crm/clue/create`, data }) +} + +// 修改线索 +export const updateClue = async (data: ClueVO) => { + return await request.put({ url: `/crm/clue/update`, data }) +} + +// 删除线索 +export const deleteClue = async (id: number) => { + return await request.delete({ url: `/crm/clue/delete?id=` + id }) +} + +// 导出线索 Excel +export const exportClue = async (params) => { + return await request.download({ url: `/crm/clue/export-excel`, params }) +} + +// 线索转移 +export const transferClue = async (data: TransferReqVO) => { + return await request.put({ url: '/crm/clue/transfer', data }) +} + +// 线索转化为客户 +export const transformClue = async (id: number) => { + return await request.put({ url: '/crm/clue/transform', params: { id } }) +} + +// 获得分配给我的、待跟进的线索数量 +export const getFollowClueCount = async () => { + return await request.get({ url: '/crm/clue/follow-count' }) +} diff --git a/src/api/crm/contact/index.ts b/src/api/crm/contact/index.ts new file mode 100644 index 0000000..7c24dfa --- /dev/null +++ b/src/api/crm/contact/index.ts @@ -0,0 +1,113 @@ +import request from '@/config/axios' +import { TransferReqVO } from '@/api/crm/permission' + +export interface ContactVO { + id: number // 编号 + name: string // 联系人名称 + customerId: number // 客户编号 + customerName?: string // 客户名称 + contactLastTime: Date // 最后跟进时间 + contactLastContent: string // 最后跟进内容 + contactNextTime: Date // 下次联系时间 + ownerUserId: number // 负责人的用户编号 + ownerUserName?: string // 负责人的用户名称 + ownerUserDept?: string // 负责人的部门名称 + mobile: string // 手机号 + telephone: string // 电话 + qq: string // QQ + wechat: string // wechat + email: string // email + areaId: number // 所在地 + areaName?: string // 所在地名称 + detailAddress: string // 详细地址 + sex: number // 性别 + master: boolean // 是否主联系人 + post: string // 职务 + parentId: number // 上级联系人编号 + parentName?: string // 上级联系人名称 + remark: string // 备注 + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 +} + +export interface ContactBusinessReqVO { + contactId: number + businessIds: number[] +} + +export interface ContactBusiness2ReqVO { + businessId: number + contactIds: number[] +} + +// 查询 CRM 联系人列表 +export const getContactPage = async (params) => { + return await request.get({ url: `/crm/contact/page`, params }) +} + +// 查询 CRM 联系人列表,基于指定客户 +export const getContactPageByCustomer = async (params: any) => { + return await request.get({ url: `/crm/contact/page-by-customer`, params }) +} + +// 查询 CRM 联系人列表,基于指定商机 +export const getContactPageByBusiness = async (params: any) => { + return await request.get({ url: `/crm/contact/page-by-business`, params }) +} + +// 查询 CRM 联系人详情 +export const getContact = async (id: number) => { + return await request.get({ url: `/crm/contact/get?id=` + id }) +} + +// 新增 CRM 联系人 +export const createContact = async (data: ContactVO) => { + return await request.post({ url: `/crm/contact/create`, data }) +} + +// 修改 CRM 联系人 +export const updateContact = async (data: ContactVO) => { + return await request.put({ url: `/crm/contact/update`, data }) +} + +// 删除 CRM 联系人 +export const deleteContact = async (id: number) => { + return await request.delete({ url: `/crm/contact/delete?id=` + id }) +} + +// 导出 CRM 联系人 Excel +export const exportContact = async (params) => { + return await request.download({ url: `/crm/contact/export-excel`, params }) +} + +// 获得 CRM 联系人列表(精简) +export const getSimpleContactList = async () => { + return await request.get({ url: `/crm/contact/simple-all-list` }) +} + +// 批量新增联系人商机关联 +export const createContactBusinessList = async (data: ContactBusinessReqVO) => { + return await request.post({ url: `/crm/contact/create-business-list`, data }) +} + +// 批量新增联系人商机关联 +export const createContactBusinessList2 = async (data: ContactBusiness2ReqVO) => { + return await request.post({ url: `/crm/contact/create-business-list2`, data }) +} + +// 解除联系人商机关联 +export const deleteContactBusinessList = async (data: ContactBusinessReqVO) => { + return await request.delete({ url: `/crm/contact/delete-business-list`, data }) +} + +// 解除联系人商机关联 +export const deleteContactBusinessList2 = async (data: ContactBusiness2ReqVO) => { + return await request.delete({ url: `/crm/contact/delete-business-list2`, data }) +} + +// 联系人转移 +export const transferContact = async (data: TransferReqVO) => { + return await request.put({ url: '/crm/contact/transfer', data }) +} diff --git a/src/api/crm/contract/config/index.ts b/src/api/crm/contract/config/index.ts new file mode 100644 index 0000000..0c7ad20 --- /dev/null +++ b/src/api/crm/contract/config/index.ts @@ -0,0 +1,16 @@ +import request from '@/config/axios' + +export interface ContractConfigVO { + notifyEnabled?: boolean + notifyDays?: number +} + +// 获取合同配置 +export const getContractConfig = async () => { + return await request.get({ url: `/crm/contract-config/get` }) +} + +// 更新合同配置 +export const saveContractConfig = async (data: ContractConfigVO) => { + return await request.put({ url: `/crm/contract-config/save`, data }) +} diff --git a/src/api/crm/contract/index.ts b/src/api/crm/contract/index.ts new file mode 100644 index 0000000..7028b77 --- /dev/null +++ b/src/api/crm/contract/index.ts @@ -0,0 +1,114 @@ +import request from '@/config/axios' +import { TransferReqVO } from '@/api/crm/permission' + +export interface ContractVO { + id: number + name: string + no: string + customerId: number + customerName?: string + businessId: number + businessName: string + contactLastTime: Date + ownerUserId: number + ownerUserName?: string + ownerUserDeptName?: string + processInstanceId: number + auditStatus: number + orderDate: Date + startTime: Date + endTime: Date + totalProductPrice: number + discountPercent: number + totalPrice: number + totalReceivablePrice: number + signContactId: number + signContactName?: string + signUserId: number + signUserName: string + remark: string + createTime?: Date + creator: string + creatorName: string + updateTime?: Date + products?: [ + { + id: number + productId: number + productName: string + productNo: string + productUnit: number + productPrice: number + contractPrice: number + count: number + totalPrice: number + } + ] +} + +// 查询 CRM 合同列表 +export const getContractPage = async (params) => { + return await request.get({ url: `/crm/contract/page`, params }) +} + +// 查询 CRM 联系人列表,基于指定客户 +export const getContractPageByCustomer = async (params: any) => { + return await request.get({ url: `/crm/contract/page-by-customer`, params }) +} + +// 查询 CRM 联系人列表,基于指定商机 +export const getContractPageByBusiness = async (params: any) => { + return await request.get({ url: `/crm/contract/page-by-business`, params }) +} + +// 查询 CRM 合同详情 +export const getContract = async (id: number) => { + return await request.get({ url: `/crm/contract/get?id=` + id }) +} + +// 查询 CRM 合同下拉列表 +export const getContractSimpleList = async (customerId: number) => { + return await request.get({ + url: `/crm/contract/simple-list?customerId=${customerId}` + }) +} + +// 新增 CRM 合同 +export const createContract = async (data: ContractVO) => { + return await request.post({ url: `/crm/contract/create`, data }) +} + +// 修改 CRM 合同 +export const updateContract = async (data: ContractVO) => { + return await request.put({ url: `/crm/contract/update`, data }) +} + +// 删除 CRM 合同 +export const deleteContract = async (id: number) => { + return await request.delete({ url: `/crm/contract/delete?id=` + id }) +} + +// 导出 CRM 合同 Excel +export const exportContract = async (params) => { + return await request.download({ url: `/crm/contract/export-excel`, params }) +} + +// 提交审核 +export const submitContract = async (id: number) => { + return await request.put({ url: `/crm/contract/submit?id=${id}` }) +} + +// 合同转移 +export const transferContract = async (data: TransferReqVO) => { + return await request.put({ url: '/crm/contract/transfer', data }) +} + +// 获得待审核合同数量 +export const getAuditContractCount = async () => { + return await request.get({ url: '/crm/contract/audit-count' }) +} + +// 获得即将到期(提醒)的合同数量 +export const getRemindContractCount = async () => { + return await request.get({ url: '/crm/contract/remind-count' }) +} diff --git a/src/api/crm/customer/index.ts b/src/api/crm/customer/index.ts new file mode 100644 index 0000000..d149d4e --- /dev/null +++ b/src/api/crm/customer/index.ts @@ -0,0 +1,132 @@ +import request from '@/config/axios' +import { TransferReqVO } from '@/api/crm/permission' + +export interface CustomerVO { + id: number // 编号 + name: string // 客户名称 + followUpStatus: boolean // 跟进状态 + contactLastTime: Date // 最后跟进时间 + contactLastContent: string // 最后跟进内容 + contactNextTime: Date // 下次联系时间 + ownerUserId: number // 负责人的用户编号 + ownerUserName?: string // 负责人的用户名称 + ownerUserDept?: string // 负责人的部门名称 + lockStatus?: boolean + dealStatus?: boolean + mobile: string // 手机号 + telephone: string // 电话 + qq: string // QQ + wechat: string // wechat + email: string // email + areaId: number // 所在地 + areaName?: string // 所在地名称 + detailAddress: string // 详细地址 + industryId: number // 所属行业 + level: number // 客户等级 + source: number // 客户来源 + remark: string // 备注 + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 +} + +// 查询客户列表 +export const getCustomerPage = async (params) => { + return await request.get({ url: `/crm/customer/page`, params }) +} + +// 进入公海客户提醒的客户列表 +export const getPutPoolRemindCustomerPage = async (params) => { + return await request.get({ url: `/crm/customer/put-pool-remind-page`, params }) +} + +// 获得待进入公海客户数量 +export const getPutPoolRemindCustomerCount = async () => { + return await request.get({ url: `/crm/customer/put-pool-remind-count` }) +} + +// 获得今日需联系客户数量 +export const getTodayContactCustomerCount = async () => { + return await request.get({ url: `/crm/customer/today-contact-count` }) +} + +// 获得分配给我、待跟进的线索数量的客户数量 +export const getFollowCustomerCount = async () => { + return await request.get({ url: `/crm/customer/follow-count` }) +} + +// 查询客户详情 +export const getCustomer = async (id: number) => { + return await request.get({ url: `/crm/customer/get?id=` + id }) +} + +// 新增客户 +export const createCustomer = async (data: CustomerVO) => { + return await request.post({ url: `/crm/customer/create`, data }) +} + +// 修改客户 +export const updateCustomer = async (data: CustomerVO) => { + return await request.put({ url: `/crm/customer/update`, data }) +} + +// 更新客户的成交状态 +export const updateCustomerDealStatus = async (id: number, dealStatus: boolean) => { + return await request.put({ url: `/crm/customer/update-deal-status`, params: { id, dealStatus } }) +} + +// 删除客户 +export const deleteCustomer = async (id: number) => { + return await request.delete({ url: `/crm/customer/delete?id=` + id }) +} + +// 导出客户 Excel +export const exportCustomer = async (params: any) => { + return await request.download({ url: `/crm/customer/export-excel`, params }) +} + +// 下载客户导入模板 +export const importCustomerTemplate = () => { + return request.download({ url: '/crm/customer/get-import-template' }) +} + +// 导入客户 +export const handleImport = async (formData) => { + return await request.upload({ url: `/crm/customer/import`, data: formData }) +} + +// 客户列表 +export const getCustomerSimpleList = async () => { + return await request.get({ url: `/crm/customer/simple-list` }) +} + +// ======================= 业务操作 ======================= + +// 客户转移 +export const transferCustomer = async (data: TransferReqVO) => { + return await request.put({ url: '/crm/customer/transfer', data }) +} + +// 锁定/解锁客户 +export const lockCustomer = async (id: number, lockStatus: boolean) => { + return await request.put({ url: `/crm/customer/lock`, data: { id, lockStatus } }) +} + +// 领取公海客户 +export const receiveCustomer = async (ids: any[]) => { + return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } }) +} + +// 分配公海给对应负责人 +export const distributeCustomer = async (ids: any[], ownerUserId: number) => { + return await request.put({ + url: '/crm/customer/distribute', + data: { ids: ids, ownerUserId } + }) +} + +// 客户放入公海 +export const putCustomerPool = async (id: number) => { + return await request.put({ url: `/crm/customer/put-pool?id=${id}` }) +} diff --git a/src/api/crm/customer/limitConfig/index.ts b/src/api/crm/customer/limitConfig/index.ts new file mode 100644 index 0000000..8677632 --- /dev/null +++ b/src/api/crm/customer/limitConfig/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface CustomerLimitConfigVO { + id?: number + type?: number + userIds?: string + deptIds?: string + maxCount?: number + dealCountEnabled?: boolean +} + +/** + * 客户限制配置类型 + */ +export enum LimitConfType { + /** + * 拥有客户数限制 + */ + CUSTOMER_QUANTITY_LIMIT = 1, + /** + * 锁定客户数限制 + */ + CUSTOMER_LOCK_LIMIT = 2 +} + +// 查询客户限制配置列表 +export const getCustomerLimitConfigPage = async (params) => { + return await request.get({ url: `/crm/customer-limit-config/page`, params }) +} + +// 查询客户限制配置详情 +export const getCustomerLimitConfig = async (id: number) => { + return await request.get({ url: `/crm/customer-limit-config/get?id=` + id }) +} + +// 新增客户限制配置 +export const createCustomerLimitConfig = async (data: CustomerLimitConfigVO) => { + return await request.post({ url: `/crm/customer-limit-config/create`, data }) +} + +// 修改客户限制配置 +export const updateCustomerLimitConfig = async (data: CustomerLimitConfigVO) => { + return await request.put({ url: `/crm/customer-limit-config/update`, data }) +} + +// 删除客户限制配置 +export const deleteCustomerLimitConfig = async (id: number) => { + return await request.delete({ url: `/crm/customer-limit-config/delete?id=` + id }) +} diff --git a/src/api/crm/customer/poolConfig/index.ts b/src/api/crm/customer/poolConfig/index.ts new file mode 100644 index 0000000..b96e61f --- /dev/null +++ b/src/api/crm/customer/poolConfig/index.ts @@ -0,0 +1,19 @@ +import request from '@/config/axios' + +export interface CustomerPoolConfigVO { + enabled?: boolean + contactExpireDays?: number + dealExpireDays?: number + notifyEnabled?: boolean + notifyDays?: number +} + +// 获取客户公海规则设置 +export const getCustomerPoolConfig = async () => { + return await request.get({ url: `/crm/customer-pool-config/get` }) +} + +// 更新客户公海规则设置 +export const saveCustomerPoolConfig = async (data: CustomerPoolConfigVO) => { + return await request.put({ url: `/crm/customer-pool-config/save`, data }) +} diff --git a/src/api/crm/followup/index.ts b/src/api/crm/followup/index.ts new file mode 100644 index 0000000..414f3f7 --- /dev/null +++ b/src/api/crm/followup/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +// 跟进记录 VO +export interface FollowUpRecordVO { + id: number // 编号 + bizType: number // 数据类型 + bizId: number // 数据编号 + type: number // 跟进类型 + content: string // 跟进内容 + picUrls: string[] // 图片 + fileUrls: string[] // 附件 + nextTime: Date // 下次联系时间 + businessIds: number[] // 关联的商机编号数组 + businesses: { + id: number + name: string + }[] // 关联的商机数组 + contactIds: number[] // 关联的联系人编号数组 + contacts: { + id: number + name: string + }[] // 关联的联系人数组 + creator: string + creatorName?: string +} + +// 跟进记录 API +export const FollowUpRecordApi = { + // 查询跟进记录分页 + getFollowUpRecordPage: async (params: any) => { + return await request.get({ url: `/crm/follow-up-record/page`, params }) + }, + + // 新增跟进记录 + createFollowUpRecord: async (data: FollowUpRecordVO) => { + return await request.post({ url: `/crm/follow-up-record/create`, data }) + }, + + // 删除跟进记录 + deleteFollowUpRecord: async (id: number) => { + return await request.delete({ url: `/crm/follow-up-record/delete?id=` + id }) + } +} diff --git a/src/api/crm/operateLog/index.ts b/src/api/crm/operateLog/index.ts new file mode 100644 index 0000000..d0f25b6 --- /dev/null +++ b/src/api/crm/operateLog/index.ts @@ -0,0 +1,11 @@ +import request from '@/config/axios' + +export interface OperateLogVO extends PageParam { + bizType: number + bizId: number +} + +// 获得操作日志 +export const getOperateLogPage = async (params: OperateLogVO) => { + return await request.get({ url: `/crm/operate-log/page`, params }) +} diff --git a/src/api/crm/permission/index.ts b/src/api/crm/permission/index.ts new file mode 100644 index 0000000..4f88b14 --- /dev/null +++ b/src/api/crm/permission/index.ts @@ -0,0 +1,72 @@ +import request from '@/config/axios' + +export interface PermissionVO { + id?: number // 数据权限编号 + userId: number // 用户编号 + bizType: number // Crm 类型 + bizId: number // Crm 类型数据编号 + level: number // 权限级别 + toBizTypes?: number[] // 同时添加至 + deptName?: string // 部门名称 + nickname?: string // 用户昵称 + postNames?: string[] // 岗位名称数组 + createTime?: Date + ids?: number[] +} + +export interface TransferReqVO { + id: number // 模块编号 + newOwnerUserId: number // 新负责人的用户编号 + oldOwnerPermissionLevel?: number // 老负责人加入团队后的权限级别 + toBizTypes?: number[] // 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择 +} + +/** + * CRM 业务类型枚举 + * + * @author HUIHUI + */ +export enum BizTypeEnum { + CRM_CLUE = 1, // 线索 + CRM_CUSTOMER = 2, // 客户 + CRM_CONTACT = 3, // 联系人 + CRM_BUSINESS = 4, // 商机 + CRM_CONTRACT = 5, // 合同 + CRM_PRODUCT = 6, // 产品 + CRM_RECEIVABLE = 7, // 回款 + CRM_RECEIVABLE_PLAN = 8 // 回款计划 +} + +/** + * CRM 数据权限级别枚举 + */ +export enum PermissionLevelEnum { + OWNER = 1, // 负责人 + READ = 2, // 只读 + WRITE = 3 // 读写 +} + +// 获得数据权限列表(查询团队成员列表) +export const getPermissionList = async (params) => { + return await request.get({ url: `/crm/permission/list`, params }) +} + +// 创建数据权限(新增团队成员) +export const createPermission = async (data: PermissionVO) => { + return await request.post({ url: `/crm/permission/create`, data }) +} + +// 编辑数据权限(修改团队成员权限级别) +export const updatePermission = async (data) => { + return await request.put({ url: `/crm/permission/update`, data }) +} + +// 删除数据权限(删除团队成员) +export const deletePermissionBatch = async (val: number[]) => { + return await request.delete({ url: '/crm/permission/delete?ids=' + val.join(',') }) +} + +// 删除自己的数据权限(退出团队) +export const deleteSelfPermission = async (id: number) => { + return await request.delete({ url: '/crm/permission/delete-self?id=' + id }) +} diff --git a/src/api/crm/product/category/index.ts b/src/api/crm/product/category/index.ts new file mode 100644 index 0000000..6341d1b --- /dev/null +++ b/src/api/crm/product/category/index.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +// TODO @zange:挪到 product 下,建个 category 包,挪进去哈; +export interface ProductCategoryVO { + id: number + name: string + parentId: number +} + +// 查询产品分类详情 +export const getProductCategory = async (id: number) => { + return await request.get({ url: `/crm/product-category/get?id=` + id }) +} + +// 新增产品分类 +export const createProductCategory = async (data: ProductCategoryVO) => { + return await request.post({ url: `/crm/product-category/create`, data }) +} + +// 修改产品分类 +export const updateProductCategory = async (data: ProductCategoryVO) => { + return await request.put({ url: `/crm/product-category/update`, data }) +} + +// 删除产品分类 +export const deleteProductCategory = async (id: number) => { + return await request.delete({ url: `/crm/product-category/delete?id=` + id }) +} + +// 产品分类列表 +export const getProductCategoryList = async (params) => { + return await request.get({ url: `/crm/product-category/list`, params }) +} diff --git a/src/api/crm/product/index.ts b/src/api/crm/product/index.ts new file mode 100644 index 0000000..f0c2328 --- /dev/null +++ b/src/api/crm/product/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface ProductVO { + id: number + name: string + no: string + unit: number + price: number + status: number + categoryId: number + categoryName?: string + description: string + ownerUserId: number +} + +// 查询产品列表 +export const getProductPage = async (params) => { + return await request.get({ url: `/crm/product/page`, params }) +} + +// 获得产品精简列表 +export const getProductSimpleList = async () => { + return await request.get({ url: `/crm/product/simple-list` }) +} + +// 查询产品详情 +export const getProduct = async (id: number) => { + return await request.get({ url: `/crm/product/get?id=` + id }) +} + +// 新增产品 +export const createProduct = async (data: ProductVO) => { + return await request.post({ url: `/crm/product/create`, data }) +} + +// 修改产品 +export const updateProduct = async (data: ProductVO) => { + return await request.put({ url: `/crm/product/update`, data }) +} + +// 删除产品 +export const deleteProduct = async (id: number) => { + return await request.delete({ url: `/crm/product/delete?id=` + id }) +} + +// 导出产品 Excel +export const exportProduct = async (params) => { + return await request.download({ url: `/crm/product/export-excel`, params }) +} diff --git a/src/api/crm/receivable/index.ts b/src/api/crm/receivable/index.ts new file mode 100644 index 0000000..32ecd25 --- /dev/null +++ b/src/api/crm/receivable/index.ts @@ -0,0 +1,73 @@ +import request from '@/config/axios' + +export interface ReceivableVO { + id: number + no: string + planId?: number + customerId?: number + customerName?: string + contractId?: number + contract?: { + id?: number + name?: string + no: string + totalPrice: number + } + auditStatus: number + processInstanceId: number + returnTime: Date + returnType: number + price: number + ownerUserId: number + ownerUserName?: string + remark: string + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 +} + +// 查询回款列表 +export const getReceivablePage = async (params) => { + return await request.get({ url: `/crm/receivable/page`, params }) +} + +// 查询回款列表 +export const getReceivablePageByCustomer = async (params) => { + return await request.get({ url: `/crm/receivable/page-by-customer`, params }) +} + +// 查询回款详情 +export const getReceivable = async (id: number) => { + return await request.get({ url: `/crm/receivable/get?id=` + id }) +} + +// 新增回款 +export const createReceivable = async (data: ReceivableVO) => { + return await request.post({ url: `/crm/receivable/create`, data }) +} + +// 修改回款 +export const updateReceivable = async (data: ReceivableVO) => { + return await request.put({ url: `/crm/receivable/update`, data }) +} + +// 删除回款 +export const deleteReceivable = async (id: number) => { + return await request.delete({ url: `/crm/receivable/delete?id=` + id }) +} + +// 导出回款 Excel +export const exportReceivable = async (params) => { + return await request.download({ url: `/crm/receivable/export-excel`, params }) +} + +// 提交审核 +export const submitReceivable = async (id: number) => { + return await request.put({ url: `/crm/receivable/submit?id=${id}` }) +} + +// 获得待审核回款数量 +export const getAuditReceivableCount = async () => { + return await request.get({ url: '/crm/receivable/audit-count' }) +} diff --git a/src/api/crm/receivable/plan/index.ts b/src/api/crm/receivable/plan/index.ts new file mode 100644 index 0000000..770b347 --- /dev/null +++ b/src/api/crm/receivable/plan/index.ts @@ -0,0 +1,74 @@ +import request from '@/config/axios' + +export interface ReceivablePlanVO { + id: number + period: number + receivableId: number + price: number + returnTime: Date + remindDays: number + returnType: number + remindTime: Date + customerId: number + customerName?: string + contractId?: number + contractNo?: string + ownerUserId: number + ownerUserName?: string + remark: string + creator: string // 创建人 + creatorName?: string // 创建人名称 + createTime: Date // 创建时间 + updateTime: Date // 更新时间 + receivable?: { + price: number + returnTime: Date + } +} + +// 查询回款计划列表 +export const getReceivablePlanPage = async (params) => { + return await request.get({ url: `/crm/receivable-plan/page`, params }) +} + +// 查询回款计划列表 +export const getReceivablePlanPageByCustomer = async (params) => { + return await request.get({ url: `/crm/receivable-plan/page-by-customer`, params }) +} + +// 查询回款计划详情 +export const getReceivablePlan = async (id: number) => { + return await request.get({ url: `/crm/receivable-plan/get?id=` + id }) +} + +// 查询回款计划下拉数据 +export const getReceivablePlanSimpleList = async (customerId: number, contractId: number) => { + return await request.get({ + url: `/crm/receivable-plan/simple-list?customerId=${customerId}&contractId=${contractId}` + }) +} + +// 新增回款计划 +export const createReceivablePlan = async (data: ReceivablePlanVO) => { + return await request.post({ url: `/crm/receivable-plan/create`, data }) +} + +// 修改回款计划 +export const updateReceivablePlan = async (data: ReceivablePlanVO) => { + return await request.put({ url: `/crm/receivable-plan/update`, data }) +} + +// 删除回款计划 +export const deleteReceivablePlan = async (id: number) => { + return await request.delete({ url: `/crm/receivable-plan/delete?id=` + id }) +} + +// 导出回款计划 Excel +export const exportReceivablePlan = async (params) => { + return await request.download({ url: `/crm/receivable-plan/export-excel`, params }) +} + +// 获得待回款提醒数量 +export const getReceivablePlanRemindCount = async () => { + return await request.get({ url: '/crm/receivable-plan/remind-count' }) +} diff --git a/src/api/crm/statistics/customer.ts b/src/api/crm/statistics/customer.ts new file mode 100644 index 0000000..c2092e4 --- /dev/null +++ b/src/api/crm/statistics/customer.ts @@ -0,0 +1,168 @@ +import request from '@/config/axios' + +export interface CrmStatisticsCustomerSummaryByDateRespVO { + time: string + customerCreateCount: number + customerDealCount: number +} + +export interface CrmStatisticsCustomerSummaryByUserRespVO { + ownerUserName: string + customerCreateCount: number + customerDealCount: number + contractPrice: number + receivablePrice: number +} + +export interface CrmStatisticsFollowUpSummaryByDateRespVO { + time: string + followUpRecordCount: number + followUpCustomerCount: number +} + +export interface CrmStatisticsFollowUpSummaryByUserRespVO { + ownerUserName: string + followupRecordCount: number + followupCustomerCount: number +} + +export interface CrmStatisticsFollowUpSummaryByTypeRespVO { + followUpType: string + followUpRecordCount: number +} + +export interface CrmStatisticsCustomerContractSummaryRespVO { + customerName: string + contractName: string + totalPrice: number + receivablePrice: number + customerType: string + customerSource: string + ownerUserName: string + creatorUserName: string + createTime: Date + orderDate: Date +} + +export interface CrmStatisticsPoolSummaryByDateRespVO { + time: string + customerPutCount: number + customerTakeCount: number +} + +export interface CrmStatisticsPoolSummaryByUserRespVO { + ownerUserName: string + customerPutCount: number + customerTakeCount: number +} + +export interface CrmStatisticsCustomerDealCycleByDateRespVO { + time: string + customerDealCycle: number +} + +export interface CrmStatisticsCustomerDealCycleByUserRespVO { + ownerUserName: string + customerDealCycle: number + customerDealCount: number +} + +export interface CrmStatisticsCustomerDealCycleByAreaRespVO { + areaName: string + customerDealCycle: number + customerDealCount: number +} + +export interface CrmStatisticsCustomerDealCycleByProductRespVO { + productName: string + customerDealCycle: number + customerDealCount: number +} + +// 客户分析 API +export const StatisticsCustomerApi = { + // 1.1 客户总量分析(按日期) + getCustomerSummaryByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-summary-by-date', + params + }) + }, + // 1.2 客户总量分析(按用户) + getCustomerSummaryByUser: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-summary-by-user', + params + }) + }, + // 2.1 客户跟进次数分析(按日期) + getFollowUpSummaryByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-follow-up-summary-by-date', + params + }) + }, + // 2.2 客户跟进次数分析(按用户) + getFollowUpSummaryByUser: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-follow-up-summary-by-user', + params + }) + }, + // 3.1 获取客户跟进方式统计数 + getFollowUpSummaryByType: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-follow-up-summary-by-type', + params + }) + }, + // 4.1 合同摘要信息(客户转化率页面) + getContractSummary: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-contract-summary', + params + }) + }, + // 5.1 获取客户公海分析(按日期) + getPoolSummaryByDate: (param: any) => { + return request.get({ + url: '/crm/statistics-customer/get-pool-summary-by-date', + params: param + }) + }, + // 5.2 获取客户公海分析(按用户) + getPoolSummaryByUser: (param: any) => { + return request.get({ + url: '/crm/statistics-customer/get-pool-summary-by-user', + params: param + }) + }, + // 6.1 获取客户成交周期(按日期) + getCustomerDealCycleByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-deal-cycle-by-date', + params + }) + }, + // 6.2 获取客户成交周期(按用户) + getCustomerDealCycleByUser: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-deal-cycle-by-user', + params + }) + }, + // 6.2 获取客户成交周期(按用户) + getCustomerDealCycleByArea: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-deal-cycle-by-area', + params + }) + }, + // 6.2 获取客户成交周期(按用户) + getCustomerDealCycleByProduct: (params: any) => { + return request.get({ + url: '/crm/statistics-customer/get-customer-deal-cycle-by-product', + params + }) + } +} diff --git a/src/api/crm/statistics/funnel.ts b/src/api/crm/statistics/funnel.ts new file mode 100644 index 0000000..574a5f4 --- /dev/null +++ b/src/api/crm/statistics/funnel.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' + +export interface CrmStatisticFunnelRespVO { + customerCount: number // 客户数 + businessCount: number // 商机数 + businessWinCount: number // 赢单数 +} + +export interface CrmStatisticsBusinessSummaryByDateRespVO { + time: string // 时间 + businessCreateCount: number // 商机数 + totalPrice: number | string // 商机金额 +} + +export interface CrmStatisticsBusinessInversionRateSummaryByDateRespVO { + time: string // 时间 + businessCount: number // 商机数量 + businessWinCount: number // 赢单商机数 +} + +// 客户分析 API +export const StatisticFunnelApi = { + // 1. 获取销售漏斗统计数据 + getFunnelSummary: (params: any) => { + return request.get({ + url: '/crm/statistics-funnel/get-funnel-summary', + params + }) + }, + // 2. 获取商机结束状态统计 + getBusinessSummaryByEndStatus: (params: any) => { + return request.get({ + url: '/crm/statistics-funnel/get-business-summary-by-end-status', + params + }) + }, + // 3. 获取新增商机分析(按日期) + getBusinessSummaryByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-funnel/get-business-summary-by-date', + params + }) + }, + // 4. 获取商机转化率分析(按日期) + getBusinessInversionRateSummaryByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-funnel/get-business-inversion-rate-summary-by-date', + params + }) + }, + // 5. 获取商机列表(按日期) + getBusinessPageByDate: (params: any) => { + return request.get({ + url: '/crm/statistics-funnel/get-business-page-by-date', + params + }) + } +} diff --git a/src/api/crm/statistics/performance.ts b/src/api/crm/statistics/performance.ts new file mode 100644 index 0000000..2318505 --- /dev/null +++ b/src/api/crm/statistics/performance.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +export interface StatisticsPerformanceRespVO { + time: string + currentMonthCount: number + lastMonthCount: number + lastYearCount: number +} + +// 排行 API +export const StatisticsPerformanceApi = { + // 员工获得合同金额统计 + getContractPricePerformance: (params: any) => { + return request.get({ + url: '/crm/statistics-performance/get-contract-price-performance', + params + }) + }, + // 员工获得回款统计 + getReceivablePricePerformance: (params: any) => { + return request.get({ + url: '/crm/statistics-performance/get-receivable-price-performance', + params + }) + }, + //员工获得签约合同数量统计 + getContractCountPerformance: (params: any) => { + return request.get({ + url: '/crm/statistics-performance/get-contract-count-performance', + params + }) + } +} diff --git a/src/api/crm/statistics/portrait.ts b/src/api/crm/statistics/portrait.ts new file mode 100644 index 0000000..c7a2572 --- /dev/null +++ b/src/api/crm/statistics/portrait.ts @@ -0,0 +1,60 @@ +import request from '@/config/axios' + +export interface CrmStatisticCustomerBaseRespVO { + customerCount: number + dealCount: number + dealPortion: string | number +} + +export interface CrmStatisticCustomerIndustryRespVO extends CrmStatisticCustomerBaseRespVO { + industryId: number + industryPortion: string | number +} + +export interface CrmStatisticCustomerSourceRespVO extends CrmStatisticCustomerBaseRespVO { + source: number + sourcePortion: string | number +} + +export interface CrmStatisticCustomerLevelRespVO extends CrmStatisticCustomerBaseRespVO { + level: number + levelPortion: string | number +} + +export interface CrmStatisticCustomerAreaRespVO extends CrmStatisticCustomerBaseRespVO { + areaId: number + areaName: string + areaPortion: string | number +} + +// 客户分析 API +export const StatisticsPortraitApi = { + // 1. 获取客户行业统计数据 + getCustomerIndustry: (params: any) => { + return request.get({ + url: '/crm/statistics-portrait/get-customer-industry-summary', + params + }) + }, + // 2. 获取客户来源统计数据 + getCustomerSource: (params: any) => { + return request.get({ + url: '/crm/statistics-portrait/get-customer-source-summary', + params + }) + }, + // 3. 获取客户级别统计数据 + getCustomerLevel: (params: any) => { + return request.get({ + url: '/crm/statistics-portrait/get-customer-level-summary', + params + }) + }, + // 4. 获取客户地区统计数据 + getCustomerArea: (params: any) => { + return request.get({ + url: '/crm/statistics-portrait/get-customer-area-summary', + params + }) + } +} diff --git a/src/api/crm/statistics/rank.ts b/src/api/crm/statistics/rank.ts new file mode 100644 index 0000000..a9b355e --- /dev/null +++ b/src/api/crm/statistics/rank.ts @@ -0,0 +1,67 @@ +import request from '@/config/axios' + +export interface StatisticsRankRespVO { + count: number + nickname: string + deptName: string +} + +// 排行 API +export const StatisticsRankApi = { + // 获得合同排行榜 + getContractPriceRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-contract-price-rank', + params + }) + }, + // 获得回款排行榜 + getReceivablePriceRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-receivable-price-rank', + params + }) + }, + // 签约合同排行 + getContractCountRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-contract-count-rank', + params + }) + }, + // 产品销量排行 + getProductSalesRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-product-sales-rank', + params + }) + }, + // 新增客户数排行 + getCustomerCountRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-customer-count-rank', + params + }) + }, + // 新增联系人数排行 + getContactsCountRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-contacts-count-rank', + params + }) + }, + // 跟进次数排行 + getFollowCountRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-follow-count-rank', + params + }) + }, + // 跟进客户数排行 + getFollowCustomerCountRank: (params: any) => { + return request.get({ + url: '/crm/statistics-rank/get-follow-customer-count-rank', + params + }) + } +} diff --git a/src/api/erp/finance/account/index.ts b/src/api/erp/finance/account/index.ts new file mode 100644 index 0000000..a62b180 --- /dev/null +++ b/src/api/erp/finance/account/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +// ERP 结算账户 VO +export interface AccountVO { + id: number // 结算账户编号 + no: string // 账户编码 + remark: string // 备注 + status: number // 开启状态 + sort: number // 排序 + defaultStatus: boolean // 是否默认 + name: string // 账户名称 +} + +// ERP 结算账户 API +export const AccountApi = { + // 查询结算账户分页 + getAccountPage: async (params: any) => { + return await request.get({ url: `/erp/account/page`, params }) + }, + + // 查询结算账户精简列表 + getAccountSimpleList: async () => { + return await request.get({ url: `/erp/account/simple-list` }) + }, + + // 查询结算账户详情 + getAccount: async (id: number) => { + return await request.get({ url: `/erp/account/get?id=` + id }) + }, + + // 新增结算账户 + createAccount: async (data: AccountVO) => { + return await request.post({ url: `/erp/account/create`, data }) + }, + + // 修改结算账户 + updateAccount: async (data: AccountVO) => { + return await request.put({ url: `/erp/account/update`, data }) + }, + + // 修改结算账户默认状态 + updateAccountDefaultStatus: async (id: number, defaultStatus: boolean) => { + return await request.put({ + url: `/erp/account/update-default-status`, + params: { + id, + defaultStatus + } + }) + }, + + // 删除结算账户 + deleteAccount: async (id: number) => { + return await request.delete({ url: `/erp/account/delete?id=` + id }) + }, + + // 导出结算账户 Excel + exportAccount: async (params: any) => { + return await request.download({ url: `/erp/account/export-excel`, params }) + } +} diff --git a/src/api/erp/finance/payment/index.ts b/src/api/erp/finance/payment/index.ts new file mode 100644 index 0000000..c6749db --- /dev/null +++ b/src/api/erp/finance/payment/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +// ERP 付款单 VO +export interface FinancePaymentVO { + id: number // 付款单编号 + no: string // 付款单号 + supplierId: number // 供应商编号 + paymentTime: Date // 付款时间 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 付款单 API +export const FinancePaymentApi = { + // 查询付款单分页 + getFinancePaymentPage: async (params: any) => { + return await request.get({ url: `/erp/finance-payment/page`, params }) + }, + + // 查询付款单详情 + getFinancePayment: async (id: number) => { + return await request.get({ url: `/erp/finance-payment/get?id=` + id }) + }, + + // 新增付款单 + createFinancePayment: async (data: FinancePaymentVO) => { + return await request.post({ url: `/erp/finance-payment/create`, data }) + }, + + // 修改付款单 + updateFinancePayment: async (data: FinancePaymentVO) => { + return await request.put({ url: `/erp/finance-payment/update`, data }) + }, + + // 更新付款单的状态 + updateFinancePaymentStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/finance-payment/update-status`, + params: { + id, + status + } + }) + }, + + // 删除付款单 + deleteFinancePayment: async (ids: number[]) => { + return await request.delete({ + url: `/erp/finance-payment/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出付款单 Excel + exportFinancePayment: async (params: any) => { + return await request.download({ url: `/erp/finance-payment/export-excel`, params }) + } +} diff --git a/src/api/erp/finance/receipt/index.ts b/src/api/erp/finance/receipt/index.ts new file mode 100644 index 0000000..4de28ca --- /dev/null +++ b/src/api/erp/finance/receipt/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +// ERP 收款单 VO +export interface FinanceReceiptVO { + id: number // 收款单编号 + no: string // 收款单号 + customerId: number // 客户编号 + receiptTime: Date // 收款时间 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 收款单 API +export const FinanceReceiptApi = { + // 查询收款单分页 + getFinanceReceiptPage: async (params: any) => { + return await request.get({ url: `/erp/finance-receipt/page`, params }) + }, + + // 查询收款单详情 + getFinanceReceipt: async (id: number) => { + return await request.get({ url: `/erp/finance-receipt/get?id=` + id }) + }, + + // 新增收款单 + createFinanceReceipt: async (data: FinanceReceiptVO) => { + return await request.post({ url: `/erp/finance-receipt/create`, data }) + }, + + // 修改收款单 + updateFinanceReceipt: async (data: FinanceReceiptVO) => { + return await request.put({ url: `/erp/finance-receipt/update`, data }) + }, + + // 更新收款单的状态 + updateFinanceReceiptStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/finance-receipt/update-status`, + params: { + id, + status + } + }) + }, + + // 删除收款单 + deleteFinanceReceipt: async (ids: number[]) => { + return await request.delete({ + url: `/erp/finance-receipt/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出收款单 Excel + exportFinanceReceipt: async (params: any) => { + return await request.download({ url: `/erp/finance-receipt/export-excel`, params }) + } +} diff --git a/src/api/erp/product/category/index.ts b/src/api/erp/product/category/index.ts new file mode 100644 index 0000000..d67ccff --- /dev/null +++ b/src/api/erp/product/category/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +// ERP 产品分类 VO +export interface ProductCategoryVO { + id: number // 分类编号 + parentId: number // 父分类编号 + name: string // 分类名称 + code: string // 分类编码 + sort: number // 分类排序 + status: number // 开启状态 +} + +// ERP 产品分类 API +export const ProductCategoryApi = { + // 查询产品分类列表 + getProductCategoryList: async () => { + return await request.get({ url: `/erp/product-category/list` }) + }, + + // 查询产品分类精简列表 + getProductCategorySimpleList: async () => { + return await request.get({ url: `/erp/product-category/simple-list` }) + }, + + // 查询产品分类详情 + getProductCategory: async (id: number) => { + return await request.get({ url: `/erp/product-category/get?id=` + id }) + }, + + // 新增产品分类 + createProductCategory: async (data: ProductCategoryVO) => { + return await request.post({ url: `/erp/product-category/create`, data }) + }, + + // 修改产品分类 + updateProductCategory: async (data: ProductCategoryVO) => { + return await request.put({ url: `/erp/product-category/update`, data }) + }, + + // 删除产品分类 + deleteProductCategory: async (id: number) => { + return await request.delete({ url: `/erp/product-category/delete?id=` + id }) + }, + + // 导出产品分类 Excel + exportProductCategory: async (params) => { + return await request.download({ url: `/erp/product-category/export-excel`, params }) + } +} diff --git a/src/api/erp/product/product/index.ts b/src/api/erp/product/product/index.ts new file mode 100644 index 0000000..1136282 --- /dev/null +++ b/src/api/erp/product/product/index.ts @@ -0,0 +1,57 @@ +import request from '@/config/axios' + +// ERP 产品 VO +export interface ProductVO { + id: number // 产品编号 + name: string // 产品名称 + barCode: string // 产品条码 + categoryId: number // 产品类型编号 + unitId: number // 单位编号 + unitName?: string // 单位名字 + status: number // 产品状态 + standard: string // 产品规格 + remark: string // 产品备注 + expiryDay: number // 保质期天数 + weight: number // 重量(kg) + purchasePrice: number // 采购价格,单位:元 + salePrice: number // 销售价格,单位:元 + minPrice: number // 最低价格,单位:元 +} + +// ERP 产品 API +export const ProductApi = { + // 查询产品分页 + getProductPage: async (params: any) => { + return await request.get({ url: `/erp/product/page`, params }) + }, + + // 查询产品精简列表 + getProductSimpleList: async () => { + return await request.get({ url: `/erp/product/simple-list` }) + }, + + // 查询产品详情 + getProduct: async (id: number) => { + return await request.get({ url: `/erp/product/get?id=` + id }) + }, + + // 新增产品 + createProduct: async (data: ProductVO) => { + return await request.post({ url: `/erp/product/create`, data }) + }, + + // 修改产品 + updateProduct: async (data: ProductVO) => { + return await request.put({ url: `/erp/product/update`, data }) + }, + + // 删除产品 + deleteProduct: async (id: number) => { + return await request.delete({ url: `/erp/product/delete?id=` + id }) + }, + + // 导出产品 Excel + exportProduct: async (params) => { + return await request.download({ url: `/erp/product/export-excel`, params }) + } +} diff --git a/src/api/erp/product/unit/index.ts b/src/api/erp/product/unit/index.ts new file mode 100644 index 0000000..1e1c8ac --- /dev/null +++ b/src/api/erp/product/unit/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +// ERP 产品单位 VO +export interface ProductUnitVO { + id: number // 单位编号 + name: string // 单位名字 + status: number // 单位状态 +} + +// ERP 产品单位 API +export const ProductUnitApi = { + // 查询产品单位分页 + getProductUnitPage: async (params: any) => { + return await request.get({ url: `/erp/product-unit/page`, params }) + }, + + // 查询产品单位精简列表 + getProductUnitSimpleList: async () => { + return await request.get({ url: `/erp/product-unit/simple-list` }) + }, + + // 查询产品单位详情 + getProductUnit: async (id: number) => { + return await request.get({ url: `/erp/product-unit/get?id=` + id }) + }, + + // 新增产品单位 + createProductUnit: async (data: ProductUnitVO) => { + return await request.post({ url: `/erp/product-unit/create`, data }) + }, + + // 修改产品单位 + updateProductUnit: async (data: ProductUnitVO) => { + return await request.put({ url: `/erp/product-unit/update`, data }) + }, + + // 删除产品单位 + deleteProductUnit: async (id: number) => { + return await request.delete({ url: `/erp/product-unit/delete?id=` + id }) + }, + + // 导出产品单位 Excel + exportProductUnit: async (params) => { + return await request.download({ url: `/erp/product-unit/export-excel`, params }) + } +} diff --git a/src/api/erp/purchase/in/index.ts b/src/api/erp/purchase/in/index.ts new file mode 100644 index 0000000..f94708d --- /dev/null +++ b/src/api/erp/purchase/in/index.ts @@ -0,0 +1,64 @@ +import request from '@/config/axios' + +// ERP 采购入库 VO +export interface PurchaseInVO { + id: number // 入库工单编号 + no: string // 采购入库号 + customerId: number // 客户编号 + inTime: Date // 入库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 + outCount: number // 采购出库数量 + returnCount: number // 采购退货数量 +} + +// ERP 采购入库 API +export const PurchaseInApi = { + // 查询采购入库分页 + getPurchaseInPage: async (params: any) => { + return await request.get({ url: `/erp/purchase-in/page`, params }) + }, + + // 查询采购入库详情 + getPurchaseIn: async (id: number) => { + return await request.get({ url: `/erp/purchase-in/get?id=` + id }) + }, + + // 新增采购入库 + createPurchaseIn: async (data: PurchaseInVO) => { + return await request.post({ url: `/erp/purchase-in/create`, data }) + }, + + // 修改采购入库 + updatePurchaseIn: async (data: PurchaseInVO) => { + return await request.put({ url: `/erp/purchase-in/update`, data }) + }, + + // 更新采购入库的状态 + updatePurchaseInStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/purchase-in/update-status`, + params: { + id, + status + } + }) + }, + + // 删除采购入库 + deletePurchaseIn: async (ids: number[]) => { + return await request.delete({ + url: `/erp/purchase-in/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出采购入库 Excel + exportPurchaseIn: async (params: any) => { + return await request.download({ url: `/erp/purchase-in/export-excel`, params }) + } +} diff --git a/src/api/erp/purchase/order/index.ts b/src/api/erp/purchase/order/index.ts new file mode 100644 index 0000000..ad3222f --- /dev/null +++ b/src/api/erp/purchase/order/index.ts @@ -0,0 +1,64 @@ +import request from '@/config/axios' + +// ERP 采购订单 VO +export interface PurchaseOrderVO { + id: number // 订单工单编号 + no: string // 采购订单号 + customerId: number // 客户编号 + orderTime: Date // 订单时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 + outCount: number // 采购出库数量 + returnCount: number // 采购退货数量 +} + +// ERP 采购订单 API +export const PurchaseOrderApi = { + // 查询采购订单分页 + getPurchaseOrderPage: async (params: any) => { + return await request.get({ url: `/erp/purchase-order/page`, params }) + }, + + // 查询采购订单详情 + getPurchaseOrder: async (id: number) => { + return await request.get({ url: `/erp/purchase-order/get?id=` + id }) + }, + + // 新增采购订单 + createPurchaseOrder: async (data: PurchaseOrderVO) => { + return await request.post({ url: `/erp/purchase-order/create`, data }) + }, + + // 修改采购订单 + updatePurchaseOrder: async (data: PurchaseOrderVO) => { + return await request.put({ url: `/erp/purchase-order/update`, data }) + }, + + // 更新采购订单的状态 + updatePurchaseOrderStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/purchase-order/update-status`, + params: { + id, + status + } + }) + }, + + // 删除采购订单 + deletePurchaseOrder: async (ids: number[]) => { + return await request.delete({ + url: `/erp/purchase-order/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出采购订单 Excel + exportPurchaseOrder: async (params: any) => { + return await request.download({ url: `/erp/purchase-order/export-excel`, params }) + } +} diff --git a/src/api/erp/purchase/return/index.ts b/src/api/erp/purchase/return/index.ts new file mode 100644 index 0000000..182e04e --- /dev/null +++ b/src/api/erp/purchase/return/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// ERP 采购退货 VO +export interface PurchaseReturnVO { + id: number // 采购退货编号 + no: string // 采购退货号 + customerId: number // 客户编号 + returnTime: Date // 退货时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 采购退货 API +export const PurchaseReturnApi = { + // 查询采购退货分页 + getPurchaseReturnPage: async (params: any) => { + return await request.get({ url: `/erp/purchase-return/page`, params }) + }, + + // 查询采购退货详情 + getPurchaseReturn: async (id: number) => { + return await request.get({ url: `/erp/purchase-return/get?id=` + id }) + }, + + // 新增采购退货 + createPurchaseReturn: async (data: PurchaseReturnVO) => { + return await request.post({ url: `/erp/purchase-return/create`, data }) + }, + + // 修改采购退货 + updatePurchaseReturn: async (data: PurchaseReturnVO) => { + return await request.put({ url: `/erp/purchase-return/update`, data }) + }, + + // 更新采购退货的状态 + updatePurchaseReturnStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/purchase-return/update-status`, + params: { + id, + status + } + }) + }, + + // 删除采购退货 + deletePurchaseReturn: async (ids: number[]) => { + return await request.delete({ + url: `/erp/purchase-return/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出采购退货 Excel + exportPurchaseReturn: async (params: any) => { + return await request.download({ url: `/erp/purchase-return/export-excel`, params }) + } +} diff --git a/src/api/erp/purchase/supplier/index.ts b/src/api/erp/purchase/supplier/index.ts new file mode 100644 index 0000000..34729a5 --- /dev/null +++ b/src/api/erp/purchase/supplier/index.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' + +// ERP 供应商 VO +export interface SupplierVO { + id: number // 供应商编号 + name: string // 供应商名称 + contact: string // 联系人 + mobile: string // 手机号码 + telephone: string // 联系电话 + email: string // 电子邮箱 + fax: string // 传真 + remark: string // 备注 + status: number // 开启状态 + sort: number // 排序 + taxNo: string // 纳税人识别号 + taxPercent: number // 税率 + bankName: string // 开户行 + bankAccount: string // 开户账号 + bankAddress: string // 开户地址 +} + +// ERP 供应商 API +export const SupplierApi = { + // 查询供应商分页 + getSupplierPage: async (params: any) => { + return await request.get({ url: `/erp/supplier/page`, params }) + }, + + // 获得供应商精简列表 + getSupplierSimpleList: async () => { + return await request.get({ url: `/erp/supplier/simple-list` }) + }, + + // 查询供应商详情 + getSupplier: async (id: number) => { + return await request.get({ url: `/erp/supplier/get?id=` + id }) + }, + + // 新增供应商 + createSupplier: async (data: SupplierVO) => { + return await request.post({ url: `/erp/supplier/create`, data }) + }, + + // 修改供应商 + updateSupplier: async (data: SupplierVO) => { + return await request.put({ url: `/erp/supplier/update`, data }) + }, + + // 删除供应商 + deleteSupplier: async (id: number) => { + return await request.delete({ url: `/erp/supplier/delete?id=` + id }) + }, + + // 导出供应商 Excel + exportSupplier: async (params) => { + return await request.download({ url: `/erp/supplier/export-excel`, params }) + } +} diff --git a/src/api/erp/sale/customer/index.ts b/src/api/erp/sale/customer/index.ts new file mode 100644 index 0000000..3aaefb5 --- /dev/null +++ b/src/api/erp/sale/customer/index.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' + +// ERP 客户 VO +export interface CustomerVO { + id: number // 客户编号 + name: string // 客户名称 + contact: string // 联系人 + mobile: string // 手机号码 + telephone: string // 联系电话 + email: string // 电子邮箱 + fax: string // 传真 + remark: string // 备注 + status: number // 开启状态 + sort: number // 排序 + taxNo: string // 纳税人识别号 + taxPercent: number // 税率 + bankName: string // 开户行 + bankAccount: string // 开户账号 + bankAddress: string // 开户地址 +} + +// ERP 客户 API +export const CustomerApi = { + // 查询客户分页 + getCustomerPage: async (params: any) => { + return await request.get({ url: `/erp/customer/page`, params }) + }, + + // 查询客户精简列表 + getCustomerSimpleList: async () => { + return await request.get({ url: `/erp/customer/simple-list` }) + }, + + // 查询客户详情 + getCustomer: async (id: number) => { + return await request.get({ url: `/erp/customer/get?id=` + id }) + }, + + // 新增客户 + createCustomer: async (data: CustomerVO) => { + return await request.post({ url: `/erp/customer/create`, data }) + }, + + // 修改客户 + updateCustomer: async (data: CustomerVO) => { + return await request.put({ url: `/erp/customer/update`, data }) + }, + + // 删除客户 + deleteCustomer: async (id: number) => { + return await request.delete({ url: `/erp/customer/delete?id=` + id }) + }, + + // 导出客户 Excel + exportCustomer: async (params) => { + return await request.download({ url: `/erp/customer/export-excel`, params }) + } +} diff --git a/src/api/erp/sale/order/index.ts b/src/api/erp/sale/order/index.ts new file mode 100644 index 0000000..2d2ac53 --- /dev/null +++ b/src/api/erp/sale/order/index.ts @@ -0,0 +1,64 @@ +import request from '@/config/axios' + +// ERP 销售订单 VO +export interface SaleOrderVO { + id: number // 订单工单编号 + no: string // 销售订单号 + customerId: number // 客户编号 + orderTime: Date // 订单时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 + outCount: number // 销售出库数量 + returnCount: number // 销售退货数量 +} + +// ERP 销售订单 API +export const SaleOrderApi = { + // 查询销售订单分页 + getSaleOrderPage: async (params: any) => { + return await request.get({ url: `/erp/sale-order/page`, params }) + }, + + // 查询销售订单详情 + getSaleOrder: async (id: number) => { + return await request.get({ url: `/erp/sale-order/get?id=` + id }) + }, + + // 新增销售订单 + createSaleOrder: async (data: SaleOrderVO) => { + return await request.post({ url: `/erp/sale-order/create`, data }) + }, + + // 修改销售订单 + updateSaleOrder: async (data: SaleOrderVO) => { + return await request.put({ url: `/erp/sale-order/update`, data }) + }, + + // 更新销售订单的状态 + updateSaleOrderStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/sale-order/update-status`, + params: { + id, + status + } + }) + }, + + // 删除销售订单 + deleteSaleOrder: async (ids: number[]) => { + return await request.delete({ + url: `/erp/sale-order/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出销售订单 Excel + exportSaleOrder: async (params: any) => { + return await request.download({ url: `/erp/sale-order/export-excel`, params }) + } +} diff --git a/src/api/erp/sale/out/index.ts b/src/api/erp/sale/out/index.ts new file mode 100644 index 0000000..cbc605e --- /dev/null +++ b/src/api/erp/sale/out/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// ERP 销售出库 VO +export interface SaleOutVO { + id: number // 销售出库编号 + no: string // 销售出库号 + customerId: number // 客户编号 + outTime: Date // 出库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 销售出库 API +export const SaleOutApi = { + // 查询销售出库分页 + getSaleOutPage: async (params: any) => { + return await request.get({ url: `/erp/sale-out/page`, params }) + }, + + // 查询销售出库详情 + getSaleOut: async (id: number) => { + return await request.get({ url: `/erp/sale-out/get?id=` + id }) + }, + + // 新增销售出库 + createSaleOut: async (data: SaleOutVO) => { + return await request.post({ url: `/erp/sale-out/create`, data }) + }, + + // 修改销售出库 + updateSaleOut: async (data: SaleOutVO) => { + return await request.put({ url: `/erp/sale-out/update`, data }) + }, + + // 更新销售出库的状态 + updateSaleOutStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/sale-out/update-status`, + params: { + id, + status + } + }) + }, + + // 删除销售出库 + deleteSaleOut: async (ids: number[]) => { + return await request.delete({ + url: `/erp/sale-out/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出销售出库 Excel + exportSaleOut: async (params: any) => { + return await request.download({ url: `/erp/sale-out/export-excel`, params }) + } +} diff --git a/src/api/erp/sale/return/index.ts b/src/api/erp/sale/return/index.ts new file mode 100644 index 0000000..160ac01 --- /dev/null +++ b/src/api/erp/sale/return/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// ERP 销售退货 VO +export interface SaleReturnVO { + id: number // 销售退货编号 + no: string // 销售退货号 + customerId: number // 客户编号 + returnTime: Date // 退货时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 销售退货 API +export const SaleReturnApi = { + // 查询销售退货分页 + getSaleReturnPage: async (params: any) => { + return await request.get({ url: `/erp/sale-return/page`, params }) + }, + + // 查询销售退货详情 + getSaleReturn: async (id: number) => { + return await request.get({ url: `/erp/sale-return/get?id=` + id }) + }, + + // 新增销售退货 + createSaleReturn: async (data: SaleReturnVO) => { + return await request.post({ url: `/erp/sale-return/create`, data }) + }, + + // 修改销售退货 + updateSaleReturn: async (data: SaleReturnVO) => { + return await request.put({ url: `/erp/sale-return/update`, data }) + }, + + // 更新销售退货的状态 + updateSaleReturnStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/sale-return/update-status`, + params: { + id, + status + } + }) + }, + + // 删除销售退货 + deleteSaleReturn: async (ids: number[]) => { + return await request.delete({ + url: `/erp/sale-return/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出销售退货 Excel + exportSaleReturn: async (params: any) => { + return await request.download({ url: `/erp/sale-return/export-excel`, params }) + } +} diff --git a/src/api/erp/statistics/purchase/index.ts b/src/api/erp/statistics/purchase/index.ts new file mode 100644 index 0000000..80d907a --- /dev/null +++ b/src/api/erp/statistics/purchase/index.ts @@ -0,0 +1,28 @@ +import request from '@/config/axios' + +// ERP 采购全局统计 VO +export interface ErpPurchaseSummaryRespVO { + todayPrice: number // 今日采购金额 + yesterdayPrice: number // 昨日采购金额 + monthPrice: number // 本月采购金额 + yearPrice: number // 今年采购金额 +} + +// ERP 采购时间段统计 VO +export interface ErpPurchaseTimeSummaryRespVO { + time: string // 时间 + price: number // 采购金额 +} + +// ERP 采购统计 API +export const PurchaseStatisticsApi = { + // 获得采购统计 + getPurchaseSummary: async (): Promise => { + return await request.get({ url: `/erp/purchase-statistics/summary` }) + }, + + // 获得采购时间段统计 + getPurchaseTimeSummary: async (): Promise => { + return await request.get({ url: `/erp/purchase-statistics/time-summary` }) + } +} diff --git a/src/api/erp/statistics/sale/index.ts b/src/api/erp/statistics/sale/index.ts new file mode 100644 index 0000000..09d8500 --- /dev/null +++ b/src/api/erp/statistics/sale/index.ts @@ -0,0 +1,28 @@ +import request from '@/config/axios' + +// ERP 销售全局统计 VO +export interface ErpSaleSummaryRespVO { + todayPrice: number // 今日销售金额 + yesterdayPrice: number // 昨日销售金额 + monthPrice: number // 本月销售金额 + yearPrice: number // 今年销售金额 +} + +// ERP 销售时间段统计 VO +export interface ErpSaleTimeSummaryRespVO { + time: string // 时间 + price: number // 销售金额 +} + +// ERP 销售统计 API +export const SaleStatisticsApi = { + // 获得销售统计 + getSaleSummary: async (): Promise => { + return await request.get({ url: `/erp/sale-statistics/summary` }) + }, + + // 获得销售时间段统计 + getSaleTimeSummary: async (): Promise => { + return await request.get({ url: `/erp/sale-statistics/time-summary` }) + } +} diff --git a/src/api/erp/stock/check/index.ts b/src/api/erp/stock/check/index.ts new file mode 100644 index 0000000..4a3e653 --- /dev/null +++ b/src/api/erp/stock/check/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +// ERP 库存盘点单 VO +export interface StockCheckVO { + id: number // 出库编号 + no: string // 出库单号 + outTime: Date // 出库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 库存盘点单 API +export const StockCheckApi = { + // 查询库存盘点单分页 + getStockCheckPage: async (params: any) => { + return await request.get({ url: `/erp/stock-check/page`, params }) + }, + + // 查询库存盘点单详情 + getStockCheck: async (id: number) => { + return await request.get({ url: `/erp/stock-check/get?id=` + id }) + }, + + // 新增库存盘点单 + createStockCheck: async (data: StockCheckVO) => { + return await request.post({ url: `/erp/stock-check/create`, data }) + }, + + // 修改库存盘点单 + updateStockCheck: async (data: StockCheckVO) => { + return await request.put({ url: `/erp/stock-check/update`, data }) + }, + + // 更新库存盘点单的状态 + updateStockCheckStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/stock-check/update-status`, + params: { + id, + status + } + }) + }, + + // 删除库存盘点单 + deleteStockCheck: async (ids: number[]) => { + return await request.delete({ + url: `/erp/stock-check/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出库存盘点单 Excel + exportStockCheck: async (params) => { + return await request.download({ url: `/erp/stock-check/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/in/index.ts b/src/api/erp/stock/in/index.ts new file mode 100644 index 0000000..148b64f --- /dev/null +++ b/src/api/erp/stock/in/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// ERP 其它入库单 VO +export interface StockInVO { + id: number // 入库编号 + no: string // 入库单号 + supplierId: number // 供应商编号 + inTime: Date // 入库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 其它入库单 API +export const StockInApi = { + // 查询其它入库单分页 + getStockInPage: async (params: any) => { + return await request.get({ url: `/erp/stock-in/page`, params }) + }, + + // 查询其它入库单详情 + getStockIn: async (id: number) => { + return await request.get({ url: `/erp/stock-in/get?id=` + id }) + }, + + // 新增其它入库单 + createStockIn: async (data: StockInVO) => { + return await request.post({ url: `/erp/stock-in/create`, data }) + }, + + // 修改其它入库单 + updateStockIn: async (data: StockInVO) => { + return await request.put({ url: `/erp/stock-in/update`, data }) + }, + + // 更新其它入库单的状态 + updateStockInStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/stock-in/update-status`, + params: { + id, + status + } + }) + }, + + // 删除其它入库单 + deleteStockIn: async (ids: number[]) => { + return await request.delete({ + url: `/erp/stock-in/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出其它入库单 Excel + exportStockIn: async (params) => { + return await request.download({ url: `/erp/stock-in/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/move/index.ts b/src/api/erp/stock/move/index.ts new file mode 100644 index 0000000..398568e --- /dev/null +++ b/src/api/erp/stock/move/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +// ERP 库存调度单 VO +export interface StockMoveVO { + id: number // 出库编号 + no: string // 出库单号 + outTime: Date // 出库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 库存调度单 API +export const StockMoveApi = { + // 查询库存调度单分页 + getStockMovePage: async (params: any) => { + return await request.get({ url: `/erp/stock-move/page`, params }) + }, + + // 查询库存调度单详情 + getStockMove: async (id: number) => { + return await request.get({ url: `/erp/stock-move/get?id=` + id }) + }, + + // 新增库存调度单 + createStockMove: async (data: StockMoveVO) => { + return await request.post({ url: `/erp/stock-move/create`, data }) + }, + + // 修改库存调度单 + updateStockMove: async (data: StockMoveVO) => { + return await request.put({ url: `/erp/stock-move/update`, data }) + }, + + // 更新库存调度单的状态 + updateStockMoveStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/stock-move/update-status`, + params: { + id, + status + } + }) + }, + + // 删除库存调度单 + deleteStockMove: async (ids: number[]) => { + return await request.delete({ + url: `/erp/stock-move/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出库存调度单 Excel + exportStockMove: async (params) => { + return await request.download({ url: `/erp/stock-move/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/out/index.ts b/src/api/erp/stock/out/index.ts new file mode 100644 index 0000000..f0f40d3 --- /dev/null +++ b/src/api/erp/stock/out/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// ERP 其它出库单 VO +export interface StockOutVO { + id: number // 出库编号 + no: string // 出库单号 + customerId: number // 客户编号 + outTime: Date // 出库时间 + totalCount: number // 合计数量 + totalPrice: number // 合计金额,单位:元 + status: number // 状态 + remark: string // 备注 +} + +// ERP 其它出库单 API +export const StockOutApi = { + // 查询其它出库单分页 + getStockOutPage: async (params: any) => { + return await request.get({ url: `/erp/stock-out/page`, params }) + }, + + // 查询其它出库单详情 + getStockOut: async (id: number) => { + return await request.get({ url: `/erp/stock-out/get?id=` + id }) + }, + + // 新增其它出库单 + createStockOut: async (data: StockOutVO) => { + return await request.post({ url: `/erp/stock-out/create`, data }) + }, + + // 修改其它出库单 + updateStockOut: async (data: StockOutVO) => { + return await request.put({ url: `/erp/stock-out/update`, data }) + }, + + // 更新其它出库单的状态 + updateStockOutStatus: async (id: number, status: number) => { + return await request.put({ + url: `/erp/stock-out/update-status`, + params: { + id, + status + } + }) + }, + + // 删除其它出库单 + deleteStockOut: async (ids: number[]) => { + return await request.delete({ + url: `/erp/stock-out/delete`, + params: { + ids: ids.join(',') + } + }) + }, + + // 导出其它出库单 Excel + exportStockOut: async (params) => { + return await request.download({ url: `/erp/stock-out/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/record/index.ts b/src/api/erp/stock/record/index.ts new file mode 100644 index 0000000..a758eb4 --- /dev/null +++ b/src/api/erp/stock/record/index.ts @@ -0,0 +1,32 @@ +import request from '@/config/axios' + +// ERP 产品库存明细 VO +export interface StockRecordVO { + id: number // 编号 + productId: number // 产品编号 + warehouseId: number // 仓库编号 + count: number // 出入库数量 + totalCount: number // 总库存量 + bizType: number // 业务类型 + bizId: number // 业务编号 + bizItemId: number // 业务项编号 + bizNo: string // 业务单号 +} + +// ERP 产品库存明细 API +export const StockRecordApi = { + // 查询产品库存明细分页 + getStockRecordPage: async (params: any) => { + return await request.get({ url: `/erp/stock-record/page`, params }) + }, + + // 查询产品库存明细详情 + getStockRecord: async (id: number) => { + return await request.get({ url: `/erp/stock-record/get?id=` + id }) + }, + + // 导出产品库存明细 Excel + exportStockRecord: async (params) => { + return await request.download({ url: `/erp/stock-record/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/stock/index.ts b/src/api/erp/stock/stock/index.ts new file mode 100644 index 0000000..4de86fb --- /dev/null +++ b/src/api/erp/stock/stock/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// ERP 产品库存 VO +export interface StockVO { + // 编号 + id: number + // 产品编号 + productId: number + // 仓库编号 + warehouseId: number + // 库存数量 + count: number +} + +// ERP 产品库存 API +export const StockApi = { + // 查询产品库存分页 + getStockPage: async (params: any) => { + return await request.get({ url: `/erp/stock/page`, params }) + }, + + // 查询产品库存详情 + getStock: async (id: number) => { + return await request.get({ url: `/erp/stock/get?id=` + id }) + }, + + // 查询产品库存详情 + getStock2: async (productId: number, warehouseId: number) => { + return await request.get({ url: `/erp/stock/get`, params: { productId, warehouseId } }) + }, + + // 获得产品库存数量 + getStockCount: async (productId: number) => { + return await request.get({ url: `/erp/stock/get-count`, params: { productId } }) + }, + + // 导出产品库存 Excel + exportStock: async (params) => { + return await request.download({ url: `/erp/stock/export-excel`, params }) + } +} diff --git a/src/api/erp/stock/warehouse/index.ts b/src/api/erp/stock/warehouse/index.ts new file mode 100644 index 0000000..598824b --- /dev/null +++ b/src/api/erp/stock/warehouse/index.ts @@ -0,0 +1,64 @@ +import request from '@/config/axios' + +// ERP 仓库 VO +export interface WarehouseVO { + id: number // 仓库编号 + name: string // 仓库名称 + address: string // 仓库地址 + sort: number // 排序 + remark: string // 备注 + principal: string // 负责人 + warehousePrice: number // 仓储费,单位:元 + truckagePrice: number // 搬运费,单位:元 + status: number // 开启状态 + defaultStatus: boolean // 是否默认 +} + +// ERP 仓库 API +export const WarehouseApi = { + // 查询仓库分页 + getWarehousePage: async (params: any) => { + return await request.get({ url: `/erp/warehouse/page`, params }) + }, + + // 查询仓库精简列表 + getWarehouseSimpleList: async () => { + return await request.get({ url: `/erp/warehouse/simple-list` }) + }, + + // 查询仓库详情 + getWarehouse: async (id: number) => { + return await request.get({ url: `/erp/warehouse/get?id=` + id }) + }, + + // 新增仓库 + createWarehouse: async (data: WarehouseVO) => { + return await request.post({ url: `/erp/warehouse/create`, data }) + }, + + // 修改仓库 + updateWarehouse: async (data: WarehouseVO) => { + return await request.put({ url: `/erp/warehouse/update`, data }) + }, + + // 修改仓库默认状态 + updateWarehouseDefaultStatus: async (id: number, defaultStatus: boolean) => { + return await request.put({ + url: `/erp/warehouse/update-default-status`, + params: { + id, + defaultStatus + } + }) + }, + + // 删除仓库 + deleteWarehouse: async (id: number) => { + return await request.delete({ url: `/erp/warehouse/delete?id=` + id }) + }, + + // 导出仓库 Excel + exportWarehouse: async (params) => { + return await request.download({ url: `/erp/warehouse/export-excel`, params }) + } +} diff --git a/src/api/infra/apiAccessLog/index.ts b/src/api/infra/apiAccessLog/index.ts new file mode 100644 index 0000000..4fa50e1 --- /dev/null +++ b/src/api/infra/apiAccessLog/index.ts @@ -0,0 +1,34 @@ +import request from '@/config/axios' + +export interface ApiAccessLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + responseBody: string + requestUrl: string + userIp: string + userAgent: string + operateModule: string + operateName: string + operateType: number + beginTime: Date + endTime: Date + duration: number + resultCode: number + resultMsg: string + createTime: Date +} + +// 查询列表API 访问日志 +export const getApiAccessLogPage = (params: PageParam) => { + return request.get({ url: '/infra/api-access-log/page', params }) +} + +// 导出API 访问日志 +export const exportApiAccessLog = (params) => { + return request.download({ url: '/infra/api-access-log/export-excel', params }) +} diff --git a/src/api/infra/apiErrorLog/index.ts b/src/api/infra/apiErrorLog/index.ts new file mode 100644 index 0000000..59ee214 --- /dev/null +++ b/src/api/infra/apiErrorLog/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +export interface ApiErrorLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + requestUrl: string + userIp: string + userAgent: string + exceptionTime: Date + exceptionName: string + exceptionMessage: string + exceptionRootCauseMessage: string + exceptionStackTrace: string + exceptionClassName: string + exceptionFileName: string + exceptionMethodName: string + exceptionLineNumber: number + processUserId: number + processStatus: number + processTime: Date + resultCode: number + createTime: Date +} + +// 查询列表API 访问日志 +export const getApiErrorLogPage = (params: PageParam) => { + return request.get({ url: '/infra/api-error-log/page', params }) +} + +// 更新 API 错误日志的处理状态 +export const updateApiErrorLogPage = (id: number, processStatus: number) => { + return request.put({ + url: '/infra/api-error-log/update-status?id=' + id + '&processStatus=' + processStatus + }) +} + +// 导出API 访问日志 +export const exportApiErrorLog = (params) => { + return request.download({ + url: '/infra/api-error-log/export-excel', + params + }) +} diff --git a/src/api/infra/codegen/index.ts b/src/api/infra/codegen/index.ts new file mode 100644 index 0000000..441ca83 --- /dev/null +++ b/src/api/infra/codegen/index.ts @@ -0,0 +1,122 @@ +import request from '@/config/axios' + +export type CodegenTableVO = { + id: number + tableId: number + isParentMenuIdValid: boolean + dataSourceConfigId: number + scene: number + tableName: string + tableComment: string + remark: string + moduleName: string + businessName: string + className: string + classComment: string + author: string + createTime: Date + updateTime: Date + templateType: number + parentMenuId: number +} + +export type CodegenColumnVO = { + id: number + tableId: number + columnName: string + dataType: string + columnComment: string + nullable: number + primaryKey: number + ordinalPosition: number + javaType: string + javaField: string + dictType: string + example: string + createOperation: number + updateOperation: number + listOperation: number + listOperationCondition: string + listOperationResult: number + htmlType: string +} + +export type DatabaseTableVO = { + name: string + comment: string +} + +export type CodegenDetailVO = { + table: CodegenTableVO + columns: CodegenColumnVO[] +} + +export type CodegenPreviewVO = { + filePath: string + code: string +} + +export type CodegenUpdateReqVO = { + table: CodegenTableVO | any + columns: CodegenColumnVO[] +} + +export type CodegenCreateListReqVO = { + dataSourceConfigId: number + tableNames: string[] +} + +// 查询列表代码生成表定义 +export const getCodegenTableList = (dataSourceConfigId: number) => { + return request.get({ url: '/infra/codegen/table/list?dataSourceConfigId=' + dataSourceConfigId }) +} + +// 查询列表代码生成表定义 +export const getCodegenTablePage = (params: PageParam) => { + return request.get({ url: '/infra/codegen/table/page', params }) +} + +// 查询详情代码生成表定义 +export const getCodegenTable = (id: number) => { + return request.get({ url: '/infra/codegen/detail?tableId=' + id }) +} + +// 新增代码生成表定义 +export const createCodegenTable = (data: CodegenCreateListReqVO) => { + return request.post({ url: '/infra/codegen/create', data }) +} + +// 修改代码生成表定义 +export const updateCodegenTable = (data: CodegenUpdateReqVO) => { + return request.put({ url: '/infra/codegen/update', data }) +} + +// 基于数据库的表结构,同步数据库的表和字段定义 +export const syncCodegenFromDB = (id: number) => { + return request.put({ url: '/infra/codegen/sync-from-db?tableId=' + id }) +} + +// 预览生成代码 +export const previewCodegen = (id: number) => { + return request.get({ url: '/infra/codegen/preview?tableId=' + id }) +} + +// 下载生成代码 +export const downloadCodegen = (id: number) => { + return request.download({ url: '/infra/codegen/download?tableId=' + id }) +} + +// 获得表定义 +export const getSchemaTableList = (params) => { + return request.get({ url: '/infra/codegen/db/table/list', params }) +} + +// 基于数据库的表结构,创建代码生成器的表定义 +export const createCodegenList = (data) => { + return request.post({ url: '/infra/codegen/create-list', data }) +} + +// 删除代码生成表定义 +export const deleteCodegenTable = (id: number) => { + return request.delete({ url: '/infra/codegen/delete?tableId=' + id }) +} diff --git a/src/api/infra/config/index.ts b/src/api/infra/config/index.ts new file mode 100644 index 0000000..5ef59f3 --- /dev/null +++ b/src/api/infra/config/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +export interface ConfigVO { + id: number | undefined + category: string + name: string + key: string + value: string + type: number + visible: boolean + remark: string + createTime: Date +} + +// 查询参数列表 +export const getConfigPage = (params: PageParam) => { + return request.get({ url: '/infra/config/page', params }) +} + +// 查询参数详情 +export const getConfig = (id: number) => { + return request.get({ url: '/infra/config/get?id=' + id }) +} + +// 根据参数键名查询参数值 +export const getConfigKey = (configKey: string) => { + return request.get({ url: '/infra/config/get-value-by-key?key=' + configKey }) +} + +// 新增参数 +export const createConfig = (data: ConfigVO) => { + return request.post({ url: '/infra/config/create', data }) +} + +// 修改参数 +export const updateConfig = (data: ConfigVO) => { + return request.put({ url: '/infra/config/update', data }) +} + +// 删除参数 +export const deleteConfig = (id: number) => { + return request.delete({ url: '/infra/config/delete?id=' + id }) +} + +// 导出参数 +export const exportConfig = (params) => { + return request.download({ url: '/infra/config/export', params }) +} diff --git a/src/api/infra/dataSourceConfig/index.ts b/src/api/infra/dataSourceConfig/index.ts new file mode 100644 index 0000000..b413f34 --- /dev/null +++ b/src/api/infra/dataSourceConfig/index.ts @@ -0,0 +1,35 @@ +import request from '@/config/axios' + +export interface DataSourceConfigVO { + id: number | undefined + name: string + url: string + username: string + password: string + createTime?: Date +} + +// 新增数据源配置 +export const createDataSourceConfig = (data: DataSourceConfigVO) => { + return request.post({ url: '/infra/data-source-config/create', data }) +} + +// 修改数据源配置 +export const updateDataSourceConfig = (data: DataSourceConfigVO) => { + return request.put({ url: '/infra/data-source-config/update', data }) +} + +// 删除数据源配置 +export const deleteDataSourceConfig = (id: number) => { + return request.delete({ url: '/infra/data-source-config/delete?id=' + id }) +} + +// 查询数据源配置详情 +export const getDataSourceConfig = (id: number) => { + return request.get({ url: '/infra/data-source-config/get?id=' + id }) +} + +// 查询数据源配置列表 +export const getDataSourceConfigList = () => { + return request.get({ url: '/infra/data-source-config/list' }) +} diff --git a/src/api/infra/demo/demo01/index.ts b/src/api/infra/demo/demo01/index.ts new file mode 100644 index 0000000..e34a05d --- /dev/null +++ b/src/api/infra/demo/demo01/index.ts @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +export interface Demo01ContactVO { + id: number + name: string + sex: number + birthday: Date + description: string + avatar: string +} + +// 查询示例联系人分页 +export const getDemo01ContactPage = async (params) => { + return await request.get({ url: `/infra/demo01-contact/page`, params }) +} + +// 查询示例联系人详情 +export const getDemo01Contact = async (id: number) => { + return await request.get({ url: `/infra/demo01-contact/get?id=` + id }) +} + +// 新增示例联系人 +export const createDemo01Contact = async (data: Demo01ContactVO) => { + return await request.post({ url: `/infra/demo01-contact/create`, data }) +} + +// 修改示例联系人 +export const updateDemo01Contact = async (data: Demo01ContactVO) => { + return await request.put({ url: `/infra/demo01-contact/update`, data }) +} + +// 删除示例联系人 +export const deleteDemo01Contact = async (id: number) => { + return await request.delete({ url: `/infra/demo01-contact/delete?id=` + id }) +} + +// 导出示例联系人 Excel +export const exportDemo01Contact = async (params) => { + return await request.download({ url: `/infra/demo01-contact/export-excel`, params }) +} diff --git a/src/api/infra/demo/demo02/index.ts b/src/api/infra/demo/demo02/index.ts new file mode 100644 index 0000000..736a123 --- /dev/null +++ b/src/api/infra/demo/demo02/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface Demo02CategoryVO { + id: number + name: string + parentId: number +} + +// 查询示例分类列表 +export const getDemo02CategoryList = async () => { + return await request.get({ url: `/infra/demo02-category/list` }) +} + +// 查询示例分类详情 +export const getDemo02Category = async (id: number) => { + return await request.get({ url: `/infra/demo02-category/get?id=` + id }) +} + +// 新增示例分类 +export const createDemo02Category = async (data: Demo02CategoryVO) => { + return await request.post({ url: `/infra/demo02-category/create`, data }) +} + +// 修改示例分类 +export const updateDemo02Category = async (data: Demo02CategoryVO) => { + return await request.put({ url: `/infra/demo02-category/update`, data }) +} + +// 删除示例分类 +export const deleteDemo02Category = async (id: number) => { + return await request.delete({ url: `/infra/demo02-category/delete?id=` + id }) +} + +// 导出示例分类 Excel +export const exportDemo02Category = async (params) => { + return await request.download({ url: `/infra/demo02-category/export-excel`, params }) +} diff --git a/src/api/infra/demo/demo03/erp/index.ts b/src/api/infra/demo/demo03/erp/index.ts new file mode 100644 index 0000000..a2ab539 --- /dev/null +++ b/src/api/infra/demo/demo03/erp/index.ts @@ -0,0 +1,91 @@ +import request from '@/config/axios' + +export interface Demo03StudentVO { + id: number + name: string + sex: number + birthday: Date + description: string +} + +// 查询学生分页 +export const getDemo03StudentPage = async (params) => { + return await request.get({ url: `/infra/demo03-student/page`, params }) +} + +// 查询学生详情 +export const getDemo03Student = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/get?id=` + id }) +} + +// 新增学生 +export const createDemo03Student = async (data: Demo03StudentVO) => { + return await request.post({ url: `/infra/demo03-student/create`, data }) +} + +// 修改学生 +export const updateDemo03Student = async (data: Demo03StudentVO) => { + return await request.put({ url: `/infra/demo03-student/update`, data }) +} + +// 删除学生 +export const deleteDemo03Student = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportDemo03Student = async (params) => { + return await request.download({ url: `/infra/demo03-student/export-excel`, params }) +} + +// ==================== 子表(学生课程) ==================== + +// 获得学生课程分页 +export const getDemo03CoursePage = async (params) => { + return await request.get({ url: `/infra/demo03-student/demo03-course/page`, params }) +} +// 新增学生课程 +export const createDemo03Course = async (data) => { + return await request.post({ url: `/infra/demo03-student/demo03-course/create`, data }) +} + +// 修改学生课程 +export const updateDemo03Course = async (data) => { + return await request.put({ url: `/infra/demo03-student/demo03-course/update`, data }) +} + +// 删除学生课程 +export const deleteDemo03Course = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/demo03-course/delete?id=` + id }) +} + +// 获得学生课程 +export const getDemo03Course = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/demo03-course/get?id=` + id }) +} + +// ==================== 子表(学生班级) ==================== + +// 获得学生班级分页 +export const getDemo03GradePage = async (params) => { + return await request.get({ url: `/infra/demo03-student/demo03-grade/page`, params }) +} +// 新增学生班级 +export const createDemo03Grade = async (data) => { + return await request.post({ url: `/infra/demo03-student/demo03-grade/create`, data }) +} + +// 修改学生班级 +export const updateDemo03Grade = async (data) => { + return await request.put({ url: `/infra/demo03-student/demo03-grade/update`, data }) +} + +// 删除学生班级 +export const deleteDemo03Grade = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/demo03-grade/delete?id=` + id }) +} + +// 获得学生班级 +export const getDemo03Grade = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/demo03-grade/get?id=` + id }) +} diff --git a/src/api/infra/demo/demo03/inner/index.ts b/src/api/infra/demo/demo03/inner/index.ts new file mode 100644 index 0000000..e366307 --- /dev/null +++ b/src/api/infra/demo/demo03/inner/index.ts @@ -0,0 +1,57 @@ +import request from '@/config/axios' + +export interface Demo03StudentVO { + id: number + name: string + sex: number + birthday: Date + description: string +} + +// 查询学生分页 +export const getDemo03StudentPage = async (params) => { + return await request.get({ url: `/infra/demo03-student/page`, params }) +} + +// 查询学生详情 +export const getDemo03Student = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/get?id=` + id }) +} + +// 新增学生 +export const createDemo03Student = async (data: Demo03StudentVO) => { + return await request.post({ url: `/infra/demo03-student/create`, data }) +} + +// 修改学生 +export const updateDemo03Student = async (data: Demo03StudentVO) => { + return await request.put({ url: `/infra/demo03-student/update`, data }) +} + +// 删除学生 +export const deleteDemo03Student = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportDemo03Student = async (params) => { + return await request.download({ url: `/infra/demo03-student/export-excel`, params }) +} + +// ==================== 子表(学生课程) ==================== + +// 获得学生课程列表 +export const getDemo03CourseListByStudentId = async (studentId) => { + return await request.get({ + url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId + }) +} + +// ==================== 子表(学生班级) ==================== + +// 获得学生班级 +export const getDemo03GradeByStudentId = async (studentId) => { + return await request.get({ + url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId + }) +} diff --git a/src/api/infra/demo/demo03/normal/index.ts b/src/api/infra/demo/demo03/normal/index.ts new file mode 100644 index 0000000..e366307 --- /dev/null +++ b/src/api/infra/demo/demo03/normal/index.ts @@ -0,0 +1,57 @@ +import request from '@/config/axios' + +export interface Demo03StudentVO { + id: number + name: string + sex: number + birthday: Date + description: string +} + +// 查询学生分页 +export const getDemo03StudentPage = async (params) => { + return await request.get({ url: `/infra/demo03-student/page`, params }) +} + +// 查询学生详情 +export const getDemo03Student = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/get?id=` + id }) +} + +// 新增学生 +export const createDemo03Student = async (data: Demo03StudentVO) => { + return await request.post({ url: `/infra/demo03-student/create`, data }) +} + +// 修改学生 +export const updateDemo03Student = async (data: Demo03StudentVO) => { + return await request.put({ url: `/infra/demo03-student/update`, data }) +} + +// 删除学生 +export const deleteDemo03Student = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportDemo03Student = async (params) => { + return await request.download({ url: `/infra/demo03-student/export-excel`, params }) +} + +// ==================== 子表(学生课程) ==================== + +// 获得学生课程列表 +export const getDemo03CourseListByStudentId = async (studentId) => { + return await request.get({ + url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId + }) +} + +// ==================== 子表(学生班级) ==================== + +// 获得学生班级 +export const getDemo03GradeByStudentId = async (studentId) => { + return await request.get({ + url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId + }) +} diff --git a/src/api/infra/file/index.ts b/src/api/infra/file/index.ts new file mode 100644 index 0000000..0e1b2e7 --- /dev/null +++ b/src/api/infra/file/index.ts @@ -0,0 +1,45 @@ +import request from '@/config/axios' + +export interface FilePageReqVO extends PageParam { + path?: string + type?: string + createTime?: Date[] +} + +// 文件预签名地址 Response VO +export interface FilePresignedUrlRespVO { + // 文件配置编号 + configId: number + // 文件上传 URL + uploadUrl: string + // 文件 URL + url: string +} + +// 查询文件列表 +export const getFilePage = (params: FilePageReqVO) => { + return request.get({ url: '/infra/file/page', params }) +} + +// 删除文件 +export const deleteFile = (id: number) => { + return request.delete({ url: '/infra/file/delete?id=' + id }) +} + +// 获取文件预签名地址 +export const getFilePresignedUrl = (path: string) => { + return request.get({ + url: '/infra/file/presigned-url', + params: { path } + }) +} + +// 创建文件 +export const createFile = (data: any) => { + return request.post({ url: '/infra/file/create', data }) +} + +// 上传文件 +export const updateFile = (data: any) => { + return request.upload({ url: '/infra/file/upload', data }) +} diff --git a/src/api/infra/fileConfig/index.ts b/src/api/infra/fileConfig/index.ts new file mode 100644 index 0000000..ba40054 --- /dev/null +++ b/src/api/infra/fileConfig/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +export interface FileClientConfig { + basePath: string + host?: string + port?: number + username?: string + password?: string + mode?: string + endpoint?: string + bucket?: string + accessKey?: string + accessSecret?: string + domain: string +} + +export interface FileConfigVO { + id: number + name: string + storage?: number + master: boolean + visible: boolean + config: FileClientConfig + remark: string + createTime: Date +} + +// 查询文件配置列表 +export const getFileConfigPage = (params: PageParam) => { + return request.get({ url: '/infra/file-config/page', params }) +} + +// 查询文件配置详情 +export const getFileConfig = (id: number) => { + return request.get({ url: '/infra/file-config/get?id=' + id }) +} + +// 更新文件配置为主配置 +export const updateFileConfigMaster = (id: number) => { + return request.put({ url: '/infra/file-config/update-master?id=' + id }) +} + +// 新增文件配置 +export const createFileConfig = (data: FileConfigVO) => { + return request.post({ url: '/infra/file-config/create', data }) +} + +// 修改文件配置 +export const updateFileConfig = (data: FileConfigVO) => { + return request.put({ url: '/infra/file-config/update', data }) +} + +// 删除文件配置 +export const deleteFileConfig = (id: number) => { + return request.delete({ url: '/infra/file-config/delete?id=' + id }) +} + +// 测试文件配置 +export const testFileConfig = (id: number) => { + return request.get({ url: '/infra/file-config/test?id=' + id }) +} diff --git a/src/api/infra/job/index.ts b/src/api/infra/job/index.ts new file mode 100644 index 0000000..033b2cb --- /dev/null +++ b/src/api/infra/job/index.ts @@ -0,0 +1,63 @@ +import request from '@/config/axios' + +export interface JobVO { + id: number + name: string + status: number + handlerName: string + handlerParam: string + cronExpression: string + retryCount: number + retryInterval: number + monitorTimeout: number + createTime: Date +} + +// 任务列表 +export const getJobPage = (params: PageParam) => { + return request.get({ url: '/infra/job/page', params }) +} + +// 任务详情 +export const getJob = (id: number) => { + return request.get({ url: '/infra/job/get?id=' + id }) +} + +// 新增任务 +export const createJob = (data: JobVO) => { + return request.post({ url: '/infra/job/create', data }) +} + +// 修改定时任务调度 +export const updateJob = (data: JobVO) => { + return request.put({ url: '/infra/job/update', data }) +} + +// 删除定时任务调度 +export const deleteJob = (id: number) => { + return request.delete({ url: '/infra/job/delete?id=' + id }) +} + +// 导出定时任务调度 +export const exportJob = (params) => { + return request.download({ url: '/infra/job/export-excel', params }) +} + +// 任务状态修改 +export const updateJobStatus = (id: number, status: number) => { + const params = { + id, + status + } + return request.put({ url: '/infra/job/update-status', params }) +} + +// 定时任务立即执行一次 +export const runJob = (id: number) => { + return request.put({ url: '/infra/job/trigger?id=' + id }) +} + +// 获得定时任务的下 n 次执行时间 +export const getJobNextTimes = (id: number) => { + return request.get({ url: '/infra/job/get_next_times?id=' + id }) +} diff --git a/src/api/infra/jobLog/index.ts b/src/api/infra/jobLog/index.ts new file mode 100644 index 0000000..ed54761 --- /dev/null +++ b/src/api/infra/jobLog/index.ts @@ -0,0 +1,34 @@ +import request from '@/config/axios' + +export interface JobLogVO { + id: number + jobId: number + handlerName: string + handlerParam: string + cronExpression: string + executeIndex: string + beginTime: Date + endTime: Date + duration: string + status: number + createTime: string + result: string +} + +// 任务日志列表 +export const getJobLogPage = (params: PageParam) => { + return request.get({ url: '/infra/job-log/page', params }) +} + +// 任务日志详情 +export const getJobLog = (id: number) => { + return request.get({ url: '/infra/job-log/get?id=' + id }) +} + +// 导出定时任务日志 +export const exportJobLog = (params) => { + return request.download({ + url: '/infra/job-log/export-excel', + params + }) +} diff --git a/src/api/infra/redis/index.ts b/src/api/infra/redis/index.ts new file mode 100644 index 0000000..f27be77 --- /dev/null +++ b/src/api/infra/redis/index.ts @@ -0,0 +1,8 @@ +import request from '@/config/axios' + +/** + * 获取redis 监控信息 + */ +export const getCache = () => { + return request.get({ url: '/infra/redis/get-monitor-info' }) +} diff --git a/src/api/infra/redis/types.ts b/src/api/infra/redis/types.ts new file mode 100644 index 0000000..548bfe9 --- /dev/null +++ b/src/api/infra/redis/types.ts @@ -0,0 +1,176 @@ +export interface RedisMonitorInfoVO { + info: RedisInfoVO + dbSize: number + commandStats: RedisCommandStatsVO[] +} + +export interface RedisInfoVO { + io_threaded_reads_processed: string + tracking_clients: string + uptime_in_seconds: string + cluster_connections: string + current_cow_size: string + maxmemory_human: string + aof_last_cow_size: string + master_replid2: string + mem_replication_backlog: string + aof_rewrite_scheduled: string + total_net_input_bytes: string + rss_overhead_ratio: string + hz: string + current_cow_size_age: string + redis_build_id: string + errorstat_BUSYGROUP: string + aof_last_bgrewrite_status: string + multiplexing_api: string + client_recent_max_output_buffer: string + allocator_resident: string + mem_fragmentation_bytes: string + aof_current_size: string + repl_backlog_first_byte_offset: string + tracking_total_prefixes: string + redis_mode: string + redis_git_dirty: string + aof_delayed_fsync: string + allocator_rss_bytes: string + repl_backlog_histlen: string + io_threads_active: string + rss_overhead_bytes: string + total_system_memory: string + loading: string + evicted_keys: string + maxclients: string + cluster_enabled: string + redis_version: string + repl_backlog_active: string + mem_aof_buffer: string + allocator_frag_bytes: string + io_threaded_writes_processed: string + instantaneous_ops_per_sec: string + used_memory_human: string + total_error_replies: string + role: string + maxmemory: string + used_memory_lua: string + rdb_current_bgsave_time_sec: string + used_memory_startup: string + used_cpu_sys_main_thread: string + lazyfree_pending_objects: string + aof_pending_bio_fsync: string + used_memory_dataset_perc: string + allocator_frag_ratio: string + arch_bits: string + used_cpu_user_main_thread: string + mem_clients_normal: string + expired_time_cap_reached_count: string + unexpected_error_replies: string + mem_fragmentation_ratio: string + aof_last_rewrite_time_sec: string + master_replid: string + aof_rewrite_in_progress: string + lru_clock: string + maxmemory_policy: string + run_id: string + latest_fork_usec: string + tracking_total_items: string + total_commands_processed: string + expired_keys: string + errorstat_ERR: string + used_memory: string + module_fork_in_progress: string + errorstat_WRONGPASS: string + aof_buffer_length: string + dump_payload_sanitizations: string + mem_clients_slaves: string + keyspace_misses: string + server_time_usec: string + executable: string + lazyfreed_objects: string + db0: string + used_memory_peak_human: string + keyspace_hits: string + rdb_last_cow_size: string + aof_pending_rewrite: string + used_memory_overhead: string + active_defrag_hits: string + tcp_port: string + uptime_in_days: string + used_memory_peak_perc: string + current_save_keys_processed: string + blocked_clients: string + total_reads_processed: string + expire_cycle_cpu_milliseconds: string + sync_partial_err: string + used_memory_scripts_human: string + aof_current_rewrite_time_sec: string + aof_enabled: string + process_supervised: string + master_repl_offset: string + used_memory_dataset: string + used_cpu_user: string + rdb_last_bgsave_status: string + tracking_total_keys: string + atomicvar_api: string + allocator_rss_ratio: string + client_recent_max_input_buffer: string + clients_in_timeout_table: string + aof_last_write_status: string + mem_allocator: string + used_memory_scripts: string + used_memory_peak: string + process_id: string + master_failover_state: string + errorstat_NOAUTH: string + used_cpu_sys: string + repl_backlog_size: string + connected_slaves: string + current_save_keys_total: string + gcc_version: string + total_system_memory_human: string + sync_full: string + connected_clients: string + module_fork_last_cow_size: string + total_writes_processed: string + allocator_active: string + total_net_output_bytes: string + pubsub_channels: string + current_fork_perc: string + active_defrag_key_hits: string + rdb_changes_since_last_save: string + instantaneous_input_kbps: string + used_memory_rss_human: string + configured_hz: string + expired_stale_perc: string + active_defrag_misses: string + used_cpu_sys_children: string + number_of_cached_scripts: string + sync_partial_ok: string + used_memory_lua_human: string + rdb_last_save_time: string + pubsub_patterns: string + slave_expires_tracked_keys: string + redis_git_sha1: string + used_memory_rss: string + rdb_last_bgsave_time_sec: string + os: string + mem_not_counted_for_evict: string + active_defrag_running: string + rejected_connections: string + aof_rewrite_buffer_length: string + total_forks: string + active_defrag_key_misses: string + allocator_allocated: string + aof_base_size: string + instantaneous_output_kbps: string + second_repl_offset: string + rdb_bgsave_in_progress: string + used_cpu_user_children: string + total_connections_received: string + migrate_cached_sockets: string +} + +export interface RedisCommandStatsVO { + command: string + calls: number + usec: number +} diff --git a/src/api/iot/device/index.ts b/src/api/iot/device/index.ts new file mode 100644 index 0000000..903874b --- /dev/null +++ b/src/api/iot/device/index.ts @@ -0,0 +1,74 @@ +import request from '@/config/axios' + +// IoT 设备 VO +export interface DeviceVO { + id: number // 设备 ID,主键,自增 + deviceKey: string // 设备唯一标识符 + deviceName: string // 设备名称 + productId: number // 产品编号 + productKey: string // 产品标识 + deviceType: number // 设备类型 + nickname: string // 设备备注名称 + gatewayId: number // 网关设备 ID + status: number // 设备状态 + statusLastUpdateTime: Date // 设备状态最后更新时间 + lastOnlineTime: Date // 最后上线时间 + lastOfflineTime: Date // 最后离线时间 + activeTime: Date // 设备激活时间 + createTime: Date // 创建时间 + ip: string // 设备的 IP 地址 + firmwareVersion: string // 设备的固件版本 + deviceSecret: string // 设备密钥,用于设备认证,需安全存储 + mqttClientId: string // MQTT 客户端 ID + mqttUsername: string // MQTT 用户名 + mqttPassword: string // MQTT 密码 + authType: string // 认证类型 + latitude: number // 设备位置的纬度 + longitude: number // 设备位置的经度 + areaId: number // 地区编码 + address: string // 设备详细地址 + serialNumber: string // 设备序列号 +} + +export interface DeviceUpdateStatusVO { + id: number // 设备 ID,主键,自增 + status: number // 设备状态 +} + +// 设备 API +export const DeviceApi = { + // 查询设备分页 + getDevicePage: async (params: any) => { + return await request.get({ url: `/iot/device/page`, params }) + }, + + // 查询设备详情 + getDevice: async (id: number) => { + return await request.get({ url: `/iot/device/get?id=` + id }) + }, + + // 新增设备 + createDevice: async (data: DeviceVO) => { + return await request.post({ url: `/iot/device/create`, data }) + }, + + // 修改设备 + updateDevice: async (data: DeviceVO) => { + return await request.put({ url: `/iot/device/update`, data }) + }, + + // 修改设备状态 + updateDeviceStatus: async (data: DeviceUpdateStatusVO) => { + return await request.put({ url: `/iot/device/update-status`, data }) + }, + + // 删除设备 + deleteDevice: async (id: number) => { + return await request.delete({ url: `/iot/device/delete?id=` + id }) + }, + + // 获取设备数量 + getDeviceCount: async (productId: number) => { + return await request.get({ url: `/iot/device/count?productId=` + productId }) + } +} diff --git a/src/api/iot/product/index.ts b/src/api/iot/product/index.ts new file mode 100644 index 0000000..1ffa490 --- /dev/null +++ b/src/api/iot/product/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +// IoT 产品 VO +export interface ProductVO { + id: number // 产品编号 + name: string // 产品名称 + productKey: string // 产品标识 + protocolId: number // 协议编号 + categoryId: number // 产品所属品类标识符 + description: string // 产品描述 + validateType: number // 数据校验级别 + status: number // 产品状态 + deviceType: number // 设备类型 + netType: number // 联网方式 + protocolType: number // 接入网关协议 + dataFormat: number // 数据格式 + deviceCount: number // 设备数量 + createTime: Date // 创建时间 +} + +// IoT 产品 API +export const ProductApi = { + // 查询产品分页 + getProductPage: async (params: any) => { + return await request.get({ url: `/iot/product/page`, params }) + }, + + // 查询产品详情 + getProduct: async (id: number) => { + return await request.get({ url: `/iot/product/get?id=` + id }) + }, + + // 新增产品 + createProduct: async (data: ProductVO) => { + return await request.post({ url: `/iot/product/create`, data }) + }, + + // 修改产品 + updateProduct: async (data: ProductVO) => { + return await request.put({ url: `/iot/product/update`, data }) + }, + + // 删除产品 + deleteProduct: async (id: number) => { + return await request.delete({ url: `/iot/product/delete?id=` + id }) + }, + + // 导出产品 Excel + exportProduct: async (params) => { + return await request.download({ url: `/iot/product/export-excel`, params }) + }, + + // 更新产品状态 + updateProductStatus: async (id: number, status: number) => { + return await request.put({ url: `/iot/product/update-status?id=` + id + `&status=` + status }) + }, + + // 查询产品(精简)列表 + getSimpleProductList() { + return request.get({ url: '/iot/product/list-all-simple' }) + } +} diff --git a/src/api/iot/thinkmodelfunction/index.ts b/src/api/iot/thinkmodelfunction/index.ts new file mode 100644 index 0000000..bd2e2d0 --- /dev/null +++ b/src/api/iot/thinkmodelfunction/index.ts @@ -0,0 +1,55 @@ +import request from '@/config/axios' + +// IoT 产品物模型 VO +export interface ThinkModelFunctionVO { + id: number // 物模型功能编号 + identifier: string // 功能标识 + name: string // 功能名称 + description: string // 功能描述 + productId: number // 产品编号 + productKey: string // 产品标识 + type: number // 功能类型 + property: string // 属性 + event: string // 事件 + service: string // 服务 +} + +// IoT 产品物模型 API +export const ThinkModelFunctionApi = { + // 查询产品物模型分页 + getThinkModelFunctionPage: async (params: any) => { + return await request.get({ url: `/iot/think-model-function/page`, params }) + }, + // 获得产品物模型 + getThinkModelFunctionListByProductId: async (params: any) => { + return await request.get({ + url: `/iot/think-model-function/list-by-product-id`, + params + }) + }, + + // 查询产品物模型详情 + getThinkModelFunction: async (id: number) => { + return await request.get({ url: `/iot/think-model-function/get?id=` + id }) + }, + + // 新增产品物模型 + createThinkModelFunction: async (data: ThinkModelFunctionVO) => { + return await request.post({ url: `/iot/think-model-function/create`, data }) + }, + + // 修改产品物模型 + updateThinkModelFunction: async (data: ThinkModelFunctionVO) => { + return await request.put({ url: `/iot/think-model-function/update`, data }) + }, + + // 删除产品物模型 + deleteThinkModelFunction: async (id: number) => { + return await request.delete({ url: `/iot/think-model-function/delete?id=` + id }) + }, + + // 导出产品物模型 Excel + exportThinkModelFunction: async (params) => { + return await request.download({ url: `/iot/think-model-function/export-excel`, params }) + } +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 0000000..8c69d9b --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,87 @@ +import request from '@/config/axios' +import { getRefreshToken } from '@/utils/auth' +import type { RegisterVO, UserLoginVO } from './types' + +export interface SmsCodeVO { + mobile: string + scene: number +} + +export interface SmsLoginVO { + mobile: string + code: string +} + +// 登录 +export const login = (data: UserLoginVO) => { + return request.post({ url: '/system/auth/login', data }) +} + +// 注册 +export const register = (data: RegisterVO) => { + return request.post({ url: '/system/auth/register', data }) +} + +// 使用租户名,获得租户编号 +export const getTenantIdByName = (name: string) => { + return request.get({ url: '/system/tenant/get-id-by-name?name=' + name }) +} + +// 使用租户域名,获得租户信息 +export const getTenantByWebsite = (website: string) => { + return request.get({ url: '/system/tenant/get-by-website?website=' + website }) +} + +// 登出 +export const loginOut = () => { + return request.post({ url: '/system/auth/logout' }) +} + +// 获取用户权限信息 +export const getInfo = () => { + return request.get({ url: '/system/auth/get-permission-info' }) +} + +//获取登录验证码 +export const sendSmsCode = (data: SmsCodeVO) => { + return request.post({ url: '/system/auth/send-sms-code', data }) +} + +// 短信验证码登录 +export const smsLogin = (data: SmsLoginVO) => { + return request.post({ url: '/system/auth/sms-login', data }) +} + +// 社交快捷登录,使用 code 授权码 +export function socialLogin(type: string, code: string, state: string) { + return request.post({ + url: '/system/auth/social-login', + data: { + type, + code, + state + } + }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type: number, redirectUri: string) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} +// 获取验证图片以及 token +export const getCode = (data: any) => { + debugger + return request.postOriginal({ url: 'system/captcha/get', data }) +} + +// 滑动或者点选验证 +export const reqCheck = (data: any) => { + return request.postOriginal({ url: 'system/captcha/check', data }) +} + +// 通过短信重置密码 +export const smsResetPassword = (data: any) => { + return request.post({ url: '/system/auth/sms-reset-password', data }) +} diff --git a/src/api/login/oauth2/index.ts b/src/api/login/oauth2/index.ts new file mode 100644 index 0000000..f4a67fb --- /dev/null +++ b/src/api/login/oauth2/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// 获得授权信息 +export const getAuthorize = (clientId: string) => { + return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId }) +} + +// 发起授权 +export const authorize = ( + responseType: string, + clientId: string, + redirectUri: string, + state: string, + autoApprove: boolean, + checkedScopes: string[], + uncheckedScopes: string[] +) => { + // 构建 scopes + const scopes = {} + for (const scope of checkedScopes) { + scopes[scope] = true + } + for (const scope of uncheckedScopes) { + scopes[scope] = false + } + // 发起请求 + return request.post({ + url: '/system/oauth2/authorize', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + params: { + response_type: responseType, + client_id: clientId, + redirect_uri: redirectUri, + state: state, + auto_approve: autoApprove, + scope: JSON.stringify(scopes) + } + }) +} diff --git a/src/api/login/types.ts b/src/api/login/types.ts new file mode 100644 index 0000000..b5790e6 --- /dev/null +++ b/src/api/login/types.ts @@ -0,0 +1,38 @@ +export type UserLoginVO = { + username: string + password: string + captchaVerification: string + socialType?: string + socialCode?: string + socialState?: string +} + +export type TokenType = { + id: number // 编号 + accessToken: string // 访问令牌 + refreshToken: string // 刷新令牌 + userId: number // 用户编号 + userType: number //用户类型 + clientId: string //客户端编号 + expiresTime: number //过期时间 +} + +export type UserVO = { + id: number + username: string + nickname: string + deptId: number + email: string + mobile: string + sex: number + avatar: string + loginIp: string + loginDate: string +} + +export type RegisterVO = { + tenantName: string + username: string + password: string + captchaVerification: string +} diff --git a/src/api/mall/market/banner/index.ts b/src/api/mall/market/banner/index.ts new file mode 100644 index 0000000..ee65024 --- /dev/null +++ b/src/api/mall/market/banner/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface BannerVO { + id: number + title: string + picUrl: string + status: number + url: string + position: number + sort: number + memo: string +} + +// 查询Banner管理列表 +export const getBannerPage = async (params) => { + return await request.get({ url: `/promotion/banner/page`, params }) +} + +// 查询Banner管理详情 +export const getBanner = async (id: number) => { + return await request.get({ url: `/promotion/banner/get?id=` + id }) +} + +// 新增Banner管理 +export const createBanner = async (data: BannerVO) => { + return await request.post({ url: `/promotion/banner/create`, data }) +} + +// 修改Banner管理 +export const updateBanner = async (data: BannerVO) => { + return await request.put({ url: `/promotion/banner/update`, data }) +} + +// 删除Banner管理 +export const deleteBanner = async (id: number) => { + return await request.delete({ url: `/promotion/banner/delete?id=` + id }) +} diff --git a/src/api/mall/product/brand.ts b/src/api/mall/product/brand.ts new file mode 100644 index 0000000..94d5370 --- /dev/null +++ b/src/api/mall/product/brand.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +/** + * 商品品牌 + */ +export interface BrandVO { + /** + * 品牌编号 + */ + id?: number + /** + * 品牌名称 + */ + name: string + /** + * 品牌图片 + */ + picUrl: string + /** + * 品牌排序 + */ + sort?: number + /** + * 品牌描述 + */ + description?: string + /** + * 开启状态 + */ + status: number +} + +// 创建商品品牌 +export const createBrand = (data: BrandVO) => { + return request.post({ url: '/product/brand/create', data }) +} + +// 更新商品品牌 +export const updateBrand = (data: BrandVO) => { + return request.put({ url: '/product/brand/update', data }) +} + +// 删除商品品牌 +export const deleteBrand = (id: number) => { + return request.delete({ url: `/product/brand/delete?id=${id}` }) +} + +// 获得商品品牌 +export const getBrand = (id: number) => { + return request.get({ url: `/product/brand/get?id=${id}` }) +} + +// 获得商品品牌列表 +export const getBrandParam = (params: PageParam) => { + return request.get({ url: '/product/brand/page', params }) +} + +// 获得商品品牌精简信息列表 +export const getSimpleBrandList = () => { + return request.get({ url: '/product/brand/list-all-simple' }) +} diff --git a/src/api/mall/product/category.ts b/src/api/mall/product/category.ts new file mode 100644 index 0000000..7e80b76 --- /dev/null +++ b/src/api/mall/product/category.ts @@ -0,0 +1,56 @@ +import request from '@/config/axios' + +/** + * 产品分类 + */ +export interface CategoryVO { + /** + * 分类编号 + */ + id?: number + /** + * 父分类编号 + */ + parentId?: number + /** + * 分类名称 + */ + name: string + /** + * 移动端分类图 + */ + picUrl: string + /** + * 分类排序 + */ + sort: number + /** + * 开启状态 + */ + status: number +} + +// 创建商品分类 +export const createCategory = (data: CategoryVO) => { + return request.post({ url: '/product/category/create', data }) +} + +// 更新商品分类 +export const updateCategory = (data: CategoryVO) => { + return request.put({ url: '/product/category/update', data }) +} + +// 删除商品分类 +export const deleteCategory = (id: number) => { + return request.delete({ url: `/product/category/delete?id=${id}` }) +} + +// 获得商品分类 +export const getCategory = (id: number) => { + return request.get({ url: `/product/category/get?id=${id}` }) +} + +// 获得商品分类列表 +export const getCategoryList = (params: any) => { + return request.get({ url: '/product/category/list', params }) +} diff --git a/src/api/mall/product/comment.ts b/src/api/mall/product/comment.ts new file mode 100644 index 0000000..defdbb9 --- /dev/null +++ b/src/api/mall/product/comment.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface CommentVO { + id: number + userId: number + userNickname: string + userAvatar: string + anonymous: boolean + orderId: number + orderItemId: number + spuId: number + spuName: string + skuId: number + visible: boolean + scores: number + descriptionScores: number + benefitScores: number + content: string + picUrls: string + replyStatus: boolean + replyUserId: number + replyContent: string + replyTime: Date +} + +// 查询商品评论列表 +export const getCommentPage = async (params) => { + return await request.get({ url: `/product/comment/page`, params }) +} + +// 查询商品评论详情 +export const getComment = async (id: number) => { + return await request.get({ url: `/product/comment/get?id=` + id }) +} + +// 添加自评 +export const createComment = async (data: CommentVO) => { + return await request.post({ url: `/product/comment/create`, data }) +} + +// 显示 / 隐藏评论 +export const updateCommentVisible = async (data: any) => { + return await request.put({ url: `/product/comment/update-visible`, data }) +} + +// 商家回复 +export const replyComment = async (data: any) => { + return await request.put({ url: `/product/comment/reply`, data }) +} diff --git a/src/api/mall/product/favorite.ts b/src/api/mall/product/favorite.ts new file mode 100644 index 0000000..3834eed --- /dev/null +++ b/src/api/mall/product/favorite.ts @@ -0,0 +1,12 @@ +import request from '@/config/axios' + +export interface Favorite { + id?: number + userId?: string // 用户编号 + spuId?: number | null // 商品 SPU 编号 +} + +// 获得 ProductFavorite 列表 +export const getFavoritePage = (params: PageParam) => { + return request.get({ url: '/product/favorite/page', params }) +} diff --git a/src/api/mall/product/history.ts b/src/api/mall/product/history.ts new file mode 100644 index 0000000..0aa45bd --- /dev/null +++ b/src/api/mall/product/history.ts @@ -0,0 +1,10 @@ +import request from '@/config/axios' + +/** + * 获得商品浏览记录分页 + * + * @param params 请求参数 + */ +export const getBrowseHistoryPage = (params: any) => { + return request.get({ url: '/product/browse-history/page', params }) +} diff --git a/src/api/mall/product/property.ts b/src/api/mall/product/property.ts new file mode 100644 index 0000000..a191d82 --- /dev/null +++ b/src/api/mall/product/property.ts @@ -0,0 +1,89 @@ +import request from '@/config/axios' + +/** + * 商品属性 + */ +export interface PropertyVO { + id?: number + /** 名称 */ + name: string + /** 备注 */ + remark?: string +} + +/** + * 属性值 + */ +export interface PropertyValueVO { + id?: number + /** 属性项的编号 */ + propertyId?: number + /** 名称 */ + name: string + /** 备注 */ + remark?: string +} + +// ------------------------ 属性项 ------------------- + +// 创建属性项 +export const createProperty = (data: PropertyVO) => { + return request.post({ url: '/product/property/create', data }) +} + +// 更新属性项 +export const updateProperty = (data: PropertyVO) => { + return request.put({ url: '/product/property/update', data }) +} + +// 删除属性项 +export const deleteProperty = (id: number) => { + return request.delete({ url: `/product/property/delete?id=${id}` }) +} + +// 获得属性项 +export const getProperty = (id: number): Promise => { + return request.get({ url: `/product/property/get?id=${id}` }) +} + +// 获得属性项分页 +export const getPropertyPage = (params: PageParam) => { + return request.get({ url: '/product/property/page', params }) +} + +// 获得属性项精简列表 +export const getPropertySimpleList = (): Promise => { + return request.get({ url: '/product/property/simple-list' }) +} + +// ------------------------ 属性值 ------------------- + +// 获得属性值分页 +export const getPropertyValuePage = (params: PageParam & any) => { + return request.get({ url: '/product/property/value/page', params }) +} + +// 获得属性值 +export const getPropertyValue = (id: number): Promise => { + return request.get({ url: `/product/property/value/get?id=${id}` }) +} + +// 创建属性值 +export const createPropertyValue = (data: PropertyValueVO) => { + return request.post({ url: '/product/property/value/create', data }) +} + +// 更新属性值 +export const updatePropertyValue = (data: PropertyValueVO) => { + return request.put({ url: '/product/property/value/update', data }) +} + +// 删除属性值 +export const deletePropertyValue = (id: number) => { + return request.delete({ url: `/product/property/value/delete?id=${id}` }) +} + +// 获得属性值精简列表 +export const getPropertyValueSimpleList = (propertyId: number): Promise => { + return request.get({ url: '/product/property/value/simple-list', params: { propertyId } }) +} diff --git a/src/api/mall/product/spu.ts b/src/api/mall/product/spu.ts new file mode 100644 index 0000000..d44c0f6 --- /dev/null +++ b/src/api/mall/product/spu.ts @@ -0,0 +1,111 @@ +import request from '@/config/axios' + +export interface Property { + propertyId?: number // 属性编号 + propertyName?: string // 属性名称 + valueId?: number // 属性值编号 + valueName?: string // 属性值名称 +} + +export interface Sku { + id?: number // 商品 SKU 编号 + name?: string // 商品 SKU 名称 + spuId?: number // SPU 编号 + properties?: Property[] // 属性数组 + price?: number | string // 商品价格 + marketPrice?: number | string // 市场价 + costPrice?: number | string // 成本价 + barCode?: string // 商品条码 + picUrl?: string // 图片地址 + stock?: number // 库存 + weight?: number // 商品重量,单位:kg 千克 + volume?: number // 商品体积,单位:m^3 平米 + firstBrokeragePrice?: number | string // 一级分销的佣金 + secondBrokeragePrice?: number | string // 二级分销的佣金 + salesCount?: number // 商品销量 +} + +export interface GiveCouponTemplate { + id?: number + name?: string // 优惠券名称 +} + +export interface Spu { + id?: number + name?: string // 商品名称 + categoryId?: number // 商品分类 + keyword?: string // 关键字 + unit?: number | undefined // 单位 + picUrl?: string // 商品封面图 + sliderPicUrls?: string[] // 商品轮播图 + introduction?: string // 商品简介 + deliveryTypes?: number[] // 配送方式 + deliveryTemplateId?: number | undefined // 运费模版 + brandId?: number // 商品品牌编号 + specType?: boolean // 商品规格 + subCommissionType?: boolean // 分销类型 + skus?: Sku[] // sku数组 + description?: string // 商品详情 + sort?: number // 商品排序 + giveIntegral?: number // 赠送积分 + virtualSalesCount?: number // 虚拟销量 + price?: number // 商品价格 + combinationPrice?: number // 商品拼团价格 + seckillPrice?: number // 商品秒杀价格 + salesCount?: number // 商品销量 + marketPrice?: number // 市场价 + costPrice?: number // 成本价 + stock?: number // 商品库存 + createTime?: Date // 商品创建时间 + status?: number // 商品状态 +} + +// 获得 Spu 列表 +export const getSpuPage = (params: PageParam) => { + return request.get({ url: '/product/spu/page', params }) +} + +// 获得 Spu 列表 tabsCount +export const getTabsCount = () => { + return request.get({ url: '/product/spu/get-count' }) +} + +// 创建商品 Spu +export const createSpu = (data: Spu) => { + return request.post({ url: '/product/spu/create', data }) +} + +// 更新商品 Spu +export const updateSpu = (data: Spu) => { + return request.put({ url: '/product/spu/update', data }) +} + +// 更新商品 Spu status +export const updateStatus = (data: { id: number; status: number }) => { + return request.put({ url: '/product/spu/update-status', data }) +} + +// 获得商品 Spu +export const getSpu = (id: number) => { + return request.get({ url: `/product/spu/get-detail?id=${id}` }) +} + +// 获得商品 Spu 详情列表 +export const getSpuDetailList = (ids: number[]) => { + return request.get({ url: `/product/spu/list?spuIds=${ids}` }) +} + +// 删除商品 Spu +export const deleteSpu = (id: number) => { + return request.delete({ url: `/product/spu/delete?id=${id}` }) +} + +// 导出商品 Spu Excel +export const exportSpu = async (params) => { + return await request.download({ url: '/product/spu/export', params }) +} + +// 获得商品 SPU 精简列表 +export const getSpuSimpleList = async () => { + return request.get({ url: '/product/spu/list-all-simple' }) +} diff --git a/src/api/mall/promotion/article/index.ts b/src/api/mall/promotion/article/index.ts new file mode 100644 index 0000000..9184c7a --- /dev/null +++ b/src/api/mall/promotion/article/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface ArticleVO { + id: number + categoryId: number + title: string + author: string + picUrl: string + introduction: string + browseCount: string + sort: number + status: number + spuId: number + recommendHot: boolean + recommendBanner: boolean + content: string +} + +// 查询文章管理列表 +export const getArticlePage = async (params: any) => { + return await request.get({ url: `/promotion/article/page`, params }) +} + +// 查询文章管理详情 +export const getArticle = async (id: number) => { + return await request.get({ url: `/promotion/article/get?id=` + id }) +} + +// 新增文章管理 +export const createArticle = async (data: ArticleVO) => { + return await request.post({ url: `/promotion/article/create`, data }) +} + +// 修改文章管理 +export const updateArticle = async (data: ArticleVO) => { + return await request.put({ url: `/promotion/article/update`, data }) +} + +// 删除文章管理 +export const deleteArticle = async (id: number) => { + return await request.delete({ url: `/promotion/article/delete?id=` + id }) +} diff --git a/src/api/mall/promotion/articleCategory/index.ts b/src/api/mall/promotion/articleCategory/index.ts new file mode 100644 index 0000000..47f5e93 --- /dev/null +++ b/src/api/mall/promotion/articleCategory/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +export interface ArticleCategoryVO { + id: number + name: string + picUrl: string + status: number + sort: number +} + +// 查询文章分类列表 +export const getArticleCategoryPage = async (params) => { + return await request.get({ url: `/promotion/article-category/page`, params }) +} + +// 查询文章分类精简信息列表 +export const getSimpleArticleCategoryList = async () => { + return await request.get({ url: `/promotion/article-category/list-all-simple` }) +} + +// 查询文章分类详情 +export const getArticleCategory = async (id: number) => { + return await request.get({ url: `/promotion/article-category/get?id=` + id }) +} + +// 新增文章分类 +export const createArticleCategory = async (data: ArticleCategoryVO) => { + return await request.post({ url: `/promotion/article-category/create`, data }) +} + +// 修改文章分类 +export const updateArticleCategory = async (data: ArticleCategoryVO) => { + return await request.put({ url: `/promotion/article-category/update`, data }) +} + +// 删除文章分类 +export const deleteArticleCategory = async (id: number) => { + return await request.delete({ url: `/promotion/article-category/delete?id=` + id }) +} diff --git a/src/api/mall/promotion/bargain/bargainActivity.ts b/src/api/mall/promotion/bargain/bargainActivity.ts new file mode 100644 index 0000000..9ad219a --- /dev/null +++ b/src/api/mall/promotion/bargain/bargainActivity.ts @@ -0,0 +1,68 @@ +import request from '@/config/axios' +import { Sku, Spu } from '@/api/mall/product/spu' + +export interface BargainActivityVO { + id?: number + name?: string + startTime?: Date + endTime?: Date + status?: number + helpMaxCount?: number // 达到该人数,才能砍到低价 + bargainCount?: number // 最大帮砍次数 + totalLimitCount?: number // 最大购买次数 + spuId: number + skuId: number + bargainFirstPrice: number // 砍价起始价格,单位分 + bargainMinPrice: number // 砍价底价 + stock: number // 活动库存 + randomMinPrice?: number // 用户每次砍价的最小金额,单位:分 + randomMaxPrice?: number // 用户每次砍价的最大金额,单位:分 +} + +// 砍价活动所需属性。选择的商品和属性的时候使用方便使用活动的通用封装 +export interface BargainProductVO { + spuId: number + skuId: number + bargainFirstPrice: number // 砍价起始价格,单位分 + bargainMinPrice: number // 砍价底价 + stock: number // 活动库存 +} + +// 扩展 Sku 配置 +export type SkuExtension = Sku & { + productConfig: BargainProductVO +} + +export interface SpuExtension extends Spu { + skus: SkuExtension[] // 重写类型 +} + +// 查询砍价活动列表 +export const getBargainActivityPage = async (params: any) => { + return await request.get({ url: '/promotion/bargain-activity/page', params }) +} + +// 查询砍价活动详情 +export const getBargainActivity = async (id: number) => { + return await request.get({ url: '/promotion/bargain-activity/get?id=' + id }) +} + +// 新增砍价活动 +export const createBargainActivity = async (data: BargainActivityVO) => { + return await request.post({ url: '/promotion/bargain-activity/create', data }) +} + +// 修改砍价活动 +export const updateBargainActivity = async (data: BargainActivityVO) => { + return await request.put({ url: '/promotion/bargain-activity/update', data }) +} + +// 关闭砍价活动 +export const closeBargainActivity = async (id: number) => { + return await request.put({ url: '/promotion/bargain-activity/close?id=' + id }) +} + +// 删除砍价活动 +export const deleteBargainActivity = async (id: number) => { + return await request.delete({ url: '/promotion/bargain-activity/delete?id=' + id }) +} diff --git a/src/api/mall/promotion/bargain/bargainHelp.ts b/src/api/mall/promotion/bargain/bargainHelp.ts new file mode 100644 index 0000000..4308ae6 --- /dev/null +++ b/src/api/mall/promotion/bargain/bargainHelp.ts @@ -0,0 +1,14 @@ +import request from '@/config/axios' + +export interface BargainHelpVO { + id: number + record: number + userId: number + reducePrice: number + endTime: Date +} + +// 查询砍价记录列表 +export const getBargainHelpPage = async (params) => { + return await request.get({ url: `/promotion/bargain-help/page`, params }) +} diff --git a/src/api/mall/promotion/bargain/bargainRecord.ts b/src/api/mall/promotion/bargain/bargainRecord.ts new file mode 100644 index 0000000..f90b784 --- /dev/null +++ b/src/api/mall/promotion/bargain/bargainRecord.ts @@ -0,0 +1,19 @@ +import request from '@/config/axios' + +export interface BargainRecordVO { + id: number + activityId: number + userId: number + spuId: number + skuId: number + bargainFirstPrice: number + bargainPrice: number + status: number + orderId: number + endTime: Date +} + +// 查询砍价记录列表 +export const getBargainRecordPage = async (params) => { + return await request.get({ url: `/promotion/bargain-record/page`, params }) +} diff --git a/src/api/mall/promotion/combination/combinationActivity.ts b/src/api/mall/promotion/combination/combinationActivity.ts new file mode 100644 index 0000000..6400267 --- /dev/null +++ b/src/api/mall/promotion/combination/combinationActivity.ts @@ -0,0 +1,72 @@ +import request from '@/config/axios' +import { Sku, Spu } from '@/api/mall/product/spu' + +export interface CombinationActivityVO { + id?: number + name?: string + spuId?: number + totalLimitCount?: number + singleLimitCount?: number + startTime?: Date + endTime?: Date + userSize?: number + totalCount?: number + successCount?: number + orderUserCount?: number + virtualGroup?: number + status?: number + limitDuration?: number + combinationPrice?: number + products: CombinationProductVO[] +} + +// 拼团活动所需属性 +export interface CombinationProductVO { + spuId: number + skuId: number + combinationPrice: number // 拼团价格 +} + +// 扩展 Sku 配置 +export type SkuExtension = Sku & { + productConfig: CombinationProductVO +} + +export interface SpuExtension extends Spu { + skus: SkuExtension[] // 重写类型 +} + +// 查询拼团活动列表 +export const getCombinationActivityPage = async (params: any) => { + return await request.get({ url: '/promotion/combination-activity/page', params }) +} + +// 查询拼团活动详情 +export const getCombinationActivity = async (id: number) => { + return await request.get({ url: '/promotion/combination-activity/get?id=' + id }) +} + +// 获得拼团活动列表,基于活动编号数组 +export const getCombinationActivityListByIds = (ids: number[]) => { + return request.get({ url: `/promotion/combination-activity/list-by-ids?ids=${ids}` }) +} + +// 新增拼团活动 +export const createCombinationActivity = async (data: CombinationActivityVO) => { + return await request.post({ url: '/promotion/combination-activity/create', data }) +} + +// 修改拼团活动 +export const updateCombinationActivity = async (data: CombinationActivityVO) => { + return await request.put({ url: '/promotion/combination-activity/update', data }) +} + +// 关闭拼团活动 +export const closeCombinationActivity = async (id: number) => { + return await request.put({ url: '/promotion/combination-activity/close?id=' + id }) +} + +// 删除拼团活动 +export const deleteCombinationActivity = async (id: number) => { + return await request.delete({ url: '/promotion/combination-activity/delete?id=' + id }) +} diff --git a/src/api/mall/promotion/combination/combinationRecord.ts b/src/api/mall/promotion/combination/combinationRecord.ts new file mode 100644 index 0000000..b2b7d75 --- /dev/null +++ b/src/api/mall/promotion/combination/combinationRecord.ts @@ -0,0 +1,28 @@ +import request from '@/config/axios' + +export interface CombinationRecordVO { + id: number // 拼团记录编号 + activityId: number // 拼团活动编号 + nickname: string // 用户昵称 + avatar: string // 用户头像 + headId: number // 团长编号 + expireTime: string // 过期时间 + userSize: number // 可参团人数 + userCount: number // 已参团人数 + status: number // 拼团状态 + spuName: string // 商品名字 + picUrl: string // 商品图片 + virtualGroup: boolean // 是否虚拟成团 + startTime: string // 开始时间 (订单付款后开始的时间) + endTime: string // 结束时间(成团时间/失败时间) +} + +// 查询拼团记录列表 +export const getCombinationRecordPage = async (params: any) => { + return await request.get({ url: '/promotion/combination-record/page', params }) +} + +// 获得拼团记录的概要信息 +export const getCombinationRecordSummary = async () => { + return await request.get({ url: '/promotion/combination-record/get-summary' }) +} diff --git a/src/api/mall/promotion/coupon/coupon.ts b/src/api/mall/promotion/coupon/coupon.ts new file mode 100644 index 0000000..2ebff5d --- /dev/null +++ b/src/api/mall/promotion/coupon/coupon.ts @@ -0,0 +1,26 @@ +import request from '@/config/axios' + +// TODO @dhb52:vo 缺少 + +// 删除优惠劵 +export const deleteCoupon = async (id: number) => { + return request.delete({ + url: `/promotion/coupon/delete?id=${id}` + }) +} + +// 获得优惠劵分页 +export const getCouponPage = async (params: PageParam) => { + return request.get({ + url: '/promotion/coupon/page', + params: params + }) +} + +// 发送优惠券 +export const sendCoupon = async (data: any) => { + return request.post({ + url: '/promotion/coupon/send', + data: data + }) +} diff --git a/src/api/mall/promotion/coupon/couponTemplate.ts b/src/api/mall/promotion/coupon/couponTemplate.ts new file mode 100644 index 0000000..7e0a68c --- /dev/null +++ b/src/api/mall/promotion/coupon/couponTemplate.ts @@ -0,0 +1,90 @@ +import request from '@/config/axios' + +export interface CouponTemplateVO { + id: number + name: string + status: number + totalCount: number + takeLimitCount: number + takeType: number + usePrice: number + productScope: number + productScopeValues: number[] + validityType: number + validStartTime: Date + validEndTime: Date + fixedStartTerm: number + fixedEndTerm: number + discountType: number + discountPercent: number + discountPrice: number + discountLimitPrice: number + takeCount: number + useCount: number +} + +// 创建优惠劵模板 +export function createCouponTemplate(data: CouponTemplateVO) { + return request.post({ + url: '/promotion/coupon-template/create', + data: data + }) +} + +// 更新优惠劵模板 +export function updateCouponTemplate(data: CouponTemplateVO) { + return request.put({ + url: '/promotion/coupon-template/update', + data: data + }) +} + +// 更新优惠劵模板的状态 +export function updateCouponTemplateStatus(id: number, status: [0, 1]) { + const data = { + id, + status + } + return request.put({ + url: '/promotion/coupon-template/update-status', + data: data + }) +} + +// 删除优惠劵模板 +export function deleteCouponTemplate(id: number) { + return request.delete({ + url: '/promotion/coupon-template/delete?id=' + id + }) +} + +// 获得优惠劵模板 +export function getCouponTemplate(id: number) { + return request.get({ + url: '/promotion/coupon-template/get?id=' + id + }) +} + +// 获得优惠劵模板分页 +export function getCouponTemplatePage(params: PageParam) { + return request.get({ + url: '/promotion/coupon-template/page', + params: params + }) +} + +// 获得优惠劵模板分页 +export function getCouponTemplateList(ids: number[]): Promise { + return request.get({ + url: `/promotion/coupon-template/list?ids=${ids}` + }) +} + +// 导出优惠劵模板 Excel +export function exportCouponTemplateExcel(params: PageParam) { + return request.get({ + url: '/promotion/coupon-template/export-excel', + params: params, + responseType: 'blob' + }) +} diff --git a/src/api/mall/promotion/discount/discountActivity.ts b/src/api/mall/promotion/discount/discountActivity.ts new file mode 100644 index 0000000..e755c1b --- /dev/null +++ b/src/api/mall/promotion/discount/discountActivity.ts @@ -0,0 +1,60 @@ +import request from '@/config/axios' +import { Sku, Spu } from '@/api/mall/product/spu' + +export interface DiscountActivityVO { + id?: number + spuId?: number + name?: string + status?: number + remark?: string + startTime?: Date + endTime?: Date + products?: DiscountProductVO[] +} +// 限时折扣相关 属性 +export interface DiscountProductVO { + spuId: number + skuId: number + discountType: number + discountPercent: number + discountPrice: number +} + +// 扩展 Sku 配置 +export type SkuExtension = Sku & { + productConfig: DiscountProductVO +} + +export interface SpuExtension extends Spu { + skus: SkuExtension[] // 重写类型 +} + +// 查询限时折扣活动列表 +export const getDiscountActivityPage = async (params) => { + return await request.get({ url: '/promotion/discount-activity/page', params }) +} + +// 查询限时折扣活动详情 +export const getDiscountActivity = async (id: number) => { + return await request.get({ url: '/promotion/discount-activity/get?id=' + id }) +} + +// 新增限时折扣活动 +export const createDiscountActivity = async (data: DiscountActivityVO) => { + return await request.post({ url: '/promotion/discount-activity/create', data }) +} + +// 修改限时折扣活动 +export const updateDiscountActivity = async (data: DiscountActivityVO) => { + return await request.put({ url: '/promotion/discount-activity/update', data }) +} + +// 关闭限时折扣活动 +export const closeDiscountActivity = async (id: number) => { + return await request.put({ url: '/promotion/discount-activity/close?id=' + id }) +} + +// 删除限时折扣活动 +export const deleteDiscountActivity = async (id: number) => { + return await request.delete({ url: '/promotion/discount-activity/delete?id=' + id }) +} diff --git a/src/api/mall/promotion/diy/page.ts b/src/api/mall/promotion/diy/page.ts new file mode 100644 index 0000000..a834b24 --- /dev/null +++ b/src/api/mall/promotion/diy/page.ts @@ -0,0 +1,45 @@ +import request from '@/config/axios' + +export interface DiyPageVO { + id?: number + templateId?: number + name: string + remark: string + previewPicUrls: string[] + property: string +} + +// 查询装修页面列表 +export const getDiyPagePage = async (params: any) => { + return await request.get({ url: `/promotion/diy-page/page`, params }) +} + +// 查询装修页面详情 +export const getDiyPage = async (id: number) => { + return await request.get({ url: `/promotion/diy-page/get?id=` + id }) +} + +// 新增装修页面 +export const createDiyPage = async (data: DiyPageVO) => { + return await request.post({ url: `/promotion/diy-page/create`, data }) +} + +// 修改装修页面 +export const updateDiyPage = async (data: DiyPageVO) => { + return await request.put({ url: `/promotion/diy-page/update`, data }) +} + +// 删除装修页面 +export const deleteDiyPage = async (id: number) => { + return await request.delete({ url: `/promotion/diy-page/delete?id=` + id }) +} + +// 获得装修页面属性 +export const getDiyPageProperty = async (id: number) => { + return await request.get({ url: `/promotion/diy-page/get-property?id=` + id }) +} + +// 更新装修页面属性 +export const updateDiyPageProperty = async (data: DiyPageVO) => { + return await request.put({ url: `/promotion/diy-page/update-property`, data }) +} diff --git a/src/api/mall/promotion/diy/template.ts b/src/api/mall/promotion/diy/template.ts new file mode 100644 index 0000000..87134c9 --- /dev/null +++ b/src/api/mall/promotion/diy/template.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' +import { DiyPageVO } from '@/api/mall/promotion/diy/page' + +export interface DiyTemplateVO { + id?: number + name: string + used: boolean + usedTime?: Date + remark: string + previewPicUrls: string[] + property: string +} + +export interface DiyTemplatePropertyVO extends DiyTemplateVO { + pages: DiyPageVO[] +} + +// 查询装修模板列表 +export const getDiyTemplatePage = async (params: any) => { + return await request.get({ url: `/promotion/diy-template/page`, params }) +} + +// 查询装修模板详情 +export const getDiyTemplate = async (id: number) => { + return await request.get({ url: `/promotion/diy-template/get?id=` + id }) +} + +// 新增装修模板 +export const createDiyTemplate = async (data: DiyTemplateVO) => { + return await request.post({ url: `/promotion/diy-template/create`, data }) +} + +// 修改装修模板 +export const updateDiyTemplate = async (data: DiyTemplateVO) => { + return await request.put({ url: `/promotion/diy-template/update`, data }) +} + +// 删除装修模板 +export const deleteDiyTemplate = async (id: number) => { + return await request.delete({ url: `/promotion/diy-template/delete?id=` + id }) +} + +// 使用装修模板 +export const useDiyTemplate = async (id: number) => { + return await request.put({ url: `/promotion/diy-template/use?id=` + id }) +} + +// 获得装修模板属性 +export const getDiyTemplateProperty = async (id: number) => { + return await request.get({ + url: `/promotion/diy-template/get-property?id=` + id + }) +} + +// 更新装修模板属性 +export const updateDiyTemplateProperty = async (data: DiyTemplateVO) => { + return await request.put({ url: `/promotion/diy-template/update-property`, data }) +} diff --git a/src/api/mall/promotion/kefu/conversation/index.ts b/src/api/mall/promotion/kefu/conversation/index.ts new file mode 100644 index 0000000..eb6eb9c --- /dev/null +++ b/src/api/mall/promotion/kefu/conversation/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +export interface KeFuConversationRespVO { + id: number // 编号 + userId: number // 会话所属用户 + userAvatar: string // 会话所属用户头像 + userNickname: string // 会话所属用户昵称 + lastMessageTime: Date // 最后聊天时间 + lastMessageContent: string // 最后聊天内容 + lastMessageContentType: number // 最后发送的消息类型 + adminPinned: boolean // 管理端置顶 + userDeleted: boolean // 用户是否可见 + adminDeleted: boolean // 管理员是否可见 + adminUnreadMessageCount: number // 管理员未读消息数 + createTime?: string // 创建时间 +} + +// 客服会话 API +export const KeFuConversationApi = { + // 获得客服会话列表 + getConversationList: async () => { + return await request.get({ url: '/promotion/kefu-conversation/list' }) + }, + // 获得客服会话 + getConversation: async (id: number) => { + return await request.get({ url: `/promotion/kefu-conversation/get?id=` + id }) + }, + // 客服会话置顶 + updateConversationPinned: async (data: any) => { + return await request.put({ + url: '/promotion/kefu-conversation/update-conversation-pinned', + data + }) + }, + // 删除客服会话 + deleteConversation: async (id: number) => { + return await request.delete({ url: `/promotion/kefu-conversation/delete?id=${id}` }) + } +} diff --git a/src/api/mall/promotion/kefu/message/index.ts b/src/api/mall/promotion/kefu/message/index.ts new file mode 100644 index 0000000..4c3bed8 --- /dev/null +++ b/src/api/mall/promotion/kefu/message/index.ts @@ -0,0 +1,36 @@ +import request from '@/config/axios' + +export interface KeFuMessageRespVO { + id: number // 编号 + conversationId: number // 会话编号 + senderId: number // 发送人编号 + senderAvatar: string // 发送人头像 + senderType: number // 发送人类型 + receiverId: number // 接收人编号 + receiverType: number // 接收人类型 + contentType: number // 消息类型 + content: string // 消息 + readStatus: boolean // 是否已读 + createTime: Date // 创建时间 +} + +// 客服会话 API +export const KeFuMessageApi = { + // 发送客服消息 + sendKeFuMessage: async (data: any) => { + return await request.post({ + url: '/promotion/kefu-message/send', + data + }) + }, + // 更新客服消息已读状态 + updateKeFuMessageReadStatus: async (conversationId: number) => { + return await request.put({ + url: '/promotion/kefu-message/update-read-status?conversationId=' + conversationId + }) + }, + // 获得消息列表(流式加载) + getKeFuMessageList: async (params: any) => { + return await request.get({ url: '/promotion/kefu-message/list', params }) + } +} diff --git a/src/api/mall/promotion/point/index.ts b/src/api/mall/promotion/point/index.ts new file mode 100644 index 0000000..38254c2 --- /dev/null +++ b/src/api/mall/promotion/point/index.ts @@ -0,0 +1,91 @@ +import request from '@/config/axios' +import { Sku, Spu } from '@/api/mall/product/spu' // 积分商城活动 VO + +// 积分商城活动 VO +export interface PointActivityVO { + id: number // 积分商城活动编号 + spuId: number // 积分商城活动商品 + status: number // 活动状态 + stock: number // 积分商城活动库存 + totalStock: number // 积分商城活动总库存 + remark?: string // 备注 + sort: number // 排序 + createTime: string // 创建时间 + products: PointProductVO[] // 积分商城商品 + + // ========== 商品字段 ========== + spuName: string // 商品名称 + picUrl: string // 商品主图 + marketPrice: number // 商品市场价,单位:分 + + //======================= 显示所需兑换积分最少的 sku 信息 ======================= + point: number // 兑换积分 + price: number // 兑换金额,单位:分 +} + +// 秒杀活动所需属性 +export interface PointProductVO { + id?: number // 积分商城商品编号 + activityId?: number // 积分商城活动 id + spuId?: number // 商品 SPU 编号 + skuId: number // 商品 SKU 编号 + count: number // 可兑换数量 + point: number // 兑换积分 + price: number // 兑换金额,单位:分 + stock: number // 积分商城商品库存 + activityStatus?: number // 积分商城商品状态 +} + +// 扩展 Sku 配置 +export type SkuExtension = Sku & { + productConfig: PointProductVO +} + +export interface SpuExtension extends Spu { + skus: SkuExtension[] // 重写类型 +} + +export interface SpuExtension0 extends Spu { + pointStock: number // 积分商城活动库存 + pointTotalStock: number // 积分商城活动总库存 + point: number // 兑换积分 + pointPrice: number // 兑换金额,单位:分 +} + +// 积分商城活动 API +export const PointActivityApi = { + // 查询积分商城活动分页 + getPointActivityPage: async (params: any) => { + return await request.get({ url: `/promotion/point-activity/page`, params }) + }, + + // 查询积分商城活动详情 + getPointActivity: async (id: number) => { + return await request.get({ url: `/promotion/point-activity/get?id=` + id }) + }, + + // 查询积分商城活动列表,基于活动编号数组 + getPointActivityListByIds: async (ids: number[]) => { + return request.get({ url: `/promotion/point-activity/list-by-ids?ids=${ids}` }) + }, + + // 新增积分商城活动 + createPointActivity: async (data: PointActivityVO) => { + return await request.post({ url: `/promotion/point-activity/create`, data }) + }, + + // 修改积分商城活动 + updatePointActivity: async (data: PointActivityVO) => { + return await request.put({ url: `/promotion/point-activity/update`, data }) + }, + + // 删除积分商城活动 + deletePointActivity: async (id: number) => { + return await request.delete({ url: `/promotion/point-activity/delete?id=` + id }) + }, + + // 关闭秒杀活动 + closePointActivity: async (id: number) => { + return await request.put({ url: '/promotion/point-activity/close?id=' + id }) + } +} diff --git a/src/api/mall/promotion/reward/rewardActivity.ts b/src/api/mall/promotion/reward/rewardActivity.ts new file mode 100644 index 0000000..e9f95ed --- /dev/null +++ b/src/api/mall/promotion/reward/rewardActivity.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' + +export interface RewardActivityVO { + id?: number + name?: string + startTime?: Date + endTime?: Date + startAndEndTime?: Date[] // 只前端使用 + remark?: string + conditionType?: number + productScope?: number + rules: RewardRule[] + // 如下仅用于表单,不提交 + productScopeValues?: number[] // 商品范围:值为品类编号列表、商品编号列表 + productCategoryIds?: number[] + productSpuIds?: number[] +} + +// 优惠规则 +export interface RewardRule { + limit?: number + discountPrice?: number + freeDelivery?: boolean + point: number + giveCouponTemplateCounts?: { + [key: number]: number + } +} + +// 新增满减送活动 +export const createRewardActivity = async (data: RewardActivityVO) => { + return await request.post({ url: '/promotion/reward-activity/create', data }) +} + +// 更新满减送活动 +export const updateRewardActivity = async (data: RewardActivityVO) => { + return await request.put({ url: '/promotion/reward-activity/update', data }) +} + +// 查询满减送活动列表 +export const getRewardActivityPage = async (params) => { + return await request.get({ url: '/promotion/reward-activity/page', params }) +} + +// 查询满减送活动详情 +export const getReward = async (id: number) => { + return await request.get({ url: '/promotion/reward-activity/get?id=' + id }) +} + +// 删除满减送活动 +export const deleteRewardActivity = async (id: number) => { + return await request.delete({ url: '/promotion/reward-activity/delete?id=' + id }) +} + +// 关闭满减送活动 +export const closeRewardActivity = async (id: number) => { + return await request.put({ url: '/promotion/reward-activity/close?id=' + id }) +} diff --git a/src/api/mall/promotion/seckill/seckillActivity.ts b/src/api/mall/promotion/seckill/seckillActivity.ts new file mode 100644 index 0000000..dc5a350 --- /dev/null +++ b/src/api/mall/promotion/seckill/seckillActivity.ts @@ -0,0 +1,75 @@ +import request from '@/config/axios' +import { Sku, Spu } from '@/api/mall/product/spu' + +export interface SeckillActivityVO { + id?: number + spuId?: number + name?: string + status?: number + remark?: string + startTime?: Date + endTime?: Date + sort?: number + configIds?: string + orderCount?: number + userCount?: number + totalPrice?: number + totalLimitCount?: number + singleLimitCount?: number + stock?: number + totalStock?: number + seckillPrice?: number + products?: SeckillProductVO[] +} + +// 秒杀活动所需属性 +export interface SeckillProductVO { + skuId: number + spuId: number + seckillPrice: number + stock: number +} + +// 扩展 Sku 配置 +export type SkuExtension = Sku & { + productConfig: SeckillProductVO +} + +export interface SpuExtension extends Spu { + skus: SkuExtension[] // 重写类型 +} + +// 查询秒杀活动列表 +export const getSeckillActivityPage = async (params) => { + return await request.get({ url: '/promotion/seckill-activity/page', params }) +} + +// 查询秒杀活动列表,基于活动编号数组 +export const getSeckillActivityListByIds = (ids: number[]) => { + return request.get({ url: `/promotion/seckill-activity/list-by-ids?ids=${ids}` }) +} + +// 查询秒杀活动详情 +export const getSeckillActivity = async (id: number) => { + return await request.get({ url: '/promotion/seckill-activity/get?id=' + id }) +} + +// 新增秒杀活动 +export const createSeckillActivity = async (data: SeckillActivityVO) => { + return await request.post({ url: '/promotion/seckill-activity/create', data }) +} + +// 修改秒杀活动 +export const updateSeckillActivity = async (data: SeckillActivityVO) => { + return await request.put({ url: '/promotion/seckill-activity/update', data }) +} + +// 关闭秒杀活动 +export const closeSeckillActivity = async (id: number) => { + return await request.put({ url: '/promotion/seckill-activity/close?id=' + id }) +} + +// 删除秒杀活动 +export const deleteSeckillActivity = async (id: number) => { + return await request.delete({ url: '/promotion/seckill-activity/delete?id=' + id }) +} diff --git a/src/api/mall/promotion/seckill/seckillConfig.ts b/src/api/mall/promotion/seckill/seckillConfig.ts new file mode 100644 index 0000000..37d9b54 --- /dev/null +++ b/src/api/mall/promotion/seckill/seckillConfig.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +// 秒杀时段 VO +export interface SeckillConfigVO { + id: number // 编号 + name: string // 秒杀时段名称 + startTime: string // 开始时间点 + endTime: string // 结束时间点 + sliderPicUrls: string[] // 秒杀轮播图 + status: number // 活动状态 +} + +// 秒杀时段 API +export const SeckillConfigApi = { + // 查询秒杀时段分页 + getSeckillConfigPage: async (params: any) => { + return await request.get({ url: `/promotion/seckill-config/page`, params }) + }, + + // 查询秒杀时段列表 + getSimpleSeckillConfigList: async () => { + return await request.get({ url: `/promotion/seckill-config/list` }) + }, + + // 查询秒杀时段详情 + getSeckillConfig: async (id: number) => { + return await request.get({ url: `/promotion/seckill-config/get?id=` + id }) + }, + + // 新增秒杀时段 + createSeckillConfig: async (data: SeckillConfigVO) => { + return await request.post({ url: `/promotion/seckill-config/create`, data }) + }, + + // 修改秒杀时段 + updateSeckillConfig: async (data: SeckillConfigVO) => { + return await request.put({ url: `/promotion/seckill-config/update`, data }) + }, + + // 删除秒杀时段 + deleteSeckillConfig: async (id: number) => { + return await request.delete({ url: `/promotion/seckill-config/delete?id=` + id }) + }, + + // 修改时段配置状态 + updateSeckillConfigStatus: async (id: number, status: number) => { + const data = { + id, + status + } + return request.put({ url: '/promotion/seckill-config/update-status', data: data }) + } +} diff --git a/src/api/mall/statistics/common.ts b/src/api/mall/statistics/common.ts new file mode 100644 index 0000000..3d96439 --- /dev/null +++ b/src/api/mall/statistics/common.ts @@ -0,0 +1,5 @@ +/** 数据对照 Response VO */ +export interface DataComparisonRespVO { + value: T + reference: T +} diff --git a/src/api/mall/statistics/member.ts b/src/api/mall/statistics/member.ts new file mode 100644 index 0000000..d9accf9 --- /dev/null +++ b/src/api/mall/statistics/member.ts @@ -0,0 +1,123 @@ +import request from '@/config/axios' +import dayjs from 'dayjs' +import { DataComparisonRespVO } from '@/api/mall/statistics/common' +import { formatDate } from '@/utils/formatTime' + +/** 会员分析 Request VO */ +export interface MemberAnalyseReqVO { + times: dayjs.ConfigType[] +} + +/** 会员分析 Response VO */ +export interface MemberAnalyseRespVO { + visitUserCount: number + orderUserCount: number + payUserCount: number + atv: number + comparison: DataComparisonRespVO +} + +/** 会员分析对照数据 Response VO */ +export interface MemberAnalyseComparisonRespVO { + registerUserCount: number + visitUserCount: number + rechargeUserCount: number +} + +/** 会员地区统计 Response VO */ +export interface MemberAreaStatisticsRespVO { + areaId: number + areaName: string + userCount: number + orderCreateUserCount: number + orderPayUserCount: number + orderPayPrice: number +} + +/** 会员性别统计 Response VO */ +export interface MemberSexStatisticsRespVO { + sex: number + userCount: number +} + +/** 会员统计 Response VO */ +export interface MemberSummaryRespVO { + userCount: number + rechargeUserCount: number + rechargePrice: number + expensePrice: number +} + +/** 会员终端统计 Response VO */ +export interface MemberTerminalStatisticsRespVO { + terminal: number + userCount: number +} + +/** 会员数量统计 Response VO */ +export interface MemberCountRespVO { + /** 用户访问量 */ + visitUserCount: string + /** 注册用户数量 */ + registerUserCount: number +} + +/** 会员注册数量 Response VO */ +export interface MemberRegisterCountRespVO { + date: string + count: number +} + +// 查询会员统计 +export const getMemberSummary = () => { + return request.get({ + url: '/statistics/member/summary' + }) +} + +// 查询会员分析数据 +export const getMemberAnalyse = (params: MemberAnalyseReqVO) => { + return request.get({ + url: '/statistics/member/analyse', + params: { times: [formatDate(params.times[0]), formatDate(params.times[1])] } + }) +} + +// 按照省份,查询会员统计列表 +export const getMemberAreaStatisticsList = () => { + return request.get({ + url: '/statistics/member/area-statistics-list' + }) +} + +// 按照性别,查询会员统计列表 +export const getMemberSexStatisticsList = () => { + return request.get({ + url: '/statistics/member/sex-statistics-list' + }) +} + +// 按照终端,查询会员统计列表 +export const getMemberTerminalStatisticsList = () => { + return request.get({ + url: '/statistics/member/terminal-statistics-list' + }) +} + +// 获得用户数量量对照 +export const getUserCountComparison = () => { + return request.get>({ + url: '/statistics/member/user-count-comparison' + }) +} + +// 获得会员注册数量列表 +export const getMemberRegisterCountList = ( + beginTime: dayjs.ConfigType, + endTime: dayjs.ConfigType +) => { + return request.get({ + url: '/statistics/member/register-count-list', + params: { times: [formatDate(beginTime), formatDate(endTime)] } + }) +} diff --git a/src/api/mall/statistics/pay.ts b/src/api/mall/statistics/pay.ts new file mode 100644 index 0000000..f5d14c9 --- /dev/null +++ b/src/api/mall/statistics/pay.ts @@ -0,0 +1,12 @@ +import request from '@/config/axios' + +/** 支付统计 */ +export interface PaySummaryRespVO { + /** 充值金额,单位分 */ + rechargePrice: number +} + +/** 获取钱包充值金额 */ +export const getWalletRechargePrice = async () => { + return await request.get({ url: `/statistics/pay/summary` }) +} diff --git a/src/api/mall/statistics/product.ts b/src/api/mall/statistics/product.ts new file mode 100644 index 0000000..798a2fa --- /dev/null +++ b/src/api/mall/statistics/product.ts @@ -0,0 +1,52 @@ +import request from '@/config/axios' +import { DataComparisonRespVO } from '@/api/mall/statistics/common' + +export interface ProductStatisticsVO { + id: number + day: string + spuId: number + spuName: string + spuPicUrl: string + browseCount: number + browseUserCount: number + favoriteCount: number + cartCount: number + orderCount: number + orderPayCount: number + orderPayPrice: number + afterSaleCount: number + afterSaleRefundPrice: number + browseConvertPercent: number +} + +// 商品统计 API +export const ProductStatisticsApi = { + // 获得商品统计分析 + getProductStatisticsAnalyse: (params: any) => { + return request.get>({ + url: '/statistics/product/analyse', + params + }) + }, + // 获得商品状况明细 + getProductStatisticsList: (params: any) => { + return request.get({ + url: '/statistics/product/list', + params + }) + }, + // 导出获得商品状况明细 Excel + exportProductStatisticsExcel: (params: any) => { + return request.download({ + url: '/statistics/product/export-excel', + params + }) + }, + // 获得商品排行榜分页 + getProductStatisticsRankPage: async (params: any) => { + return await request.get({ + url: `/statistics/product/rank-page`, + params + }) + } +} diff --git a/src/api/mall/statistics/trade.ts b/src/api/mall/statistics/trade.ts new file mode 100644 index 0000000..e59952a --- /dev/null +++ b/src/api/mall/statistics/trade.ts @@ -0,0 +1,119 @@ +import request from '@/config/axios' +import dayjs from 'dayjs' +import { formatDate } from '@/utils/formatTime' +import { DataComparisonRespVO } from '@/api/mall/statistics/common' + +/** 交易统计 Response VO */ +export interface TradeSummaryRespVO { + yesterdayOrderCount: number + monthOrderCount: number + yesterdayPayPrice: number + monthPayPrice: number +} + +/** 交易状况 Request VO */ +export interface TradeTrendReqVO { + times: [dayjs.ConfigType, dayjs.ConfigType] +} + +/** 交易状况统计 Response VO */ +export interface TradeTrendSummaryRespVO { + time: string + turnoverPrice: number + orderPayPrice: number + rechargePrice: number + expensePrice: number + walletPayPrice: number + brokerageSettlementPrice: number + afterSaleRefundPrice: number +} + +/** 交易订单数量 Response VO */ +export interface TradeOrderCountRespVO { + /** 待发货 */ + undelivered?: number + /** 待核销 */ + pickUp?: number + /** 退款中 */ + afterSaleApply?: number + /** 提现待审核 */ + auditingWithdraw?: number +} + +/** 交易订单统计 Response VO */ +export interface TradeOrderSummaryRespVO { + /** 支付订单商品数 */ + orderPayCount?: number + /** 总支付金额,单位:分 */ + orderPayPrice?: number +} + +/** 订单量趋势统计 Response VO */ +export interface TradeOrderTrendRespVO { + /** 日期 */ + date: string + /** 订单数量 */ + orderPayCount: number + /** 订单支付金额 */ + orderPayPrice: number +} + +// 查询交易统计 +export const getTradeStatisticsSummary = () => { + return request.get>({ + url: '/statistics/trade/summary' + }) +} + +// 获得交易状况统计 +export const getTradeStatisticsAnalyse = (params: TradeTrendReqVO) => { + return request.get>({ + url: '/statistics/trade/analyse', + params: formatDateParam(params) + }) +} + +// 获得交易状况明细 +export const getTradeStatisticsList = (params: TradeTrendReqVO) => { + return request.get({ + url: '/statistics/trade/list', + params: formatDateParam(params) + }) +} + +// 导出交易状况明细 +export const exportTradeStatisticsExcel = (params: TradeTrendReqVO) => { + return request.download({ + url: '/statistics/trade/export-excel', + params: formatDateParam(params) + }) +} + +// 获得交易订单数量 +export const getOrderCount = async () => { + return await request.get({ url: `/statistics/trade/order-count` }) +} + +// 获得交易订单数量对照 +export const getOrderComparison = async () => { + return await request.get>({ + url: `/statistics/trade/order-comparison` + }) +} + +// 获得订单量趋势统计 +export const getOrderCountTrendComparison = ( + type: number, + beginTime: dayjs.ConfigType, + endTime: dayjs.ConfigType +) => { + return request.get[]>({ + url: '/statistics/trade/order-count-trend', + params: { type, beginTime: formatDate(beginTime), endTime: formatDate(endTime) } + }) +} + +/** 时间参数需要格式化, 确保接口能识别 */ +const formatDateParam = (params: TradeTrendReqVO) => { + return { times: [formatDate(params.times[0]), formatDate(params.times[1])] } as TradeTrendReqVO +} diff --git a/src/api/mall/trade/afterSale/index.ts b/src/api/mall/trade/afterSale/index.ts new file mode 100644 index 0000000..a109ee6 --- /dev/null +++ b/src/api/mall/trade/afterSale/index.ts @@ -0,0 +1,75 @@ +import request from '@/config/axios' + +export interface TradeAfterSaleVO { + id?: number | null // 售后编号,主键自增 + no?: string // 售后单号 + status?: number | null // 退款状态 + way?: number | null // 售后方式 + type?: number | null // 售后类型 + userId?: number | null // 用户编号 + applyReason?: string // 申请原因 + applyDescription?: string // 补充描述 + applyPicUrls?: string[] // 补充凭证图片 + orderId?: number | null // 交易订单编号 + orderNo?: string // 订单流水号 + orderItemId?: number | null // 交易订单项编号 + spuId?: number | null // 商品 SPU 编号 + spuName?: string // 商品 SPU 名称 + skuId?: number | null // 商品 SKU 编号 + properties?: ProductPropertiesVO[] // 属性数组 + picUrl?: string // 商品图片 + count?: number | null // 退货商品数量 + auditTime?: Date // 审批时间 + auditUserId?: number | null // 审批人 + auditReason?: string // 审批备注 + refundPrice?: number | null // 退款金额,单位:分。 + payRefundId?: number | null // 支付退款编号 + refundTime?: Date // 退款时间 + logisticsId?: number | null // 退货物流公司编号 + logisticsNo?: string // 退货物流单号 + deliveryTime?: Date // 退货时间 + receiveTime?: Date // 收货时间 + receiveReason?: string // 收货备注 +} + +export interface ProductPropertiesVO { + propertyId?: number | null // 属性的编号 + propertyName?: string // 属性的名称 + valueId?: number | null //属性值的编号 + valueName?: string // 属性值的名称 +} + +// 获得交易售后分页 +export const getAfterSalePage = async (params) => { + return await request.get({ url: `/trade/after-sale/page`, params }) +} + +// 获得交易售后详情 +export const getAfterSale = async (id: any) => { + return await request.get({ url: `/trade/after-sale/get-detail?id=${id}` }) +} + +// 同意售后 +export const agree = async (id: any) => { + return await request.put({ url: `/trade/after-sale/agree?id=${id}` }) +} + +// 拒绝售后 +export const disagree = async (data: any) => { + return await request.put({ url: `/trade/after-sale/disagree`, data }) +} + +// 确认收货 +export const receive = async (id: any) => { + return await request.put({ url: `/trade/after-sale/receive?id=${id}` }) +} + +// 拒绝收货 +export const refuse = async (id: any) => { + return await request.put({ url: `/trade/after-sale/refuse?id=${id}` }) +} + +// 确认退款 +export const refund = async (id: any) => { + return await request.put({ url: `/trade/after-sale/refund?id=${id}` }) +} diff --git a/src/api/mall/trade/brokerage/record/index.ts b/src/api/mall/trade/brokerage/record/index.ts new file mode 100644 index 0000000..7df9a22 --- /dev/null +++ b/src/api/mall/trade/brokerage/record/index.ts @@ -0,0 +1,11 @@ +import request from '@/config/axios' + +// 查询佣金记录列表 +export const getBrokerageRecordPage = async (params: any) => { + return await request.get({ url: `/trade/brokerage-record/page`, params }) +} + +// 查询佣金记录详情 +export const getBrokerageRecord = async (id: number) => { + return await request.get({ url: `/trade/brokerage-record/get?id=` + id }) +} diff --git a/src/api/mall/trade/brokerage/user/index.ts b/src/api/mall/trade/brokerage/user/index.ts new file mode 100644 index 0000000..8ed6977 --- /dev/null +++ b/src/api/mall/trade/brokerage/user/index.ts @@ -0,0 +1,44 @@ +import request from '@/config/axios' + +export interface BrokerageUserVO { + id: number + bindUserId: number + bindUserTime: Date + brokerageEnabled: boolean + brokerageTime: Date + price: number + frozenPrice: number + + nickname: string + avatar: string +} + +// 创建分销用户 +export const createBrokerageUser = (data: any) => { + return request.post({ url: '/trade/brokerage-user/create', data }) +} + +// 查询分销用户列表 +export const getBrokerageUserPage = async (params: any) => { + return await request.get({ url: `/trade/brokerage-user/page`, params }) +} + +// 查询分销用户详情 +export const getBrokerageUser = async (id: number) => { + return await request.get({ url: `/trade/brokerage-user/get?id=` + id }) +} + +// 修改推广员 +export const updateBindUser = async (data: any) => { + return await request.put({ url: `/trade/brokerage-user/update-bind-user`, data }) +} + +// 清除推广员 +export const clearBindUser = async (data: any) => { + return await request.put({ url: `/trade/brokerage-user/clear-bind-user`, data }) +} + +// 修改推广资格 +export const updateBrokerageEnabled = async (data: any) => { + return await request.put({ url: `/trade/brokerage-user/update-brokerage-enable`, data }) +} diff --git a/src/api/mall/trade/brokerage/withdraw/index.ts b/src/api/mall/trade/brokerage/withdraw/index.ts new file mode 100644 index 0000000..c93286a --- /dev/null +++ b/src/api/mall/trade/brokerage/withdraw/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +export interface BrokerageWithdrawVO { + id: number + userId: number + price: number + feePrice: number + totalPrice: number + type: number + name: string + accountNo: string + bankName: string + bankAddress: string + accountQrCodeUrl: string + status: number + auditReason: string + auditTime: Date + remark: string +} + +// 查询佣金提现列表 +export const getBrokerageWithdrawPage = async (params: any) => { + return await request.get({ url: `/trade/brokerage-withdraw/page`, params }) +} + +// 查询佣金提现详情 +export const getBrokerageWithdraw = async (id: number) => { + return await request.get({ url: `/trade/brokerage-withdraw/get?id=` + id }) +} + +// 佣金提现 - 通过申请 +export const approveBrokerageWithdraw = async (id: number) => { + return await request.put({ url: `/trade/brokerage-withdraw/approve?id=` + id }) +} + +// 审核佣金提现 - 驳回申请 +export const rejectBrokerageWithdraw = async (data: BrokerageWithdrawVO) => { + return await request.put({ url: `/trade/brokerage-withdraw/reject`, data }) +} diff --git a/src/api/mall/trade/config/index.ts b/src/api/mall/trade/config/index.ts new file mode 100644 index 0000000..43fdbdf --- /dev/null +++ b/src/api/mall/trade/config/index.ts @@ -0,0 +1,23 @@ +import request from '@/config/axios' + +export interface ConfigVO { + brokerageEnabled: boolean + brokerageEnabledCondition: number + brokerageBindMode: number + brokeragePosterUrls: string + brokerageFirstPercent: number + brokerageSecondPercent: number + brokerageWithdrawMinPrice: number + brokerageFrozenDays: number + brokerageWithdrawTypes: string +} + +// 查询交易中心配置详情 +export const getTradeConfig = async () => { + return await request.get({ url: `/trade/config/get` }) +} + +// 保存交易中心配置 +export const saveTradeConfig = async (data: ConfigVO) => { + return await request.put({ url: `/trade/config/save`, data }) +} diff --git a/src/api/mall/trade/delivery/express/index.ts b/src/api/mall/trade/delivery/express/index.ts new file mode 100644 index 0000000..0070bcd --- /dev/null +++ b/src/api/mall/trade/delivery/express/index.ts @@ -0,0 +1,45 @@ +import request from '@/config/axios' + +export interface DeliveryExpressVO { + id: number + code: string + name: string + logo: string + sort: number + status: number +} + +// 查询快递公司列表 +export const getDeliveryExpressPage = async (params: PageParam) => { + return await request.get({ url: '/trade/delivery/express/page', params }) +} + +// 查询快递公司详情 +export const getDeliveryExpress = async (id: number) => { + return await request.get({ url: '/trade/delivery/express/get?id=' + id }) +} + +// 获得快递公司精简信息列表 +export const getSimpleDeliveryExpressList = () => { + return request.get({ url: '/trade/delivery/express/list-all-simple' }) +} + +// 新增快递公司 +export const createDeliveryExpress = async (data: DeliveryExpressVO) => { + return await request.post({ url: '/trade/delivery/express/create', data }) +} + +// 修改快递公司 +export const updateDeliveryExpress = async (data: DeliveryExpressVO) => { + return await request.put({ url: '/trade/delivery/express/update', data }) +} + +// 删除快递公司 +export const deleteDeliveryExpress = async (id: number) => { + return await request.delete({ url: '/trade/delivery/express/delete?id=' + id }) +} + +// 导出快递公司 Excel +export const exportDeliveryExpressApi = async (params) => { + return await request.download({ url: '/trade/delivery/express/export-excel', params }) +} diff --git a/src/api/mall/trade/delivery/expressTemplate/index.ts b/src/api/mall/trade/delivery/expressTemplate/index.ts new file mode 100644 index 0000000..9ed23bc --- /dev/null +++ b/src/api/mall/trade/delivery/expressTemplate/index.ts @@ -0,0 +1,54 @@ +import request from '@/config/axios' + +export interface DeliveryExpressTemplateVO { + id: number + name: string + chargeMode: number + sort: number + templateCharge: ExpressTemplateChargeVO[] + templateFree: ExpressTemplateFreeVO[] +} + +export declare type ExpressTemplateChargeVO = { + areaIds: number[] + startCount: number + startPrice: number + extraCount: number + extraPrice: number +} + +export declare type ExpressTemplateFreeVO = { + areaIds: number[] + freeCount: number + freePrice: number +} + +// 查询快递运费模板列表 +export const getDeliveryExpressTemplatePage = async (params: PageParam) => { + return await request.get({ url: '/trade/delivery/express-template/page', params }) +} + +// 查询快递运费模板详情 +export const getDeliveryExpressTemplate = async (id: number) => { + return await request.get({ url: '/trade/delivery/express-template/get?id=' + id }) +} + +// 查询快递运费模板详情 +export const getSimpleTemplateList = async () => { + return await request.get({ url: '/trade/delivery/express-template/list-all-simple' }) +} + +// 新增快递运费模板 +export const createDeliveryExpressTemplate = async (data: DeliveryExpressTemplateVO) => { + return await request.post({ url: '/trade/delivery/express-template/create', data }) +} + +// 修改快递运费模板 +export const updateDeliveryExpressTemplate = async (data: DeliveryExpressTemplateVO) => { + return await request.put({ url: '/trade/delivery/express-template/update', data }) +} + +// 删除快递运费模板 +export const deleteDeliveryExpressTemplate = async (id: number) => { + return await request.delete({ url: '/trade/delivery/express-template/delete?id=' + id }) +} diff --git a/src/api/mall/trade/delivery/pickUpStore/index.ts b/src/api/mall/trade/delivery/pickUpStore/index.ts new file mode 100644 index 0000000..ea6c852 --- /dev/null +++ b/src/api/mall/trade/delivery/pickUpStore/index.ts @@ -0,0 +1,52 @@ +import request from '@/config/axios' + +export interface DeliveryPickUpStoreVO { + id: number + name: string + introduction: string + phone: string + areaId: number + detailAddress: string + logo: string + openingTime: string + closingTime: string + latitude: number + longitude: number + status: number + verifyUserIds: number[] // 绑定用户编号组数 +} + +// 查询自提门店列表 +export const getDeliveryPickUpStorePage = async (params: any) => { + return await request.get({ url: '/trade/delivery/pick-up-store/page', params }) +} + +// 查询自提门店详情 +export const getDeliveryPickUpStore = async (id: number) => { + return await request.get({ url: '/trade/delivery/pick-up-store/get?id=' + id }) +} + +// 查询自提门店精简列表 +export const getSimpleDeliveryPickUpStoreList = async (): Promise => { + return await request.get({ url: '/trade/delivery/pick-up-store/simple-list' }) +} + +// 新增自提门店 +export const createDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) => { + return await request.post({ url: '/trade/delivery/pick-up-store/create', data }) +} + +// 修改自提门店 +export const updateDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) => { + return await request.put({ url: '/trade/delivery/pick-up-store/update', data }) +} + +// 删除自提门店 +export const deleteDeliveryPickUpStore = async (id: number) => { + return await request.delete({ url: '/trade/delivery/pick-up-store/delete?id=' + id }) +} + +// 绑定自提店员 +export const bindStoreStaffId = async (data: any) => { + return await request.post({ url: '/trade/delivery/pick-up-store/bind', data }) +} diff --git a/src/api/mall/trade/order/index.ts b/src/api/mall/trade/order/index.ts new file mode 100644 index 0000000..37fee8c --- /dev/null +++ b/src/api/mall/trade/order/index.ts @@ -0,0 +1,188 @@ +import request from '@/config/axios' + +export interface OrderVO { + // ========== 订单基本信息 ========== + id?: number | null // 订单编号 + no?: string // 订单流水号 + createTime?: Date | null // 下单时间 + type?: number | null // 订单类型 + terminal?: number | null // 订单来源 + userId?: number | null // 用户编号 + userIp?: string // 用户 IP + userRemark?: string // 用户备注 + status?: number | null // 订单状态 + productCount?: number | null // 购买的商品数量 + finishTime?: Date | null // 订单完成时间 + cancelTime?: Date | null // 订单取消时间 + cancelType?: number | null // 取消类型 + remark?: string // 商家备注 + + // ========== 价格 + 支付基本信息 ========== + payOrderId?: number | null // 支付订单编号 + payStatus?: boolean // 是否已支付 + payTime?: Date | null // 付款时间 + payChannelCode?: string // 支付渠道 + totalPrice?: number | null // 商品原价(总) + discountPrice?: number | null // 订单优惠(总) + deliveryPrice?: number | null // 运费金额 + adjustPrice?: number | null // 订单调价(总) + payPrice?: number | null // 应付金额(总) + // ========== 收件 + 物流基本信息 ========== + deliveryType?: number | null // 发货方式 + pickUpStoreId?: number // 自提门店编号 + pickUpVerifyCode?: string // 自提核销码 + deliveryTemplateId?: number | null // 配送模板编号 + logisticsId?: number | null // 发货物流公司编号 + logisticsNo?: string // 发货物流单号 + deliveryTime?: Date | null // 发货时间 + receiveTime?: Date | null // 收货时间 + receiverName?: string // 收件人名称 + receiverMobile?: string // 收件人手机 + receiverPostCode?: number | null // 收件人邮编 + receiverAreaId?: number | null // 收件人地区编号 + receiverAreaName?: string //收件人地区名字 + receiverDetailAddress?: string // 收件人详细地址 + + // ========== 售后基本信息 ========== + afterSaleStatus?: number | null // 售后状态 + refundPrice?: number | null // 退款金额 + + // ========== 营销基本信息 ========== + couponId?: number | null // 优惠劵编号 + couponPrice?: number | null // 优惠劵减免金额 + pointPrice?: number | null // 积分抵扣的金额 + vipPrice?: number | null // VIP 减免金额 + + items?: OrderItemRespVO[] // 订单项列表 + // 下单用户信息 + user?: { + id?: number | null + nickname?: string + avatar?: string + } + // 推广用户信息 + brokerageUser?: { + id?: number | null + nickname?: string + avatar?: string + } + // 订单操作日志 + logs?: OrderLogRespVO[] +} + +export interface OrderLogRespVO { + content?: string + createTime?: Date + userType?: number +} + +export interface OrderItemRespVO { + // ========== 订单项基本信息 ========== + id?: number | null // 编号 + userId?: number | null // 用户编号 + orderId?: number | null // 订单编号 + // ========== 商品基本信息 ========== + spuId?: number | null // 商品 SPU 编号 + spuName?: string //商品 SPU 名称 + skuId?: number | null // 商品 SKU 编号 + picUrl?: string //商品图片 + count?: number | null //购买数量 + // ========== 价格 + 支付基本信息 ========== + originalPrice?: number | null //商品原价(总) + originalUnitPrice?: number | null //商品原价(单) + discountPrice?: number | null //商品优惠(总) + payPrice?: number | null //商品实付金额(总) + orderPartPrice?: number | null //子订单分摊金额(总) + orderDividePrice?: number | null //分摊后子订单实付金额(总) + // ========== 营销基本信息 ========== + // TODO 芋艿:在捉摸一下 + // ========== 售后基本信息 ========== + afterSaleStatus?: number | null // 售后状态 + properties?: ProductPropertiesVO[] //属性数组 +} + +export interface ProductPropertiesVO { + propertyId?: number | null // 属性的编号 + propertyName?: string // 属性的名称 + valueId?: number | null //属性值的编号 + valueName?: string // 属性值的名称 +} + +/** 交易订单统计 */ +export interface TradeOrderSummaryRespVO { + /** 订单数量 */ + orderCount?: number + /** 订单金额 */ + orderPayPrice?: string + /** 退款单数 */ + afterSaleCount?: number + /** 退款金额 */ + afterSalePrice?: string +} + +// 查询交易订单列表 +export const getOrderPage = async (params: any) => { + return await request.get({ url: `/trade/order/page`, params }) +} + +// 查询交易订单统计 +export const getOrderSummary = async (params: any) => { + return await request.get({ url: `/trade/order/summary`, params }) +} + +// 查询交易订单详情 +export const getOrder = async (id: number | null) => { + return await request.get({ url: `/trade/order/get-detail?id=` + id }) +} + +// 查询交易订单物流详情 +export const getExpressTrackList = async (id: number | null) => { + return await request.get({ url: `/trade/order/get-express-track-list?id=` + id }) +} + +export interface DeliveryVO { + id?: number // 订单编号 + logisticsId: number | null // 物流公司编号 + logisticsNo: string // 物流编号 +} + +// 订单发货 +export const deliveryOrder = async (data: DeliveryVO) => { + return await request.put({ url: `/trade/order/delivery`, data }) +} + +// 订单备注 +export const updateOrderRemark = async (data: any) => { + return await request.put({ url: `/trade/order/update-remark`, data }) +} + +// 订单调价 +export const updateOrderPrice = async (data: any) => { + return await request.put({ url: `/trade/order/update-price`, data }) +} + +// 修改订单地址 +export const updateOrderAddress = async (data: any) => { + return await request.put({ url: `/trade/order/update-address`, data }) +} + +// 订单核销 +export const pickUpOrder = async (id: number) => { + return await request.put({ url: `/trade/order/pick-up-by-id?id=${id}` }) +} + +// 订单核销 +export const pickUpOrderByVerifyCode = async (pickUpVerifyCode: string) => { + return await request.put({ + url: `/trade/order/pick-up-by-verify-code`, + params: { pickUpVerifyCode } + }) +} + +// 查询核销码对应的订单 +export const getOrderByPickUpVerifyCode = async (pickUpVerifyCode: string) => { + return await request.get({ + url: `/trade/order/get-by-pick-up-verify-code`, + params: { pickUpVerifyCode } + }) +} diff --git a/src/api/member/address/index.ts b/src/api/member/address/index.ts new file mode 100644 index 0000000..a914f97 --- /dev/null +++ b/src/api/member/address/index.ts @@ -0,0 +1,15 @@ +import request from '@/config/axios' + +export interface AddressVO { + id: number + name: string + mobile: string + areaId: number + detailAddress: string + defaultStatus: boolean +} + +// 查询用户收件地址列表 +export const getAddressList = async (params) => { + return await request.get({ url: `/member/address/list`, params }) +} diff --git a/src/api/member/config/index.ts b/src/api/member/config/index.ts new file mode 100644 index 0000000..7ddca16 --- /dev/null +++ b/src/api/member/config/index.ts @@ -0,0 +1,19 @@ +import request from '@/config/axios' + +export interface ConfigVO { + id: number + pointTradeDeductEnable: number + pointTradeDeductUnitPrice: number + pointTradeDeductMaxPrice: number + pointTradeGivePoint: number +} + +// 查询积分设置详情 +export const getConfig = async () => { + return await request.get({ url: `/member/config/get` }) +} + +// 新增修改积分设置 +export const saveConfig = async (data: ConfigVO) => { + return await request.put({ url: `/member/config/save`, data }) +} diff --git a/src/api/member/experience-record/index.ts b/src/api/member/experience-record/index.ts new file mode 100644 index 0000000..6d40a48 --- /dev/null +++ b/src/api/member/experience-record/index.ts @@ -0,0 +1,22 @@ +import request from '@/config/axios' + +export interface ExperienceRecordVO { + id: number + userId: number + bizId: string + bizType: number + title: string + description: string + experience: number + totalExperience: number +} + +// 查询会员经验记录列表 +export const getExperienceRecordPage = async (params) => { + return await request.get({ url: `/member/experience-record/page`, params }) +} + +// 查询会员经验记录详情 +export const getExperienceRecord = async (id: number) => { + return await request.get({ url: `/member/experience-record/get?id=` + id }) +} diff --git a/src/api/member/group/index.ts b/src/api/member/group/index.ts new file mode 100644 index 0000000..df3054e --- /dev/null +++ b/src/api/member/group/index.ts @@ -0,0 +1,38 @@ +import request from '@/config/axios' + +export interface GroupVO { + id: number + name: string + remark: string + status: number +} + +// 查询用户分组列表 +export const getGroupPage = async (params: any) => { + return await request.get({ url: `/member/group/page`, params }) +} + +// 查询用户分组详情 +export const getGroup = async (id: number) => { + return await request.get({ url: `/member/group/get?id=` + id }) +} + +// 新增用户分组 +export const createGroup = async (data: GroupVO) => { + return await request.post({ url: `/member/group/create`, data }) +} + +// 查询用户分组 - 精简信息列表 +export const getSimpleGroupList = async () => { + return await request.get({ url: `/member/group/list-all-simple` }) +} + +// 修改用户分组 +export const updateGroup = async (data: GroupVO) => { + return await request.put({ url: `/member/group/update`, data }) +} + +// 删除用户分组 +export const deleteGroup = async (id: number) => { + return await request.delete({ url: `/member/group/delete?id=` + id }) +} diff --git a/src/api/member/level/index.ts b/src/api/member/level/index.ts new file mode 100644 index 0000000..0ded493 --- /dev/null +++ b/src/api/member/level/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface LevelVO { + id: number + name: string + experience: number + value: number + discountPercent: number + icon: string + bgUrl: string + status: number +} + +// 查询会员等级列表 +export const getLevelList = async (params) => { + return await request.get({ url: `/member/level/list`, params }) +} + +// 查询会员等级详情 +export const getLevel = async (id: number) => { + return await request.get({ url: `/member/level/get?id=` + id }) +} + +// 查询会员等级 - 精简信息列表 +export const getSimpleLevelList = async () => { + return await request.get({ url: `/member/level/list-all-simple` }) +} + +// 新增会员等级 +export const createLevel = async (data: LevelVO) => { + return await request.post({ url: `/member/level/create`, data }) +} + +// 修改会员等级 +export const updateLevel = async (data: LevelVO) => { + return await request.put({ url: `/member/level/update`, data }) +} + +// 删除会员等级 +export const deleteLevel = async (id: number) => { + return await request.delete({ url: `/member/level/delete?id=` + id }) +} diff --git a/src/api/member/point/record/index.ts b/src/api/member/point/record/index.ts new file mode 100644 index 0000000..f47ae46 --- /dev/null +++ b/src/api/member/point/record/index.ts @@ -0,0 +1,18 @@ +import request from '@/config/axios' + +export interface RecordVO { + id: number + bizId: string + bizType: string + title: string + description: string + point: number + totalPoint: number + userId: number + createDate: Date +} + +// 查询用户积分记录列表 +export const getRecordPage = async (params) => { + return await request.get({ url: `/member/point/record/page`, params }) +} diff --git a/src/api/member/signin/config/index.ts b/src/api/member/signin/config/index.ts new file mode 100644 index 0000000..50a7d63 --- /dev/null +++ b/src/api/member/signin/config/index.ts @@ -0,0 +1,34 @@ +import request from '@/config/axios' + +export interface SignInConfigVO { + id?: number + day?: number + point?: number + experience?: number + status?: number +} + +// 查询积分签到规则列表 +export const getSignInConfigList = async () => { + return await request.get({ url: `/member/sign-in/config/list` }) +} + +// 查询积分签到规则详情 +export const getSignInConfig = async (id: number) => { + return await request.get({ url: `/member/sign-in/config/get?id=` + id }) +} + +// 新增积分签到规则 +export const createSignInConfig = async (data: SignInConfigVO) => { + return await request.post({ url: `/member/sign-in/config/create`, data }) +} + +// 修改积分签到规则 +export const updateSignInConfig = async (data: SignInConfigVO) => { + return await request.put({ url: `/member/sign-in/config/update`, data }) +} + +// 删除积分签到规则 +export const deleteSignInConfig = async (id: number) => { + return await request.delete({ url: `/member/sign-in/config/delete?id=` + id }) +} diff --git a/src/api/member/signin/record/index.ts b/src/api/member/signin/record/index.ts new file mode 100644 index 0000000..7d13702 --- /dev/null +++ b/src/api/member/signin/record/index.ts @@ -0,0 +1,13 @@ +import request from '@/config/axios' + +export interface SignInRecordVO { + id: number + userId: number + day: number + point: number +} + +// 查询用户签到积分列表 +export const getSignInRecordPage = async (params) => { + return await request.get({ url: `/member/sign-in/record/page`, params }) +} diff --git a/src/api/member/tag/index.ts b/src/api/member/tag/index.ts new file mode 100644 index 0000000..7ff6e9b --- /dev/null +++ b/src/api/member/tag/index.ts @@ -0,0 +1,36 @@ +import request from '@/config/axios' + +export interface TagVO { + id: number + name: string +} + +// 查询会员标签列表 +export const getMemberTagPage = async (params: any) => { + return await request.get({ url: `/member/tag/page`, params }) +} + +// 查询会员标签详情 +export const getMemberTag = async (id: number) => { + return await request.get({ url: `/member/tag/get?id=` + id }) +} + +// 查询会员标签 - 精简信息列表 +export const getSimpleTagList = async () => { + return await request.get({ url: `/member/tag/list-all-simple` }) +} + +// 新增会员标签 +export const createMemberTag = async (data: TagVO) => { + return await request.post({ url: `/member/tag/create`, data }) +} + +// 修改会员标签 +export const updateMemberTag = async (data: TagVO) => { + return await request.put({ url: `/member/tag/update`, data }) +} + +// 删除会员标签 +export const deleteMemberTag = async (id: number) => { + return await request.delete({ url: `/member/tag/delete?id=` + id }) +} diff --git a/src/api/member/user/index.ts b/src/api/member/user/index.ts new file mode 100644 index 0000000..1f8acf4 --- /dev/null +++ b/src/api/member/user/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +export interface UserVO { + id: number + avatar: string | undefined + birthday: number | undefined + createTime: number | undefined + loginDate: number | undefined + loginIp: string + mark: string + mobile: string + name: string | undefined + nickname: string | undefined + registerIp: string + sex: number + status: number + areaId: number | undefined + areaName: string | undefined + levelName: string | null + point: number | undefined | null + totalPoint: number | undefined | null + experience: number | null | undefined +} + +// 查询会员用户列表 +export const getUserPage = async (params) => { + return await request.get({ url: `/member/user/page`, params }) +} + +// 查询会员用户详情 +export const getUser = async (id: number) => { + return await request.get({ url: `/member/user/get?id=` + id }) +} + +// 修改会员用户 +export const updateUser = async (data: UserVO) => { + return await request.put({ url: `/member/user/update`, data }) +} + +// 修改会员用户等级 +export const updateUserLevel = async (data: any) => { + return await request.put({ url: `/member/user/update-level`, data }) +} + +// 修改会员用户积分 +export const updateUserPoint = async (data: any) => { + return await request.put({ url: `/member/user/update-point`, data }) +} diff --git a/src/api/mp/account/index.ts b/src/api/mp/account/index.ts new file mode 100644 index 0000000..e973cda --- /dev/null +++ b/src/api/mp/account/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +export interface AccountVO { + id: number + name: string +} + +// 创建公众号账号 +export const createAccount = async (data) => { + return await request.post({ url: '/mp/account/create', data }) +} + +// 更新公众号账号 +export const updateAccount = async (data) => { + return request.put({ url: '/mp/account/update', data: data }) +} + +// 删除公众号账号 +export const deleteAccount = async (id) => { + return request.delete({ url: '/mp/account/delete?id=' + id, method: 'delete' }) +} + +// 获得公众号账号 +export const getAccount = async (id) => { + return request.get({ url: '/mp/account/get?id=' + id }) +} + +// 获得公众号账号分页 +export const getAccountPage = async (query) => { + return request.get({ url: '/mp/account/page', params: query }) +} + +// 获取公众号账号精简信息列表 +export const getSimpleAccountList = async () => { + return request.get({ url: '/mp/account/list-all-simple' }) +} + +// 生成公众号二维码 +export const generateAccountQrCode = async (id) => { + return request.put({ url: '/mp/account/generate-qr-code?id=' + id }) +} + +// 清空公众号 API 配额 +export const clearAccountQuota = async (id) => { + return request.put({ url: '/mp/account/clear-quota?id=' + id }) +} diff --git a/src/api/mp/autoReply/index.ts b/src/api/mp/autoReply/index.ts new file mode 100644 index 0000000..5045e6d --- /dev/null +++ b/src/api/mp/autoReply/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +// 创建公众号的自动回复 +export const createAutoReply = (data) => { + return request.post({ + url: '/mp/auto-reply/create', + data: data + }) +} + +// 更新公众号的自动回复 +export const updateAutoReply = (data) => { + return request.put({ + url: '/mp/auto-reply/update', + data: data + }) +} + +// 删除公众号的自动回复 +export const deleteAutoReply = (id) => { + return request.delete({ + url: '/mp/auto-reply/delete?id=' + id + }) +} + +// 获得公众号的自动回复 +export const getAutoReply = (id) => { + return request.get({ + url: '/mp/auto-reply/get?id=' + id + }) +} + +// 获得公众号的自动回复分页 +export const getAutoReplyPage = (query) => { + return request.get({ + url: '/mp/auto-reply/page', + params: query + }) +} diff --git a/src/api/mp/draft/index.ts b/src/api/mp/draft/index.ts new file mode 100644 index 0000000..ce6a443 --- /dev/null +++ b/src/api/mp/draft/index.ts @@ -0,0 +1,35 @@ +import request from '@/config/axios' + +// 获得公众号草稿分页 +export const getDraftPage = (query) => { + return request.get({ + url: '/mp/draft/page', + params: query + }) +} + +// 创建公众号草稿 +export const createDraft = (accountId, articles) => { + return request.post({ + url: '/mp/draft/create?accountId=' + accountId, + data: { + articles + } + }) +} + +// 更新公众号草稿 +export const updateDraft = (accountId, mediaId, articles) => { + return request.put({ + url: '/mp/draft/update?accountId=' + accountId + '&mediaId=' + mediaId, + method: 'put', + data: articles + }) +} + +// 删除公众号草稿 +export const deleteDraft = (accountId, mediaId) => { + return request.delete({ + url: '/mp/draft/delete?accountId=' + accountId + '&mediaId=' + mediaId + }) +} diff --git a/src/api/mp/freePublish/index.ts b/src/api/mp/freePublish/index.ts new file mode 100644 index 0000000..beef026 --- /dev/null +++ b/src/api/mp/freePublish/index.ts @@ -0,0 +1,23 @@ +import request from '@/config/axios' + +// 获得公众号素材分页 +export const getFreePublishPage = (query) => { + return request.get({ + url: '/mp/free-publish/page', + params: query + }) +} + +// 删除公众号素材 +export const deleteFreePublish = (accountId, articleId) => { + return request.delete({ + url: '/mp/free-publish/delete?accountId=' + accountId + '&articleId=' + articleId + }) +} + +// 发布公众号素材 +export const submitFreePublish = (accountId, mediaId) => { + return request.post({ + url: '/mp/free-publish/submit?accountId=' + accountId + '&mediaId=' + mediaId + }) +} diff --git a/src/api/mp/material/index.ts b/src/api/mp/material/index.ts new file mode 100644 index 0000000..fcc37ab --- /dev/null +++ b/src/api/mp/material/index.ts @@ -0,0 +1,16 @@ +import request from '@/config/axios' + +// 获得公众号素材分页 +export const getMaterialPage = (query) => { + return request.get({ + url: '/mp/material/page', + params: query + }) +} + +// 删除公众号永久素材 +export const deletePermanentMaterial = (id) => { + return request.delete({ + url: '/mp/material/delete-permanent?id=' + id + }) +} diff --git a/src/api/mp/menu/index.ts b/src/api/mp/menu/index.ts new file mode 100644 index 0000000..cc78647 --- /dev/null +++ b/src/api/mp/menu/index.ts @@ -0,0 +1,26 @@ +import request from '@/config/axios' + +// 获得公众号菜单列表 +export const getMenuList = (accountId) => { + return request.get({ + url: '/mp/menu/list?accountId=' + accountId + }) +} + +// 保存公众号菜单 +export const saveMenu = (accountId, menus) => { + return request.post({ + url: '/mp/menu/save', + data: { + accountId, + menus + } + }) +} + +// 删除公众号菜单 +export const deleteMenu = (accountId) => { + return request.delete({ + url: '/mp/menu/delete?accountId=' + accountId + }) +} diff --git a/src/api/mp/message/index.ts b/src/api/mp/message/index.ts new file mode 100644 index 0000000..ad9b95d --- /dev/null +++ b/src/api/mp/message/index.ts @@ -0,0 +1,17 @@ +import request from '@/config/axios' + +// 获得公众号消息分页 +export const getMessagePage = (query: PageParam) => { + return request.get({ + url: '/mp/message/page', + params: query + }) +} + +// 给粉丝发送消息 +export const sendMessage = (data) => { + return request.post({ + url: '/mp/message/send', + data: data + }) +} diff --git a/src/api/mp/statistics/index.ts b/src/api/mp/statistics/index.ts new file mode 100644 index 0000000..72cae60 --- /dev/null +++ b/src/api/mp/statistics/index.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +// 获取消息发送概况数据 +export const getUpstreamMessage = (query) => { + return request.get({ + url: '/mp/statistics/upstream-message', + params: query + }) +} + +// 用户增减数据 +export const getUserSummary = (query) => { + return request.get({ + url: '/mp/statistics/user-summary', + params: query + }) +} + +// 获得用户累计数据 +export const getUserCumulate = (query) => { + return request.get({ + url: '/mp/statistics/user-cumulate', + params: query + }) +} + +// 获得接口分析数据 +export const getInterfaceSummary = (query) => { + return request.get({ + url: '/mp/statistics/interface-summary', + params: query + }) +} diff --git a/src/api/mp/tag/index.ts b/src/api/mp/tag/index.ts new file mode 100644 index 0000000..50183a5 --- /dev/null +++ b/src/api/mp/tag/index.ts @@ -0,0 +1,60 @@ +import request from '@/config/axios' + +export interface TagVO { + id?: number + name: string + accountId: number + createTime: Date +} + +// 创建公众号标签 +export const createTag = (data: TagVO) => { + return request.post({ + url: '/mp/tag/create', + data: data + }) +} + +// 更新公众号标签 +export const updateTag = (data: TagVO) => { + return request.put({ + url: '/mp/tag/update', + data: data + }) +} + +// 删除公众号标签 +export const deleteTag = (id: number) => { + return request.delete({ + url: '/mp/tag/delete?id=' + id + }) +} + +// 获得公众号标签 +export const getTag = (id: number) => { + return request.get({ + url: '/mp/tag/get?id=' + id + }) +} + +// 获得公众号标签分页 +export const getTagPage = (query: PageParam) => { + return request.get({ + url: '/mp/tag/page', + params: query + }) +} + +// 获取公众号标签精简信息列表 +export const getSimpleTagList = () => { + return request.get({ + url: '/mp/tag/list-all-simple' + }) +} + +// 同步公众号标签 +export const syncTag = (accountId: number) => { + return request.post({ + url: '/mp/tag/sync?accountId=' + accountId + }) +} diff --git a/src/api/mp/user/index.ts b/src/api/mp/user/index.ts new file mode 100644 index 0000000..b89acc7 --- /dev/null +++ b/src/api/mp/user/index.ts @@ -0,0 +1,31 @@ +import request from '@/config/axios' + +// 更新公众号粉丝 +export const updateUser = (data) => { + return request.put({ + url: '/mp/user/update', + data: data + }) +} + +// 获得公众号粉丝 +export const getUser = (id) => { + return request.get({ + url: '/mp/user/get?id=' + id + }) +} + +// 获得公众号粉丝分页 +export const getUserPage = (query) => { + return request.get({ + url: '/mp/user/page', + params: query + }) +} + +// 同步公众号粉丝 +export const syncUser = (accountId) => { + return request.post({ + url: '/mp/user/sync?accountId=' + accountId + }) +} diff --git a/src/api/pay/app/index.ts b/src/api/pay/app/index.ts new file mode 100644 index 0000000..d6fa83c --- /dev/null +++ b/src/api/pay/app/index.ts @@ -0,0 +1,68 @@ +import request from '@/config/axios' + +export interface AppVO { + id: number + appKey: string + name: string + status: number + remark: string + payNotifyUrl: string + refundNotifyUrl: string + transferNotifyUrl: string + merchantId: number + merchantName: string + createTime: Date +} + +export interface AppPageReqVO extends PageParam { + name?: string + status?: number + remark?: string + payNotifyUrl?: string + refundNotifyUrl?: string + transferNotifyUrl?: string + merchantName?: string + createTime?: Date[] +} + +export interface AppUpdateStatusReqVO { + id: number + status: number +} + +// 查询列表支付应用 +export const getAppPage = (params: AppPageReqVO) => { + return request.get({ url: '/pay/app/page', params }) +} + +// 查询详情支付应用 +export const getApp = (id: number) => { + return request.get({ url: '/pay/app/get?id=' + id }) +} + +// 新增支付应用 +export const createApp = (data: AppVO) => { + return request.post({ url: '/pay/app/create', data }) +} + +// 修改支付应用 +export const updateApp = (data: AppVO) => { + return request.put({ url: '/pay/app/update', data }) +} + +// 支付应用信息状态修改 +export const changeAppStatus = (data: AppUpdateStatusReqVO) => { + return request.put({ url: '/pay/app/update-status', data: data }) +} + +// 删除支付应用 +export const deleteApp = (id: number) => { + return request.delete({ url: '/pay/app/delete?id=' + id }) +} + +// 获得支付应用列表 +export const getAppList = () => { + return request.get({ + url: '/pay/app/list' + }) +} diff --git a/src/api/pay/channel/index.ts b/src/api/pay/channel/index.ts new file mode 100644 index 0000000..0f4ff42 --- /dev/null +++ b/src/api/pay/channel/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +export interface ChannelVO { + id: number + code: string + config: string + status: number + remark: string + feeRate: number + appId: number + createTime: Date +} + +// 查询列表支付渠道 +export const getChannelPage = (params: PageParam) => { + return request.get({ url: '/pay/channel/page', params }) +} + +// 查询详情支付渠道 +export const getChannel = (appId: string, code: string) => { + const params = { + appId: appId, + code: code + } + return request.get({ url: '/pay/channel/get', params: params }) +} + +// 新增支付渠道 +export const createChannel = (data: ChannelVO) => { + return request.post({ url: '/pay/channel/create', data }) +} + +// 修改支付渠道 +export const updateChannel = (data: ChannelVO) => { + return request.put({ url: '/pay/channel/update', data }) +} + +// 删除支付渠道 +export const deleteChannel = (id: number) => { + return request.delete({ url: '/pay/channel/delete?id=' + id }) +} + +// 导出支付渠道 +export const exportChannel = (params) => { + return request.download({ url: '/pay/channel/export-excel', params }) +} diff --git a/src/api/pay/demo/index.ts b/src/api/pay/demo/index.ts new file mode 100644 index 0000000..3824a8b --- /dev/null +++ b/src/api/pay/demo/index.ts @@ -0,0 +1,36 @@ +import request from '@/config/axios' + +export interface DemoOrderVO { + spuId: number + createTime: Date +} + +// 创建示例订单 +export function createDemoOrder(data: DemoOrderVO) { + return request.post({ + url: '/pay/demo-order/create', + data: data + }) +} + +// 获得示例订单 +export function getDemoOrder(id: number) { + return request.get({ + url: '/pay/demo-order/get?id=' + id + }) +} + +// 获得示例订单分页 +export function getDemoOrderPage(query: PageParam) { + return request.get({ + url: '/pay/demo-order/page', + params: query + }) +} + +// 退款示例订单 +export function refundDemoOrder(id) { + return request.put({ + url: '/pay/demo-order/refund?id=' + id + }) +} diff --git a/src/api/pay/demo/transfer/index.ts b/src/api/pay/demo/transfer/index.ts new file mode 100644 index 0000000..a95b0d5 --- /dev/null +++ b/src/api/pay/demo/transfer/index.ts @@ -0,0 +1,25 @@ +import request from '@/config/axios' + +export interface DemoTransferVO { + price: number + type: number + userName: string + alipayLogonId: string + openid: string +} + +// 创建示例转账单 +export function createDemoTransfer(data: DemoTransferVO) { + return request.post({ + url: '/pay/demo-transfer/create', + data: data + }) +} + +// 获得示例订单分页 +export function getDemoTransferPage(query: PageParam) { + return request.get({ + url: '/pay/demo-transfer/page', + params: query + }) +} diff --git a/src/api/pay/notify/index.ts b/src/api/pay/notify/index.ts new file mode 100644 index 0000000..dc8bd88 --- /dev/null +++ b/src/api/pay/notify/index.ts @@ -0,0 +1,16 @@ +import request from '@/config/axios' + +// 获得支付通知明细 +export const getNotifyTaskDetail = (id) => { + return request.get({ + url: '/pay/notify/get-detail?id=' + id + }) +} + +// 获得支付通知分页 +export const getNotifyTaskPage = (query) => { + return request.get({ + url: '/pay/notify/page', + params: query + }) +} diff --git a/src/api/pay/order/index.ts b/src/api/pay/order/index.ts new file mode 100644 index 0000000..6460c4d --- /dev/null +++ b/src/api/pay/order/index.ts @@ -0,0 +1,110 @@ +import request from '@/config/axios' + +export interface OrderVO { + id: number + merchantId: number + appId: number + channelId: number + channelCode: string + merchantOrderId: string + subject: string + body: string + notifyUrl: string + notifyStatus: number + amount: number + channelFeeRate: number + channelFeeAmount: number + status: number + userIp: string + expireTime: Date + successTime: Date + notifyTime: Date + successExtensionId: number + refundStatus: number + refundTimes: number + refundAmount: number + channelUserId: string + channelOrderNo: string + createTime: Date +} + +export interface OrderPageReqVO extends PageParam { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + merchantOrderId?: string + subject?: string + body?: string + notifyUrl?: string + notifyStatus?: number + amount?: number + channelFeeRate?: number + channelFeeAmount?: number + status?: number + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + successExtensionId?: number + refundStatus?: number + refundTimes?: number + channelUserId?: string + channelOrderNo?: string + createTime?: Date[] +} + +export interface OrderExportReqVO { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + merchantOrderId?: string + subject?: string + body?: string + notifyUrl?: string + notifyStatus?: number + amount?: number + channelFeeRate?: number + channelFeeAmount?: number + status?: number + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + successExtensionId?: number + refundStatus?: number + refundTimes?: number + channelUserId?: string + channelOrderNo?: string + createTime?: Date[] +} + +// 查询列表支付订单 +export const getOrderPage = async (params: OrderPageReqVO) => { + return await request.get({ url: '/pay/order/page', params }) +} + +// 查询详情支付订单 +export const getOrder = async (id: number, sync?: boolean) => { + return await request.get({ + url: '/pay/order/get', + params: { + id, + sync + } + }) +} + +// 获得支付订单的明细 +export const getOrderDetail = async (id: number) => { + return await request.get({ url: '/pay/order/get-detail?id=' + id }) +} + +// 提交支付订单 +export const submitOrder = async (data: any) => { + return await request.post({ url: '/pay/order/submit', data }) +} + +// 导出支付订单 +export const exportOrder = async (params: OrderExportReqVO) => { + return await request.download({ url: '/pay/order/export-excel', params }) +} diff --git a/src/api/pay/refund/index.ts b/src/api/pay/refund/index.ts new file mode 100644 index 0000000..4b587f2 --- /dev/null +++ b/src/api/pay/refund/index.ts @@ -0,0 +1,116 @@ +import request from '@/config/axios' + +export interface RefundVO { + id: number + merchantId: number + appId: number + channelId: number + channelCode: string + orderId: string + tradeNo: string + merchantOrderId: string + merchantRefundNo: string + notifyUrl: string + notifyStatus: number + status: number + type: number + payAmount: number + refundAmount: number + reason: string + userIp: string + channelOrderNo: string + channelRefundNo: string + channelErrorCode: string + channelErrorMsg: string + channelExtras: string + expireTime: Date + successTime: Date + notifyTime: Date + createTime: Date +} + +export interface RefundPageReqVO extends PageParam { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + orderId?: string + tradeNo?: string + merchantOrderId?: string + merchantRefundNo?: string + notifyUrl?: string + notifyStatus?: number + status?: number + type?: number + payAmount?: number + refundAmount?: number + reason?: string + userIp?: string + channelOrderNo?: string + channelRefundNo?: string + channelErrorCode?: string + channelErrorMsg?: string + channelExtras?: string + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + createTime?: Date[] +} + +export interface PayRefundExportReqVO { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + orderId?: string + tradeNo?: string + merchantOrderId?: string + merchantRefundNo?: string + notifyUrl?: string + notifyStatus?: number + status?: number + type?: number + payAmount?: number + refundAmount?: number + reason?: string + userIp?: string + channelOrderNo?: string + channelRefundNo?: string + channelErrorCode?: string + channelErrorMsg?: string + channelExtras?: string + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + createTime?: Date[] +} + +// 查询列表退款订单 +export const getRefundPage = (params: RefundPageReqVO) => { + return request.get({ url: '/pay/refund/page', params }) +} + +// 查询详情退款订单 +export const getRefund = (id: number) => { + return request.get({ url: '/pay/refund/get?id=' + id }) +} + +// 新增退款订单 +export const createRefund = (data: RefundVO) => { + return request.post({ url: '/pay/refund/create', data }) +} + +// 修改退款订单 +export const updateRefund = (data: RefundVO) => { + return request.put({ url: '/pay/refund/update', data }) +} + +// 删除退款订单 +export const deleteRefund = (id: number) => { + return request.delete({ url: '/pay/refund/delete?id=' + id }) +} + +// 导出退款订单 +export const exportRefund = (params: PayRefundExportReqVO) => { + return request.download({ url: '/pay/refund/export-excel', params }) +} diff --git a/src/api/pay/transfer/index.ts b/src/api/pay/transfer/index.ts new file mode 100644 index 0000000..7a58abf --- /dev/null +++ b/src/api/pay/transfer/index.ts @@ -0,0 +1,27 @@ +import request from '@/config/axios' + +export interface TransferVO { + appId: number + channelCode: string + merchantTransferId: string + type: number + price: number + subject: string + userName: string + alipayLogonId: string + openid: string +} + +// 新增转账单 +export const createTransfer = async (data: TransferVO) => { + return await request.post({ url: `/pay/transfer/create`, data }) +} + +// 查询转账单列表 +export const getTransferPage = async (params) => { + return await request.get({ url: `/pay/transfer/page`, params }) +} + +export const getTransfer = async (id: number) => { + return await request.get({ url: '/pay/transfer/get?id=' + id }) +} diff --git a/src/api/pay/wallet/balance/index.ts b/src/api/pay/wallet/balance/index.ts new file mode 100644 index 0000000..d7c3edd --- /dev/null +++ b/src/api/pay/wallet/balance/index.ts @@ -0,0 +1,32 @@ +import request from '@/config/axios' + +/** 用户钱包查询参数 */ +export interface PayWalletUserReqVO { + userId: number +} + +/** 钱包 VO */ +export interface WalletVO { + id: number + userId: number + userType: number + balance: number + totalExpense: number + totalRecharge: number + freezePrice: number +} + +/** 查询用户钱包详情 */ +export const getWallet = async (params: PayWalletUserReqVO) => { + return await request.get({ url: `/pay/wallet/get`, params }) +} + +/** 查询会员钱包列表 */ +export const getWalletPage = async (params: any) => { + return await request.get({ url: `/pay/wallet/page`, params }) +} + +/** 修改会员钱包余额 */ +export const updateWalletBalance = async (data: any) => { + return await request.put({ url: `/pay/wallet/update-balance`, data }) +} diff --git a/src/api/pay/wallet/rechargePackage/index.ts b/src/api/pay/wallet/rechargePackage/index.ts new file mode 100644 index 0000000..c8e4cc9 --- /dev/null +++ b/src/api/pay/wallet/rechargePackage/index.ts @@ -0,0 +1,34 @@ +import request from '@/config/axios' + +export interface WalletRechargePackageVO { + id: number + name: string + payPrice: number + bonusPrice: number + status: number +} + +// 查询套餐充值列表 +export const getWalletRechargePackagePage = async (params) => { + return await request.get({ url: '/pay/wallet-recharge-package/page', params }) +} + +// 查询套餐充值详情 +export const getWalletRechargePackage = async (id: number) => { + return await request.get({ url: '/pay/wallet-recharge-package/get?id=' + id }) +} + +// 新增套餐充值 +export const createWalletRechargePackage = async (data: WalletRechargePackageVO) => { + return await request.post({ url: '/pay/wallet-recharge-package/create', data }) +} + +// 修改套餐充值 +export const updateWalletRechargePackage = async (data: WalletRechargePackageVO) => { + return await request.put({ url: '/pay/wallet-recharge-package/update', data }) +} + +// 删除套餐充值 +export const deleteWalletRechargePackage = async (id: number) => { + return await request.delete({ url: '/pay/wallet-recharge-package/delete?id=' + id }) +} diff --git a/src/api/pay/wallet/transaction/index.ts b/src/api/pay/wallet/transaction/index.ts new file mode 100644 index 0000000..3377ffa --- /dev/null +++ b/src/api/pay/wallet/transaction/index.ts @@ -0,0 +1,14 @@ +import request from '@/config/axios' + +export interface WalletTransactionVO { + id: number + walletId: number + title: string + price: number + balance: number +} + +// 查询会员钱包流水列表 +export const getWalletTransactionPage = async (params) => { + return await request.get({ url: `/pay/wallet-transaction/page`, params }) +} diff --git a/src/api/system/area/index.ts b/src/api/system/area/index.ts new file mode 100644 index 0000000..e91a499 --- /dev/null +++ b/src/api/system/area/index.ts @@ -0,0 +1,11 @@ +import request from '@/config/axios' + +// 获得地区树 +export const getAreaTree = async () => { + return await request.get({ url: '/system/area/tree' }) +} + +// 获得 IP 对应的地区名 +export const getAreaByIp = async (ip: string) => { + return await request.get({ url: '/system/area/get-by-ip?ip=' + ip }) +} diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts new file mode 100644 index 0000000..04d5c88 --- /dev/null +++ b/src/api/system/dept/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface DeptVO { + id?: number + name: string + parentId: number + status: number + sort: number + leaderUserId: number + phone: string + email: string + createTime: Date +} + +// 查询部门(精简)列表 +export const getSimpleDeptList = async (): Promise => { + return await request.get({ url: '/system/dept/simple-list' }) +} + +// 查询部门列表 +export const getDeptPage = async (params: PageParam) => { + return await request.get({ url: '/system/dept/list', params }) +} + +// 查询部门详情 +export const getDept = async (id: number) => { + return await request.get({ url: '/system/dept/get?id=' + id }) +} + +// 新增部门 +export const createDept = async (data: DeptVO) => { + return await request.post({ url: '/system/dept/create', data: data }) +} + +// 修改部门 +export const updateDept = async (params: DeptVO) => { + return await request.put({ url: '/system/dept/update', data: params }) +} + +// 删除部门 +export const deleteDept = async (id: number) => { + return await request.delete({ url: '/system/dept/delete?id=' + id }) +} diff --git a/src/api/system/dict/dict.data.ts b/src/api/system/dict/dict.data.ts new file mode 100644 index 0000000..f428648 --- /dev/null +++ b/src/api/system/dict/dict.data.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export type DictDataVO = { + id: number | undefined + sort: number | undefined + label: string + value: string + dictType: string + status: number + colorType: string + cssClass: string + remark: string + createTime: Date +} + +// 查询字典数据(精简)列表 +export const getSimpleDictDataList = () => { + return request.get({ url: '/system/dict-data/simple-list' }) +} + +// 查询字典数据列表 +export const getDictDataPage = (params: PageParam) => { + return request.get({ url: '/system/dict-data/page', params }) +} + +// 查询字典数据详情 +export const getDictData = (id: number) => { + return request.get({ url: '/system/dict-data/get?id=' + id }) +} + +// 新增字典数据 +export const createDictData = (data: DictDataVO) => { + return request.post({ url: '/system/dict-data/create', data }) +} + +// 修改字典数据 +export const updateDictData = (data: DictDataVO) => { + return request.put({ url: '/system/dict-data/update', data }) +} + +// 删除字典数据 +export const deleteDictData = (id: number) => { + return request.delete({ url: '/system/dict-data/delete?id=' + id }) +} + +// 导出字典类型数据 +export const exportDictData = (params) => { + return request.download({ url: '/system/dict-data/export', params }) +} diff --git a/src/api/system/dict/dict.type.ts b/src/api/system/dict/dict.type.ts new file mode 100644 index 0000000..eaa5fb6 --- /dev/null +++ b/src/api/system/dict/dict.type.ts @@ -0,0 +1,44 @@ +import request from '@/config/axios' + +export type DictTypeVO = { + id: number | undefined + name: string + type: string + status: number + remark: string + createTime: Date +} + +// 查询字典(精简)列表 +export const getSimpleDictTypeList = () => { + return request.get({ url: '/system/dict-type/list-all-simple' }) +} + +// 查询字典列表 +export const getDictTypePage = (params: PageParam) => { + return request.get({ url: '/system/dict-type/page', params }) +} + +// 查询字典详情 +export const getDictType = (id: number) => { + return request.get({ url: '/system/dict-type/get?id=' + id }) +} + +// 新增字典 +export const createDictType = (data: DictTypeVO) => { + return request.post({ url: '/system/dict-type/create', data }) +} + +// 修改字典 +export const updateDictType = (data: DictTypeVO) => { + return request.put({ url: '/system/dict-type/update', data }) +} + +// 删除字典 +export const deleteDictType = (id: number) => { + return request.delete({ url: '/system/dict-type/delete?id=' + id }) +} +// 导出字典类型 +export const exportDictType = (params) => { + return request.download({ url: '/system/dict-type/export', params }) +} diff --git a/src/api/system/loginLog/index.ts b/src/api/system/loginLog/index.ts new file mode 100644 index 0000000..7296f25 --- /dev/null +++ b/src/api/system/loginLog/index.ts @@ -0,0 +1,25 @@ +import request from '@/config/axios' + +export interface LoginLogVO { + id: number + logType: number + traceId: number + userId: number + userType: number + username: string + result: number + status: number + userIp: string + userAgent: string + createTime: Date +} + +// 查询登录日志列表 +export const getLoginLogPage = (params: PageParam) => { + return request.get({ url: '/system/login-log/page', params }) +} + +// 导出登录日志 +export const exportLoginLog = (params) => { + return request.download({ url: '/system/login-log/export', params }) +} diff --git a/src/api/system/mail/account/index.ts b/src/api/system/mail/account/index.ts new file mode 100644 index 0000000..15e0391 --- /dev/null +++ b/src/api/system/mail/account/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface MailAccountVO { + id: number + mail: string + username: string + password: string + host: string + port: number + sslEnable: boolean + starttlsEnable: boolean +} + +// 查询邮箱账号列表 +export const getMailAccountPage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-account/page', params }) +} + +// 查询邮箱账号详情 +export const getMailAccount = async (id: number) => { + return await request.get({ url: '/system/mail-account/get?id=' + id }) +} + +// 新增邮箱账号 +export const createMailAccount = async (data: MailAccountVO) => { + return await request.post({ url: '/system/mail-account/create', data }) +} + +// 修改邮箱账号 +export const updateMailAccount = async (data: MailAccountVO) => { + return await request.put({ url: '/system/mail-account/update', data }) +} + +// 删除邮箱账号 +export const deleteMailAccount = async (id: number) => { + return await request.delete({ url: '/system/mail-account/delete?id=' + id }) +} + +// 获得邮箱账号精简列表 +export const getSimpleMailAccountList = async () => { + return request.get({ url: '/system/mail-account/simple-list' }) +} diff --git a/src/api/system/mail/log/index.ts b/src/api/system/mail/log/index.ts new file mode 100644 index 0000000..13172a7 --- /dev/null +++ b/src/api/system/mail/log/index.ts @@ -0,0 +1,30 @@ +import request from '@/config/axios' + +export interface MailLogVO { + id: number + userId: number + userType: number + toMail: string + accountId: number + fromMail: string + templateId: number + templateCode: string + templateNickname: string + templateTitle: string + templateContent: string + templateParams: string + sendStatus: number + sendTime: Date + sendMessageId: string + sendException: string +} + +// 查询邮件日志列表 +export const getMailLogPage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-log/page', params }) +} + +// 查询邮件日志详情 +export const getMailLog = async (id: number) => { + return await request.get({ url: '/system/mail-log/get?id=' + id }) +} diff --git a/src/api/system/mail/template/index.ts b/src/api/system/mail/template/index.ts new file mode 100644 index 0000000..fb7ce5e --- /dev/null +++ b/src/api/system/mail/template/index.ts @@ -0,0 +1,50 @@ +import request from '@/config/axios' + +export interface MailTemplateVO { + id: number + name: string + code: string + accountId: number + nickname: string + title: string + content: string + params: string + status: number + remark: string +} + +export interface MailSendReqVO { + mail: string + templateCode: string + templateParams: Map +} + +// 查询邮件模版列表 +export const getMailTemplatePage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-template/page', params }) +} + +// 查询邮件模版详情 +export const getMailTemplate = async (id: number) => { + return await request.get({ url: '/system/mail-template/get?id=' + id }) +} + +// 新增邮件模版 +export const createMailTemplate = async (data: MailTemplateVO) => { + return await request.post({ url: '/system/mail-template/create', data }) +} + +// 修改邮件模版 +export const updateMailTemplate = async (data: MailTemplateVO) => { + return await request.put({ url: '/system/mail-template/update', data }) +} + +// 删除邮件模版 +export const deleteMailTemplate = async (id: number) => { + return await request.delete({ url: '/system/mail-template/delete?id=' + id }) +} + +// 发送邮件 +export const sendMail = (data: MailSendReqVO) => { + return request.post({ url: '/system/mail-template/send-mail', data }) +} diff --git a/src/api/system/menu/index.ts b/src/api/system/menu/index.ts new file mode 100644 index 0000000..5a80668 --- /dev/null +++ b/src/api/system/menu/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface MenuVO { + id: number + name: string + permission: string + type: number + sort: number + parentId: number + path: string + icon: string + component: string + componentName?: string + status: number + visible: boolean + keepAlive: boolean + alwaysShow?: boolean + createTime: Date +} + +// 查询菜单(精简)列表 +export const getSimpleMenusList = () => { + return request.get({ url: '/system/menu/simple-list' }) +} + +// 查询菜单列表 +export const getMenuList = (params) => { + return request.get({ url: '/system/menu/list', params }) +} + +// 获取菜单详情 +export const getMenu = (id: number) => { + return request.get({ url: '/system/menu/get?id=' + id }) +} + +// 新增菜单 +export const createMenu = (data: MenuVO) => { + return request.post({ url: '/system/menu/create', data }) +} + +// 修改菜单 +export const updateMenu = (data: MenuVO) => { + return request.put({ url: '/system/menu/update', data }) +} + +// 删除菜单 +export const deleteMenu = (id: number) => { + return request.delete({ url: '/system/menu/delete?id=' + id }) +} diff --git a/src/api/system/notice/index.ts b/src/api/system/notice/index.ts new file mode 100644 index 0000000..f643469 --- /dev/null +++ b/src/api/system/notice/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface NoticeVO { + id: number | undefined + title: string + type: number + content: string + status: number + remark: string + creator: string + createTime: Date +} + +// 查询公告列表 +export const getNoticePage = (params: PageParam) => { + return request.get({ url: '/system/notice/page', params }) +} + +// 查询公告详情 +export const getNotice = (id: number) => { + return request.get({ url: '/system/notice/get?id=' + id }) +} + +// 新增公告 +export const createNotice = (data: NoticeVO) => { + return request.post({ url: '/system/notice/create', data }) +} + +// 修改公告 +export const updateNotice = (data: NoticeVO) => { + return request.put({ url: '/system/notice/update', data }) +} + +// 删除公告 +export const deleteNotice = (id: number) => { + return request.delete({ url: '/system/notice/delete?id=' + id }) +} + +// 推送公告 +export const pushNotice = (id: number) => { + return request.post({ url: '/system/notice/push?id=' + id }) +} diff --git a/src/api/system/notify/message/index.ts b/src/api/system/notify/message/index.ts new file mode 100644 index 0000000..e407c77 --- /dev/null +++ b/src/api/system/notify/message/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' +import qs from 'qs' + +export interface NotifyMessageVO { + id: number + userId: number + userType: number + templateId: number + templateCode: string + templateNickname: string + templateContent: string + templateType: number + templateParams: string + readStatus: boolean + readTime: Date + createTime: Date +} + +// 查询站内信消息列表 +export const getNotifyMessagePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-message/page', params }) +} + +// 获得我的站内信分页 +export const getMyNotifyMessagePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-message/my-page', params }) +} + +// 批量标记已读 +export const updateNotifyMessageRead = async (ids) => { + return await request.put({ + url: '/system/notify-message/update-read?' + qs.stringify({ ids: ids }, { indices: false }) + }) +} + +// 标记所有站内信为已读 +export const updateAllNotifyMessageRead = async () => { + return await request.put({ url: '/system/notify-message/update-all-read' }) +} + +// 获取当前用户的最新站内信列表 +export const getUnreadNotifyMessageList = async () => { + return await request.get({ url: '/system/notify-message/get-unread-list' }) +} + +// 获得当前用户的未读站内信数量 +export const getUnreadNotifyMessageCount = async () => { + return await request.get({ url: '/system/notify-message/get-unread-count' }) +} diff --git a/src/api/system/notify/template/index.ts b/src/api/system/notify/template/index.ts new file mode 100644 index 0000000..44355df --- /dev/null +++ b/src/api/system/notify/template/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface NotifyTemplateVO { + id?: number + name: string + nickname: string + code: string + content: string + type?: number + params: string + status: number + remark: string +} + +export interface NotifySendReqVO { + userId: number | null + templateCode: string + templateParams: Map +} + +// 查询站内信模板列表 +export const getNotifyTemplatePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-template/page', params }) +} + +// 查询站内信模板详情 +export const getNotifyTemplate = async (id: number) => { + return await request.get({ url: '/system/notify-template/get?id=' + id }) +} + +// 新增站内信模板 +export const createNotifyTemplate = async (data: NotifyTemplateVO) => { + return await request.post({ url: '/system/notify-template/create', data }) +} + +// 修改站内信模板 +export const updateNotifyTemplate = async (data: NotifyTemplateVO) => { + return await request.put({ url: '/system/notify-template/update', data }) +} + +// 删除站内信模板 +export const deleteNotifyTemplate = async (id: number) => { + return await request.delete({ url: '/system/notify-template/delete?id=' + id }) +} + +// 发送站内信 +export const sendNotify = (data: NotifySendReqVO) => { + return request.post({ url: '/system/notify-template/send-notify', data }) +} diff --git a/src/api/system/oauth2/client.ts b/src/api/system/oauth2/client.ts new file mode 100644 index 0000000..6f71aca --- /dev/null +++ b/src/api/system/oauth2/client.ts @@ -0,0 +1,47 @@ +import request from '@/config/axios' + +export interface OAuth2ClientVO { + id: number + clientId: string + secret: string + name: string + logo: string + description: string + status: number + accessTokenValiditySeconds: number + refreshTokenValiditySeconds: number + redirectUris: string[] + autoApprove: boolean + authorizedGrantTypes: string[] + scopes: string[] + authorities: string[] + resourceIds: string[] + additionalInformation: string + isAdditionalInformationJson: boolean + createTime: Date +} + +// 查询 OAuth2 客户端的列表 +export const getOAuth2ClientPage = (params: PageParam) => { + return request.get({ url: '/system/oauth2-client/page', params }) +} + +// 查询 OAuth2 客户端的详情 +export const getOAuth2Client = (id: number) => { + return request.get({ url: '/system/oauth2-client/get?id=' + id }) +} + +// 新增 OAuth2 客户端 +export const createOAuth2Client = (data: OAuth2ClientVO) => { + return request.post({ url: '/system/oauth2-client/create', data }) +} + +// 修改 OAuth2 客户端 +export const updateOAuth2Client = (data: OAuth2ClientVO) => { + return request.put({ url: '/system/oauth2-client/update', data }) +} + +// 删除 OAuth2 +export const deleteOAuth2Client = (id: number) => { + return request.delete({ url: '/system/oauth2-client/delete?id=' + id }) +} diff --git a/src/api/system/oauth2/token.ts b/src/api/system/oauth2/token.ts new file mode 100644 index 0000000..ac89ae8 --- /dev/null +++ b/src/api/system/oauth2/token.ts @@ -0,0 +1,22 @@ +import request from '@/config/axios' + +export interface OAuth2TokenVO { + id: number + accessToken: string + refreshToken: string + userId: number + userType: number + clientId: string + createTime: Date + expiresTime: Date +} + +// 查询 token列表 +export const getAccessTokenPage = (params: PageParam) => { + return request.get({ url: '/system/oauth2-token/page', params }) +} + +// 删除 token +export const deleteAccessToken = (accessToken: string) => { + return request.delete({ url: '/system/oauth2-token/delete?accessToken=' + accessToken }) +} diff --git a/src/api/system/operatelog/index.ts b/src/api/system/operatelog/index.ts new file mode 100644 index 0000000..cdb713e --- /dev/null +++ b/src/api/system/operatelog/index.ts @@ -0,0 +1,30 @@ +import request from '@/config/axios' + +export type OperateLogVO = { + id: number + traceId: string + userType: number + userId: number + userName: string + type: string + subType: string + bizId: number + action: string + extra: string + requestMethod: string + requestUrl: string + userIp: string + userAgent: string + creator: string + creatorName: string + createTime: Date +} + +// 查询操作日志列表 +export const getOperateLogPage = (params: PageParam) => { + return request.get({ url: '/system/operate-log/page', params }) +} +// 导出操作日志 +export const exportOperateLog = (params: any) => { + return request.download({ url: '/system/operate-log/export', params }) +} diff --git a/src/api/system/permission/index.ts b/src/api/system/permission/index.ts new file mode 100644 index 0000000..b3c7696 --- /dev/null +++ b/src/api/system/permission/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface PermissionAssignUserRoleReqVO { + userId: number + roleIds: number[] +} + +export interface PermissionAssignRoleMenuReqVO { + roleId: number + menuIds: number[] +} + +export interface PermissionAssignRoleDataScopeReqVO { + roleId: number + dataScope: number + dataScopeDeptIds: number[] +} + +// 查询角色拥有的菜单权限 +export const getRoleMenuList = async (roleId: number) => { + return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId }) +} + +// 赋予角色菜单权限 +export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => { + return await request.post({ url: '/system/permission/assign-role-menu', data }) +} + +// 赋予角色数据权限 +export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => { + return await request.post({ url: '/system/permission/assign-role-data-scope', data }) +} + +// 查询用户拥有的角色数组 +export const getUserRoleList = async (userId: number) => { + return await request.get({ url: '/system/permission/list-user-roles?userId=' + userId }) +} + +// 赋予用户角色 +export const assignUserRole = async (data: PermissionAssignUserRoleReqVO) => { + return await request.post({ url: '/system/permission/assign-user-role', data }) +} diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts new file mode 100644 index 0000000..0e6f2ca --- /dev/null +++ b/src/api/system/post/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +export interface PostVO { + id?: number + name: string + code: string + sort: number + status: number + remark: string + createTime?: Date +} + +// 查询岗位列表 +export const getPostPage = async (params: PageParam) => { + return await request.get({ url: '/system/post/page', params }) +} + +// 获取岗位精简信息列表 +export const getSimplePostList = async (): Promise => { + return await request.get({ url: '/system/post/simple-list' }) +} + +// 查询岗位详情 +export const getPost = async (id: number) => { + return await request.get({ url: '/system/post/get?id=' + id }) +} + +// 新增岗位 +export const createPost = async (data: PostVO) => { + return await request.post({ url: '/system/post/create', data }) +} + +// 修改岗位 +export const updatePost = async (data: PostVO) => { + return await request.put({ url: '/system/post/update', data }) +} + +// 删除岗位 +export const deletePost = async (id: number) => { + return await request.delete({ url: '/system/post/delete?id=' + id }) +} + +// 导出岗位 +export const exportPost = async (params) => { + return await request.download({ url: '/system/post/export', params }) +} diff --git a/src/api/system/role/index.ts b/src/api/system/role/index.ts new file mode 100644 index 0000000..3325dde --- /dev/null +++ b/src/api/system/role/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +export interface RoleVO { + id: number + name: string + code: string + sort: number + status: number + type: number + dataScope: number + dataScopeDeptIds: number[] + createTime: Date +} + +export interface UpdateStatusReqVO { + id: number + status: number +} + +// 查询角色列表 +export const getRolePage = async (params: PageParam) => { + return await request.get({ url: '/system/role/page', params }) +} + +// 查询角色(精简)列表 +export const getSimpleRoleList = async (): Promise => { + return await request.get({ url: '/system/role/simple-list' }) +} + +// 查询角色详情 +export const getRole = async (id: number) => { + return await request.get({ url: '/system/role/get?id=' + id }) +} + +// 新增角色 +export const createRole = async (data: RoleVO) => { + return await request.post({ url: '/system/role/create', data }) +} + +// 修改角色 +export const updateRole = async (data: RoleVO) => { + return await request.put({ url: '/system/role/update', data }) +} + +// 修改角色状态 +export const updateRoleStatus = async (data: UpdateStatusReqVO) => { + return await request.put({ url: '/system/role/update-status', data }) +} + +// 删除角色 +export const deleteRole = async (id: number) => { + return await request.delete({ url: '/system/role/delete?id=' + id }) +} + +// 导出角色 +export const exportRole = (params) => { + return request.download({ + url: '/system/role/export-excel', + params + }) +} diff --git a/src/api/system/sms/smsChannel/index.ts b/src/api/system/sms/smsChannel/index.ts new file mode 100644 index 0000000..bcdaa7f --- /dev/null +++ b/src/api/system/sms/smsChannel/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface SmsChannelVO { + id: number + code: string + status: number + signature: string + remark: string + apiKey: string + apiSecret: string + callbackUrl: string + createTime: Date +} + +// 查询短信渠道列表 +export const getSmsChannelPage = (params: PageParam) => { + return request.get({ url: '/system/sms-channel/page', params }) +} + +// 获得短信渠道精简列表 +export function getSimpleSmsChannelList() { + return request.get({ url: '/system/sms-channel/simple-list' }) +} + +// 查询短信渠道详情 +export const getSmsChannel = (id: number) => { + return request.get({ url: '/system/sms-channel/get?id=' + id }) +} + +// 新增短信渠道 +export const createSmsChannel = (data: SmsChannelVO) => { + return request.post({ url: '/system/sms-channel/create', data }) +} + +// 修改短信渠道 +export const updateSmsChannel = (data: SmsChannelVO) => { + return request.put({ url: '/system/sms-channel/update', data }) +} + +// 删除短信渠道 +export const deleteSmsChannel = (id: number) => { + return request.delete({ url: '/system/sms-channel/delete?id=' + id }) +} diff --git a/src/api/system/sms/smsLog/index.ts b/src/api/system/sms/smsLog/index.ts new file mode 100644 index 0000000..f989171 --- /dev/null +++ b/src/api/system/sms/smsLog/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface SmsLogVO { + id: number | null + channelId: number | null + channelCode: string + templateId: number | null + templateCode: string + templateType: number | null + templateContent: string + templateParams: Map | null + apiTemplateId: string + mobile: string + userId: number | null + userType: number | null + sendStatus: number | null + sendTime: Date | null + apiSendCode: string + apiSendMsg: string + apiRequestId: string + apiSerialNo: string + receiveStatus: number | null + receiveTime: Date | null + apiReceiveCode: string + apiReceiveMsg: string + createTime: Date | null +} + +// 查询短信日志列表 +export const getSmsLogPage = (params: PageParam) => { + return request.get({ url: '/system/sms-log/page', params }) +} + +// 导出短信日志 +export const exportSmsLog = (params) => { + return request.download({ url: '/system/sms-log/export-excel', params }) +} diff --git a/src/api/system/sms/smsTemplate/index.ts b/src/api/system/sms/smsTemplate/index.ts new file mode 100644 index 0000000..868ddd4 --- /dev/null +++ b/src/api/system/sms/smsTemplate/index.ts @@ -0,0 +1,60 @@ +import request from '@/config/axios' + +export interface SmsTemplateVO { + id?: number + type?: number + status: number + code: string + name: string + content: string + remark: string + apiTemplateId: string + channelId?: number + channelCode?: string + params?: string[] + createTime?: Date +} + +export interface SendSmsReqVO { + mobile: string + templateCode: string + templateParams: Map +} + +// 查询短信模板列表 +export const getSmsTemplatePage = (params: PageParam) => { + return request.get({ url: '/system/sms-template/page', params }) +} + +// 查询短信模板详情 +export const getSmsTemplate = (id: number) => { + return request.get({ url: '/system/sms-template/get?id=' + id }) +} + +// 新增短信模板 +export const createSmsTemplate = (data: SmsTemplateVO) => { + return request.post({ url: '/system/sms-template/create', data }) +} + +// 修改短信模板 +export const updateSmsTemplate = (data: SmsTemplateVO) => { + return request.put({ url: '/system/sms-template/update', data }) +} + +// 删除短信模板 +export const deleteSmsTemplate = (id: number) => { + return request.delete({ url: '/system/sms-template/delete?id=' + id }) +} + +// 导出短信模板 +export const exportSmsTemplate = (params) => { + return request.download({ + url: '/system/sms-template/export-excel', + params + }) +} + +// 发送短信 +export const sendSms = (data: SendSmsReqVO) => { + return request.post({ url: '/system/sms-template/send-sms', data }) +} diff --git a/src/api/system/social/client/index.ts b/src/api/system/social/client/index.ts new file mode 100644 index 0000000..bf13ab4 --- /dev/null +++ b/src/api/system/social/client/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface SocialClientVO { + id: number + name: string + socialType: number + userType: number + clientId: string + clientSecret: string + agentId: string + status: number +} + +// 查询社交客户端列表 +export const getSocialClientPage = async (params) => { + return await request.get({ url: `/system/social-client/page`, params }) +} + +// 查询社交客户端详情 +export const getSocialClient = async (id: number) => { + return await request.get({ url: `/system/social-client/get?id=` + id }) +} + +// 新增社交客户端 +export const createSocialClient = async (data: SocialClientVO) => { + return await request.post({ url: `/system/social-client/create`, data }) +} + +// 修改社交客户端 +export const updateSocialClient = async (data: SocialClientVO) => { + return await request.put({ url: `/system/social-client/update`, data }) +} + +// 删除社交客户端 +export const deleteSocialClient = async (id: number) => { + return await request.delete({ url: `/system/social-client/delete?id=` + id }) +} diff --git a/src/api/system/social/user/index.ts b/src/api/system/social/user/index.ts new file mode 100644 index 0000000..f11231b --- /dev/null +++ b/src/api/system/social/user/index.ts @@ -0,0 +1,24 @@ +import request from '@/config/axios' + +export interface SocialUserVO { + id: number + type: number + openid: string + token: string + rawTokenInfo: string + nickname: string + avatar: string + rawUserInfo: string + code: string + state: string +} + +// 查询社交用户列表 +export const getSocialUserPage = async (params) => { + return await request.get({ url: `/system/social-user/page`, params }) +} + +// 查询社交用户详情 +export const getSocialUser = async (id: number) => { + return await request.get({ url: `/system/social-user/get?id=` + id }) +} diff --git a/src/api/system/tenant/index.ts b/src/api/system/tenant/index.ts new file mode 100644 index 0000000..176c375 --- /dev/null +++ b/src/api/system/tenant/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +export interface TenantVO { + id: number + name: string + contactName: string + contactMobile: string + status: number + domain: string + packageId: number + username: string + password: string + expireTime: Date + accountCount: number + createTime: Date +} + +export interface TenantPageReqVO extends PageParam { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} + +export interface TenantExportReqVO { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} + +// 查询租户列表 +export const getTenantPage = (params: TenantPageReqVO) => { + return request.get({ url: '/system/tenant/page', params }) +} + +// 查询租户详情 +export const getTenant = (id: number) => { + return request.get({ url: '/system/tenant/get?id=' + id }) +} + +// 新增租户 +export const createTenant = (data: TenantVO) => { + return request.post({ url: '/system/tenant/create', data }) +} + +// 修改租户 +export const updateTenant = (data: TenantVO) => { + return request.put({ url: '/system/tenant/update', data }) +} + +// 删除租户 +export const deleteTenant = (id: number) => { + return request.delete({ url: '/system/tenant/delete?id=' + id }) +} + +// 导出租户 +export const exportTenant = (params: TenantExportReqVO) => { + return request.download({ url: '/system/tenant/export-excel', params }) +} diff --git a/src/api/system/tenantPackage/index.ts b/src/api/system/tenantPackage/index.ts new file mode 100644 index 0000000..e01375a --- /dev/null +++ b/src/api/system/tenantPackage/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface TenantPackageVO { + id: number + name: string + status: number + remark: string + creator: string + updater: string + updateTime: string + menuIds: number[] + createTime: Date +} + +// 查询租户套餐列表 +export const getTenantPackagePage = (params: PageParam) => { + return request.get({ url: '/system/tenant-package/page', params }) +} + +// 获得租户 +export const getTenantPackage = (id: number) => { + return request.get({ url: '/system/tenant-package/get?id=' + id }) +} + +// 新增租户套餐 +export const createTenantPackage = (data: TenantPackageVO) => { + return request.post({ url: '/system/tenant-package/create', data }) +} + +// 修改租户套餐 +export const updateTenantPackage = (data: TenantPackageVO) => { + return request.put({ url: '/system/tenant-package/update', data }) +} + +// 删除租户套餐 +export const deleteTenantPackage = (id: number) => { + return request.delete({ url: '/system/tenant-package/delete?id=' + id }) +} +// 获取租户套餐精简信息列表 +export const getTenantPackageList = () => { + return request.get({ url: '/system/tenant-package/simple-list' }) +} diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts new file mode 100644 index 0000000..beb6e51 --- /dev/null +++ b/src/api/system/user/index.ts @@ -0,0 +1,81 @@ +import request from '@/config/axios' + +export interface UserVO { + id: number + username: string + nickname: string + deptId: number + postIds: string[] + email: string + mobile: string + sex: number + avatar: string + loginIp: string + status: number + remark: string + loginDate: Date + createTime: Date +} + +// 查询用户管理列表 +export const getUserPage = (params: PageParam) => { + return request.get({ url: '/system/user/page', params }) +} + +// 查询所有用户列表 +export const getAllUser = () => { + return request.get({ url: '/system/user/all' }) +} + +// 查询用户详情 +export const getUser = (id: number) => { + return request.get({ url: '/system/user/get?id=' + id }) +} + +// 新增用户 +export const createUser = (data: UserVO) => { + return request.post({ url: '/system/user/create', data }) +} + +// 修改用户 +export const updateUser = (data: UserVO) => { + return request.put({ url: '/system/user/update', data }) +} + +// 删除用户 +export const deleteUser = (id: number) => { + return request.delete({ url: '/system/user/delete?id=' + id }) +} + +// 导出用户 +export const exportUser = (params) => { + return request.download({ url: '/system/user/export', params }) +} + +// 下载用户导入模板 +export const importUserTemplate = () => { + return request.download({ url: '/system/user/get-import-template' }) +} + +// 用户密码重置 +export const resetUserPwd = (id: number, password: string) => { + const data = { + id, + password + } + return request.put({ url: '/system/user/update-password', data: data }) +} + +// 用户状态修改 +export const updateUserStatus = (id: number, status: number) => { + const data = { + id, + status + } + return request.put({ url: '/system/user/update-status', data: data }) +} + +// 获取用户精简信息列表 +export const getSimpleUserList = (): Promise => { + return request.get({ url: '/system/user/simple-list' }) +} diff --git a/src/api/system/user/profile.ts b/src/api/system/user/profile.ts new file mode 100644 index 0000000..1e80e85 --- /dev/null +++ b/src/api/system/user/profile.ts @@ -0,0 +1,65 @@ +import request from '@/config/axios' + +export interface ProfileVO { + id: number + username: string + nickname: string + dept: { + id: number + name: string + } + roles: { + id: number + name: string + }[] + posts: { + id: number + name: string + }[] + socialUsers: { + type: number + openid: string + }[] + email: string + mobile: string + sex: number + avatar: string + status: number + remark: string + loginIp: string + loginDate: Date + createTime: Date +} + +export interface UserProfileUpdateReqVO { + nickname: string + email: string + mobile: string + sex: number +} + +// 查询用户个人信息 +export const getUserProfile = () => { + return request.get({ url: '/system/user/profile/get' }) +} + +// 修改用户个人信息 +export const updateUserProfile = (data: UserProfileUpdateReqVO) => { + return request.put({ url: '/system/user/profile/update', data }) +} + +// 用户密码重置 +export const updateUserPassword = (oldPassword: string, newPassword: string) => { + return request.put({ + url: '/system/user/profile/update-password', + data: { + oldPassword: oldPassword, + newPassword: newPassword + } + }) +} + +// 用户头像上传 +export const uploadAvatar = (data) => { + return request.upload({ url: '/system/user/profile/update-avatar', data: data }) +} diff --git a/src/api/system/user/socialUser.ts b/src/api/system/user/socialUser.ts new file mode 100644 index 0000000..79f4d40 --- /dev/null +++ b/src/api/system/user/socialUser.ts @@ -0,0 +1,31 @@ +import request from '@/config/axios' + +// 社交绑定,使用 code 授权码 +export const socialBind = (type, code, state) => { + return request.post({ + url: '/system/social-user/bind', + data: { + type, + code, + state + } + }) +} + +// 取消社交绑定 +export const socialUnbind = (type, openid) => { + return request.delete({ + url: '/system/social-user/unbind', + data: { + type, + openid + } + }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type, redirectUri) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} diff --git a/src/assets/ai/copy-style2.svg b/src/assets/ai/copy-style2.svg new file mode 100644 index 0000000..2d56a87 --- /dev/null +++ b/src/assets/ai/copy-style2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ai/copy.svg b/src/assets/ai/copy.svg new file mode 100644 index 0000000..f51f8d8 --- /dev/null +++ b/src/assets/ai/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ai/dall2.jpg b/src/assets/ai/dall2.jpg new file mode 100644 index 0000000..c07374d Binary files /dev/null and b/src/assets/ai/dall2.jpg differ diff --git a/src/assets/ai/dall3.jpg b/src/assets/ai/dall3.jpg new file mode 100644 index 0000000..7f45803 Binary files /dev/null and b/src/assets/ai/dall3.jpg differ diff --git a/src/assets/ai/delete.svg b/src/assets/ai/delete.svg new file mode 100644 index 0000000..d2ee18e --- /dev/null +++ b/src/assets/ai/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ai/gpt.svg b/src/assets/ai/gpt.svg new file mode 100644 index 0000000..603e2e9 --- /dev/null +++ b/src/assets/ai/gpt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ai/qingxi.jpg b/src/assets/ai/qingxi.jpg new file mode 100644 index 0000000..d76b815 Binary files /dev/null and b/src/assets/ai/qingxi.jpg differ diff --git a/src/assets/ai/ziran.jpg b/src/assets/ai/ziran.jpg new file mode 100644 index 0000000..6290724 Binary files /dev/null and b/src/assets/ai/ziran.jpg differ diff --git a/src/assets/audio/response.mp3 b/src/assets/audio/response.mp3 new file mode 100644 index 0000000..b7cb777 Binary files /dev/null and b/src/assets/audio/response.mp3 differ diff --git a/src/assets/imgs/avatar.gif b/src/assets/imgs/avatar.gif new file mode 100644 index 0000000..fdbd32c Binary files /dev/null and b/src/assets/imgs/avatar.gif differ diff --git a/src/assets/imgs/avatar.jpg b/src/assets/imgs/avatar.jpg new file mode 100644 index 0000000..d46a70a Binary files /dev/null and b/src/assets/imgs/avatar.jpg differ diff --git a/src/assets/imgs/diy/app-nav-bar-mp.png b/src/assets/imgs/diy/app-nav-bar-mp.png new file mode 100644 index 0000000..c982804 Binary files /dev/null and b/src/assets/imgs/diy/app-nav-bar-mp.png differ diff --git a/src/assets/imgs/diy/statusBar.png b/src/assets/imgs/diy/statusBar.png new file mode 100644 index 0000000..b85562e Binary files /dev/null and b/src/assets/imgs/diy/statusBar.png differ diff --git a/src/assets/imgs/logo.png b/src/assets/imgs/logo.png new file mode 100644 index 0000000..7e1043f Binary files /dev/null and b/src/assets/imgs/logo.png differ diff --git a/src/assets/imgs/profile.jpg b/src/assets/imgs/profile.jpg new file mode 100644 index 0000000..e4bcf87 Binary files /dev/null and b/src/assets/imgs/profile.jpg differ diff --git a/src/assets/imgs/wechat.png b/src/assets/imgs/wechat.png new file mode 100644 index 0000000..6afc5e4 Binary files /dev/null and b/src/assets/imgs/wechat.png differ diff --git a/src/assets/map/json/china.json b/src/assets/map/json/china.json new file mode 100644 index 0000000..bbc0a83 --- /dev/null +++ b/src/assets/map/json/china.json @@ -0,0 +1,856 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "710000", + "properties": { + "id": "710000", + "cp": [121.509062, 24.044332], + "name": "台湾", + "childNum": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@°Ü¯Û"], + [ + "@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ" + ], + ["@@\\p|WoYG¿¥I†j@¢"], + ["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"], + ["@@ÆEE—„kWqë @œ"], + ["@@fced"], + ["@@„¯ɜÄèaì¯ØǓIġĽ"], + ["@@çûĖ롖hòř "] + ], + "encodeOffsets": [ + [[122886, 24033]], + [[123335, 22980]], + [[122375, 24193]], + [[122518, 24117]], + [[124427, 22618]], + [[124862, 26043]], + [[126259, 26318]], + [[127671, 26683]] + ] + } + }, + { + "type": "Feature", + "id": "130000", + "properties": { + "id": "130000", + "cp": [114.502461, 38.045474], + "name": "河北", + "childNum": 3 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"], + ["@@U`Ts¿m‚"], + [ + "@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒Sp›¢dYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧĖ¸fŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgʊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|Ç°…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃĶš¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷Ñws¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@cĢ¬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®VŠ¹d^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qᵧš™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚" + ] + ], + "encodeOffsets": [[[119712, 40641]], [[121616, 39981]], [[116462, 37237]]] + } + }, + { + "type": "Feature", + "id": "140000", + "properties": { + "id": "140000", + "cp": [111.849248, 36.857014], + "name": "山西", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT‰©±@¥ù@É¡‰ZcW|WqOJmĩl«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~ĥqXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dz¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz" + ], + "encodeOffsets": [[116874, 41716]] + } + }, + { + "type": "Feature", + "id": "150000", + "properties": { + "id": "150000", + "cp": [111.670801, 41.818311], + "name": "内蒙古", + "childNum": 2 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + "@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠóƐÇ\\ƒ‡@áügQ͋u¥Fƒ“T՛¿Jû‡]|mvāÎYua^WoÀa·­ząÒot׶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\ĴuUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍz]‹±…ŭ©ŸÅ’]ŒÅÐ}UË¥©Tċ™ïxgckfWgi\\ÏĒ¥HkµE˜ë{»ÏetcG±ahUiñiWsɁˆ·c–C‚Õk]wȑ|ća}w…VaĚ᠞ŒG°ùnM¬¯†{ȈÐÆA’¥ÄêJxÙ¢”hP¢Ûˆº€µwWOŸóFŽšÁz^ÀŗÎú´§¢T¤ǻƺSė‰ǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇq‡Z‘ñiñC³ª—…»E`¨åXēÕqÉû[l•}ç@čƘóO¿¡ƒFUsA‰“ʽīccšocƒ‚ƒÇS}„“£‡IS~ălkĩXçmĈ…ŀЂoÐdxÒuL^T{r@¢‘žÍƒĝKén£kQ™‰yšÅõËXŷƏL§~}kqš»IHėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µsKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ǎ›¼ȳÐUf†dIxÿ\\G ˆzâɏÙOº·pqy£†@ŒŠqþ@Ǟ˽IBäƣzsÂZ†ÁàĻdñ°ŕzéØűzșCìDȐĴĺf®ŽÀľưø@ɜÖÞKĊŇƄ§‚͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mȠJˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚĒ¸ĞGȖƴƀj`ĢçĶāàŃºēĢƒĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dždÀɞ_ĸdîàŎjʜêTЪŌ‡ŜWÈ|tqĢUB~´°ÎFC•ŽU¼pĀēƄN¦¾O¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Ší¨ÅDK°ßtŇĔKš¨ǵÂcḷ̌ĚǣȄĽF‡lġUĵœŇ‹ȣFʉɁƒMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFŽxúQ„Er´W„rh¤Ɛ \\talĈDJ˜Ü|[Pll̚¸ƎGú´Pž¬W¦†^¦–H]prR“n|or¾wLVnÇIujkmon£cX^Bh`¥V”„¦U¤¸}€xRj–[^xN[~ªŠxQ„‚[`ªHÆÂExx^wšN¶Ê˜|¨ì†˜€MrœdYp‚oRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚r¤–`[|òDŞĔöxElÖdH„ÀI`„Ď\\Àì~ƎR¼tf•¦^¢ķ¶e”ÐÚMŒptgj–„ɡČÅyġLû™ŇV®ŠÄÈƀ†Ď°P|ªVV†ªj–¬ĚÒêp¬–E|ŬÂc|ÀtƐK fˆ{ĘFĒœƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfŒ£K£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ġu¦öČ^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ" + ] + ], + "encodeOffsets": [[[129102, 52189]]] + } + }, + { + "type": "Feature", + "id": "210000", + "properties": { + "id": "210000", + "cp": [123.429096, 41.796767], + "name": "辽宁", + "childNum": 16 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@L–Ž@@s™a"], + ["@@MnNm"], + ["@@d‚c"], + ["@@eÀ‚C@b‚“‰"], + ["@@f‡…Xwkbr–Ä`qg"], + ["@@^jtW‘Q"], + ["@@~ Y]c"], + ["@@G`ĔN^_¿Z‚ÃM"], + ["@@iX¶B‹Y"], + ["@@„YƒZ"], + ["@@L_{Epf"], + ["@@^WqCT\\"], + ["@@\\[“‹§t|”¤_"], + ["@@m`n_"], + ["@@Ïxnj{q_×^Giip"], + [ + "@@@œé^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼W–‚YÀäĦ’‘`XlžR`žôLUVžfK–¢†{NZdĒª’YĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~†źBŽ|¦ÕœEž¤Ð`\\|Kˆ˜UnnI]¤ÀÂĊnŎ™R®Ő¿¶\\ÀøíDm¦ÎbŨab‰œaĘ\\ľã‚¸a˜tÎSƐ´©v\\ÖÚÌǴ¤Â‡¨JKr€Z_Z€fjþhPkx€`Y”’RIŒjJcVf~sCN¤ ˆE‚œhæm‰–sHy¨SðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·C¥‡GD›rí@wÕKţ݋˜Ÿ«V·i}xËÍ÷‘i©ĝ‡ɝǡ]ƒˆ{c™±OW‹³Ya±Ÿ‰_穂Hžĕoƫ€Ňqƒr³‰Lys[„ñ³¯OS–ďOMisZ†±ÅFC¥Pq{‚Ã[Pg}\\—¿ghćO…•k^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀff‘dF~ˆ€ĀeĖ€d`sx² šƒ®EżĀdQ‹Âd^~ăÔHˆ¦\\›LKpĄVez¤NP ǹӗR™ÆąJSh­a[¦´Âghwm€BÐ¨źhI|žVVŽ—Ž|p] Â¼èNä¶ÜBÖ¼“L`‚¼bØæŒKV”ŸpoœúNZÞÒKxpw|ÊEMnzEQšŽIZ”ŽZ‡NBˆčÚFÜçmĩ‚WĪñt‘ÞĵÇñZ«uD‚±|Əlij¥ãn·±PmÍa‰–da‡ CL‡Ǒkùó¡³Ï«QaċϑOÃ¥ÕđQȥċƭy‹³ÃA" + ] + ], + "encodeOffsets": [ + [[123686, 41445]], + [[126019, 40435]], + [[124393, 40128]], + [[126117, 39963]], + [[125322, 40140]], + [[126686, 40700]], + [[126041, 40374]], + [[125584, 40168]], + [[125453, 40165]], + [[125362, 40214]], + [[125280, 40291]], + [[125774, 39997]], + [[125976, 40496]], + [[125822, 39993]], + [[125509, 40217]], + [[122731, 40949]] + ] + } + }, + { + "type": "Feature", + "id": "220000", + "properties": { "id": "220000", "cp": [125.3245, 43.886841], "name": "吉林", "childNum": 1 }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁTĠs¶¿âƊGW¾ìA¦·TѬ†è¥€ÏÐJ¨¼ÒÖ¼ƒƦɄxÊ~S–tD@ŠĂ¼Ŵ¡jlºWžvЉˆzƦZЎ²CH— „Axiukd‹ŒGgetqmcžÛ£Ozy¥cE}|…¾cZ…k‚‰¿uŐã[oxGikfeäT@…šSUwpiÚFM©’£è^ڟ‚`@v¶eň†f h˜eP¶žt“äOlÔUgƒÞzŸU`lœ}ÔÆUvØ_Ō¬Öi^ĉi§²ÃŠB~¡Ĉ™ÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYx‘ƘDVÇĺĿg¿cwÅ\\¹˜¥Yĭlœ¤žOv†šLjM_a W`zļMž·\\swqÝSA‡š—q‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄUĞd\\i֚ŒˆmÈBĤÜɲDEh LG¾ƀľ{WaŒYÍȏĢĘÔRîĐj‹}Ǟ“ccj‡oUb½š{“h§Ǿ{K‹ƖµÎ÷žGĀÖŠåưÎs­l›•yiē«‹`姝H¥Ae^§„GK}iã\\c]v©ģZ“mÃ|“[M}ģTɟĵ‘Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜYünĎųVY^’˜ydõkÅZW„«WUa~U·Sb•wGçǑ‚“iW^q‹F‚“›uNĝ—·Ew„‹UtW·Ýďæ©PuqEzwAV•—XR‰ãQ`­©GŒM‡ehc›c”ďϝd‡©ÑW_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhĿDCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG" + ], + "encodeOffsets": [[130196, 42528]] + } + }, + { + "type": "Feature", + "id": "230000", + "properties": { + "id": "230000", + "cp": [128.642464, 46.756967], + "name": "黑龙江", + "childNum": 2 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + "@@UƒµNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³pŽj£º”š¿”»WH´¯”U¸đĢmžtĜyzzNN|g¸÷äűѱĉā~mq^—Œ[ƒ”››”ƒǁÑďlw]¯xQĔ‰¯l‰’€°řĴrŠ™˜BˆÞTxr[tŽ¸ĻN_yŸX`biN™Ku…P›£k‚ZĮ—¦[ºxÆÀdhŽĹŀUÈƗCw’áZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFćš}¢‰A±Äj¨]ĊÕjŋ«×`VuÓś~_kŷVÝyh„“VkÄãPs”Oµ—fŸge‚Ň…µf@u_Ù ÙcŸªNªÙEojVx™T@†ãSefjlwH\\pŏäÀvŠŽlY†½d{†F~¦dyz¤PÜndsrhf‹HcŒvlwjFœ£G˜±DύƥY‡yϊu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|Cš˜zxAè¥bœfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒUŸzou‡xe]}Ž…AyȑW¯ÌmK‡“Q]‹Īºif¸ÄX|sZt|½ÚUΠlkš^p{f¤lˆºlÆW –€A²˜PVܜPH”Êâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi†`¶—„bXƒrBgxfv»ŽuUiˆŒ^v~”J¬mVp´£Œ´VWrnP½ì¢BX‚¬h™ŠðX¹^TjVœŠriªj™tŊÄm€tPGx¸bgRšŽsT`ZozÆO]’ÒFô҆Oƒ‡ŊŒvŞ”p’cGŒêŠsx´DR–Œ{A†„EOr°Œ•žx|íœbˆ³Wm~DVjºéNN†Ëܲɶ­GƒxŷCStŸ}]ûō•SmtuÇÃĕN•™āg»šíT«u}ç½BĵÞʣ¥ëÊ¡Mێ³ãȅ¡ƋaǩÈÉQ‰†G¢·lG|›„tvgrrf«†ptęŘnŠÅĢr„I²¯LiØsPf˜_vĠd„xM prʹšL¤‹¤‡eˌƒÀđK“žïÙVY§]I‡óáĥ]ķ†Kˆ¥Œj|pŇ\\kzţ¦šnņäÔVĂîĪ¬|vW’®l¤èØr‚˜•xm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄ–Ą»ƢjȦOǺ¨ìSŖÆƬy”Qœv`–cwƒZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ġ[@gġ}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Ǹ¯YßċġHµ ¡eå`ļƒrĉŘóƢFì“ĎWøxÊk†”ƈdƬv|–I|·©NqńRŀƒ¤é”eŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^Xm‡—HĊĕË«W·ċëx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ħ…ŨK~”ȰCĐ´Ƕ£’fNÎèâw¢XnŮeÂÆĶŽ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®‚ØCÔ ŬGƠ”ƦYĜ‡ĘÜƬDJ—g_ͥœ@čŅĻA“¶¯@wÎqC½Ĉ»NŸăëK™ďÍQ“Ùƫ[«Ãí•gßÔÇOÝáW‘ñuZ“¯ĥ€Ÿŕā¡ÑķJu¤E Ÿå¯°WKɱ_d_}}vyŸõu¬ï¹ÓU±½@gÏ¿rýD‰†g…Cd‰µ—°MFYxw¿CG£‹Rƛ½Õ{]L§{qqąš¿BÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]" + ] + ], + "encodeOffsets": [[[134456, 44547]]] + } + }, + { + "type": "Feature", + "id": "320000", + "properties": { + "id": "320000", + "cp": [119.767413, 33.041544], + "name": "江苏", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©DaÜތ·jgàiDbPufjDk`dPOîƒhw¡ĥ‡¥šG˜ŸP²ĐobºrY†„î¶aHŢ´ ]´‚rılw³r_{£DB_Ûdåuk|ˆŨ¯F Cºyr{XFy™e³Þċ‡¿Â™kĭB¿„MvÛpm`rÚã”@Ę¹hågËÖƿxnlč¶Åì½Ot¾dJlŠVJʜǀœŞqvnOŠ^ŸJ”Z‘ż·Q}ê͎ÅmµÒ]Žƍ¦Dq}¬R^èĂ´ŀĻĊIԒtžIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJŴu»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ" + ], + "encodeOffsets": [[121740, 32276]] + } + }, + { + "type": "Feature", + "id": "330000", + "properties": { + "id": "330000", + "cp": [120.153576, 29.287459], + "name": "浙江", + "childNum": 45 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@E^dQ]K"], + ["@@jX^j‡"], + ["@@sfŠbU‡"], + ["@@qP\\xz[ck"], + ["@@‘Rƒ¢‚FX}°[s_"], + ["@@Cbœ\\—}"], + ["@@e|v\\la{u"], + ["@@v~u}"], + ["@@QxÂF¯}"], + ["@@¹nŒvÞs¯o"], + ["@@rSkUEj"], + ["@@bi­ZŒP"], + ["@@p[}INf"], + ["@@À¿€"], + ["@@¹dnbŒ…"], + ["@@rSŸBnR"], + ["@@g~h}"], + ["@@FlEk"], + ["@@OdPc"], + ["@@v[u\\"], + ["@@FjâL~wyoo~›sµL–\\"], + ["@@¬e¹aNˆ"], + ["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"], + ["@@ÊA­©[¬"], + ["@@KxŒv­"], + ["@@@hlIk]"], + ["@@pW{o||j"], + ["@@Md|_mC"], + ["@@¢…X£ÏylD¼XˆtH"], + ["@@hlÜ[LykAvyfw^Ež›¤"], + ["@@fp¤Mus“R"], + ["@@®_ma~•LÁ¬šZ"], + ["@@iM„xZ"], + ["@@ZcYd"], + ["@@Z~dOSo|A¿qZv"], + ["@@@`”EN¡v"], + ["@@|–TY{"], + ["@@@n@m"], + ["@@XWkCT\\"], + ["@@ºwšZRkĕWO¢"], + ["@@™X®±Grƪ\\ÔáXq{‹"], + ["@@ůTG°ĄLHm°UC‹"], + [ + "@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВjē¢·ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™iqªĭiAu‡A­µ”_W¥ƣO\\lċĢttC¨£t`ˆ™PZäuXßBs‡Ļyek€OđġĵHuXBšµ]׌‡­­\\›°®¬F¢¾pµ¼kŘó¬Wät’¸|@ž•L¨¸µr“ºù³Ù~§WI‹ŸZWŽ®’±Ð¨ÒÉx€`‰²pĜ•rOògtÁZ}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…Øzœ©PœCÈڜĒ±„hŖ‡l¬â~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst" + ], + ["@@o\\V’zRZ}y"], + ["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"] + ], + "encodeOffsets": [ + [[125592, 31553]], + [[125785, 31436]], + [[125729, 31431]], + [[125513, 31380]], + [[125223, 30438]], + [[125115, 30114]], + [[124815, 29155]], + [[124419, 28746]], + [[124095, 28635]], + [[124005, 28609]], + [[125000, 30713]], + [[125111, 30698]], + [[125078, 30682]], + [[125150, 30684]], + [[124014, 28103]], + [[125008, 31331]], + [[125411, 31468]], + [[125329, 31479]], + [[125626, 30916]], + [[125417, 30956]], + [[125254, 30976]], + [[125199, 30997]], + [[125095, 31058]], + [[125083, 30915]], + [[124885, 31015]], + [[125218, 30798]], + [[124867, 30838]], + [[124755, 30788]], + [[124802, 30809]], + [[125267, 30657]], + [[125218, 30578]], + [[125200, 30562]], + [[124968, 30474]], + [[125167, 30396]], + [[124955, 29879]], + [[124714, 29781]], + [[124762, 29462]], + [[124325, 28754]], + [[123990, 28459]], + [[125366, 31477]], + [[125115, 30363]], + [[125369, 31139]], + [[122495, 31878]], + [[125329, 30690]], + [[125192, 30787]] + ] + } + }, + { + "type": "Feature", + "id": "340000", + "properties": { "id": "340000", "cp": [117.283042, 31.26119], "name": "安徽", "childNum": 3 }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@^iuLX^"], + ["@@‚e©Ehl"], + [ + "@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbƒíZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iĠGÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½W—®£ChŒÃsiŒkkly]_teu[bFa‰Tig‡n{]Gqªo‹ĈMYá|·¥f¥—őaSÕė™NµñĞ«ImŒ_m¿Âa]uĜp …Z_§{Cƒäg¤°r[_Yj‰ÆOdý“[ŽI[á·¥“Q_n‡ùgL¾mv™ˊBÜƶĊJhšp“c¹˜O]iŠ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆߎF¶žX®¿‰mŒ™w…RIޓfßoG‘³¾©uyH‘į{Ɓħ¯AFnuP…ÍÔzšŒV—dàôº^Ðæd´€‡oG¤{S‰¬ćxã}›ŧ×Kǥĩ«žÕOEзÖdÖsƘѨ[’Û^Xr¢¼˜§xvěƵ`K”§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē…ßúLÃϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴĖ¶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´" + ] + ], + "encodeOffsets": [[[121722, 32278]], [[119475, 30423]], [[119168, 35472]]] + } + }, + { + "type": "Feature", + "id": "350000", + "properties": { + "id": "350000", + "cp": [118.306239, 26.075302], + "name": "福建", + "childNum": 18 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@“zht´‡]"], + ["@@aj^~ĆG—©O"], + ["@@ed¨„C}}i"], + ["@@@vˆPGsQ"], + ["@@‰sBz‚ddW]Q"], + ["@@SŽ¨Q“{"], + ["@@NŽVucW"], + ["@@qptBAq"], + ["@@‰’¸[mu"], + ["@@Q\\pD]_"], + ["@@jSwUadpF"], + ["@@eXª~ƒ•"], + ["@@AjvFso"], + ["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"], + ["@@IjJi"], + ["@@wJI€ˆxš«¼AoNe{M­"], + ["@@K‰±¡Óˆ”ČäeZ"], + [ + "@@k¡¹Eh~c®wBk‹UplÀ¡I•~Māe£bN¨gZý¡a±Öcp©PhžI”Ÿ¢Qq…ÇGj‹|¥U™ g[Ky¬ŏ–v@OpˆtÉEŸF„\\@ åA¬ˆV{Xģ‰ĐBy…cpě…¼³Ăp·¤ƒ¥o“hqqÚ¡ŅLsƒ^ᗞ§qlŸÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěcݧSùĩąSWó«íęACµ›eR—åǃRCÒÇZÍ¢‹ź±^dlsŒtjD¸•‚ZpužÔâÒH¾oLUêÃÔjjēò´ĄW‚ƛ…^Ñ¥‹ĦŸ@Çò–ŠmŒƒOw¡õyJ†yD}¢ďÑÈġfŠZd–a©º²z£šN–ƒjD°Ötj¶¬ZSÎ~¾c°¶Ðm˜x‚O¸¢Pl´žSL|¥žA†ȪĖM’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ A’†žĬkvsq‡^aÎbvŒd–™fÊòSD€´Z^’xPsÞrv‹ƞŀ˜jJd×ŘÉ ®A–ΦĤd€xĆqAŒ†ZR”ÀMźŒnĊ»ŒİÐZ— YX–æJŠyĊ²ˆ·¶q§·–K@·{s‘Xãô«lŗ¶»o½E¡­«¢±¨Yˆ®Ø‹¶^A™vWĶGĒĢžPlzfˆļŽtàAvWYãšO_‡¤sD§ssČġ[kƤPX¦Ž`¶“ž®ˆBBvĪjv©šjx[L¥àï[F…¼ÍË»ğV`«•Ip™}ccÅĥZE‹ãoP…´B@ŠD—¸m±“z«Ƴ—¿å³BRضˆœWlâþäą`“]Z£Tc— ĹGµ¶H™m@_©—kŒ‰¾xĨ‡ôȉðX«½đCIbćqK³Á‹Äš¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsƒ¥E@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guĮck\\_" + ] + ], + "encodeOffsets": [ + [[123250, 27563]], + [[122541, 27268]], + [[123020, 27189]], + [[122916, 27125]], + [[122887, 26845]], + [[122808, 26762]], + [[122568, 25912]], + [[122778, 26197]], + [[122515, 26757]], + [[122816, 26587]], + [[123388, 27005]], + [[122450, 26243]], + [[122578, 25962]], + [[121255, 25103]], + [[120987, 24903]], + [[122339, 25802]], + [[121042, 25093]], + [[122439, 26024]] + ] + } + }, + { + "type": "Feature", + "id": "360000", + "properties": { + "id": "360000", + "cp": [115.592151, 27.676493], + "name": "江西", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@ĢĨƐgļˆ¼ÂMD~ņªe^\\^§„ý©j׍cZ†Ø¨zdÒa¶ˆlҍJŒìõ`oz÷@¤u޸´†ôęöY¼‰HČƶajlÞƩ¥éZ[”|h}^U Œ ¥p„ĄžƦO lt¸Æ €Q\\€ŠaÆ|CnÂOjt­ĚĤd’ÈŒF`’¶„@Ð딠¦ōҞ¨Sêv†HĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpĠV®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗā¼‹mĉŹ‹¿NQ“…YB‹ąrwģcÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^ķqss¿FūūV՟·´Ç{éĈý‰ÿ›OEˆR_ŸđûIċâJh­ŅıN‘ȩĕB…¦K{Tk³¡OP·wn—µÏd¯}½TÍ«YiµÕsC¯„iM•¤™­•¦¯P|ÿUHv“he¥oFTu‰õ\\ŽOSs‹MòđƇiaºćXŸĊĵà·çhƃ÷ǜ{‘ígu^›đg’m[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²" + ], + "encodeOffsets": [[116689, 26234]] + } + }, + { + "type": "Feature", + "id": "370000", + "properties": { + "id": "370000", + "cp": [118.000923, 36.275807], + "name": "山东", + "childNum": 13 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@Xjd]{K"], + ["@@itbFHy"], + ["@@HlGk"], + ["@@T‚ŒGŸy"], + ["@@K¬˜•‹U"], + ["@@WdXc"], + ["@@PtOs"], + ["@@•LnXhc"], + ["@@ppVƒu]Or"], + ["@@cdzAUa"], + ["@@udRhnCI‡"], + ["@@ˆoIƒpR„"], + [ + "@@Ľč{fzƤî’Kš–ÎMĮ]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞƄLĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌĒœbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐĖ¹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFYŸ¨Mf~C¿`€à_RÇzwƌfQnny´INoƬˆèôº|sT„JUš›‚L„îVj„ǎ¾Ē؍‚Dz²XPn±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«M`‡¶d¡ô‰Ö°šmȰBÔjjŒ´PM|”c^d¤u•ƒ¤Û´Œä«ƢfPk¶Môlˆ]Lb„}su^ke{lC‘…M•rDŠÇ­]NÑFsmoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤ÁçFQ¡„KtŵƋ]CgÏAùSed‡cÚź—ŠuYfƒyMmhUWpSyGwMPqŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕBmœ@Io‚g——Z¯u‹TMx}C‘‰VK‚ï{éƵP—™_K«™pÛÙqċtkkù]gŽ‹Tğwo•ɁsMõ³ă‡AN£™MRkmEʕč™ÛbMjÝGu…IZ™—GPģ‡ãħE[iµBEuŸDPԛ~ª¼ętŠœ]ŒûG§€¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~Ż¸Y’I“] P‰umŝrƿ›‰›Iā‹[x‰edz‹L‘¯v¯s¬ÁY…~}…ťuŁŒg›ƋpÝĄ_ņī¶ÏSR´ÁP~ž¿Cyžċßdwk´Ss•X|t‰`Ä Èð€AªìÎT°¦Dd–€a^lĎDĶÚY°Ž`ĪŴǒˆ”àŠv\\ebŒZH„ŖR¬ŢƱùęO•ÑM­³FۃWp[ƒ" + ] + ], + "encodeOffsets": [ + [[123806, 39303]], + [[123821, 39266]], + [[123742, 39256]], + [[123702, 39203]], + [[123649, 39066]], + [[123847, 38933]], + [[123580, 38839]], + [[123894, 37288]], + [[123043, 36624]], + [[123344, 38676]], + [[123522, 38857]], + [[123628, 38858]], + [[118260, 36742]] + ] + } + }, + { + "type": "Feature", + "id": "410000", + "properties": { + "id": "410000", + "cp": [113.665412, 33.757975], + "name": "河南", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧv~††}ÂZž«¤lPǕ£ªÝŴÅR§ØnhcŒtâk‡nύ­ľŹUÓÝdKuķ‡I§oTũÙďkęĆH¸ÓŒ\\ăŒ¿PcnS{wBIvɘĽ[GqµuŸŇôYgûƒZcaŽ©@½Õǽys¯}lgg@­C\\£as€IdÍuCQñ[L±ęk·‹ţb¨©kK—’»›KC²‘òGKmĨS`ƒ˜UQ™nk}AGē”sqaJ¥ĐGR‰ĎpCuÌy ã iMc”plk|tRk†ðœev~^‘´†¦ÜŽSí¿_iyjI|ȑ|¿_»d}qŸ^{“Ƈdă}Ÿtqµ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½Yŷpµú³XU›½ġy™łå‰kÚwZXˆ·l„¢Á¢K”zO„Λ΀jc¼htoDHr…|­J“½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ…Ťƒ]MÛfaQpě±ǽ¾]u­Fu‹÷nƒ™čįADp}AjmcEǒaª³o³ÆÍSƇĈÙDIzˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝu–”~m²Ƹ›¸fW‰ĦrƔ}Î^gjdfÔ¡J}\\n C˜¦þWxªJRÔŠu¬ĨĨmF†dM{\\d\\ŠYÊ¢ú@@¦ª²SŠÜsC–}fNècbpRmlØ^g„d¢aÒ¢CZˆZxvÆ¶N¿’¢T@€uCœ¬^ĊðÄn|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠŢ`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m" + ], + "encodeOffsets": [[118256, 37017]] + } + }, + { + "type": "Feature", + "id": "420000", + "properties": { + "id": "420000", + "cp": [113.298572, 30.684355], + "name": "湖北", + "childNum": 3 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@AB‚"], + ["@@lskt"], + [ + "@@¾«}{ra®pîÃ\\™›{øCŠËyyB±„b\\›ò˜Ý˜jK›‡L ]ĎĽÌ’JyÚCƈćÎT´Å´pb©È‘dFin~BCo°BĎĚømvŒ®E^vǾ½Ĝ²Ro‚bÜeNŽ„^ĺ£R†¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I”¾®I†{GqpCgyl{‡£œÍƒÍyPL“¡ƒ¡¸kW‡xYlÙ抚ŁĢzœ¾žV´W¶ùŸo¾ZHxjwfx„GNÁ•³Xéæl¶‰EièIH‰ u’jÌQ~v|sv¶Ôi|ú¢Fh˜Qsğ¦ƒSiŠBg™ÐE^ÁÐ{–čnOÂȞUÎóĔ†ÊēIJ}Z³½Mŧïeyp·uk³DsѨŸL“¶_œÅuèw»—€¡WqÜ]\\‘Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟO‡ƒKÉġÿ×wg”÷IÅzCg†]m«ªGeçÃTC’«[‰t§{loWeC@ps_Bp‘­r‘„f_``Z|ei¡—oċMqow€¹DƝӛDYpûs•–‹Ykıǃ}s¥ç³[§ŸcYŠ§HK„«Qy‰]¢“wwö€¸ïx¼ņ¾Xv®ÇÀµRĠЋžHMž±cÏd„ƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy…¿³x¯N‰o‰|¹H™ÏÛm‹júË~Tš•u˜ęjCöAwě¬R’đl¯ Ñb­‰ŇT†Ŀ_[Œ‘IčĄʿnM¦ğ\\É[T·™k¹œ©oĕ@A¾w•ya¥Y\\¥Âaz¯ãÁ¡k¥ne£Ûw†E©Êō¶˓uoj_Uƒ¡cF¹­[Wv“P©w—huÕyBF“ƒ`R‹qJUw\\i¡{jŸŸEPïÿ½fć…QÑÀQ{ž‚°‡fLԁ~wXg—ītêݾ–ĺ‘Hdˆ³fJd]‹HJ²…E€ƒoU¥†HhwQsƐ»Xmg±çve›]Dm͂PˆoCc¾‹_h”–høYrŊU¶eD°Č_N~øĹĚ·`z’]Äþp¼…äÌQŒv\\rCŒé¾TnkžŐڀÜa‡“¼ÝƆĢ¶Ûo…d…ĔňТJq’Pb ¾|JŒ¾fXŠƐîĨ_Z¯À}úƲ‹N_ĒĊ^„‘ĈaŐyp»CÇĕKŠšñL³ŠġMŒ²wrIÒŭxjb[œžn«øœ˜—æˆàƒ ^²­h¯Ú€ŐªÞ¸€Y²ĒVø}Ā^İ™´‚LŠÚm„¥ÀJÞ{JVŒųÞŃx×sxxƈē ģMř–ÚðòIf–Ċ“Œ\\Ʈ±ŒdʧĘD†vČ_Àæ~DŒċ´A®µ†¨ØLV¦êHÒ¤" + ] + ], + "encodeOffsets": [[[113712, 34000]], [[115612, 30507]], [[113649, 34054]]] + } + }, + { + "type": "Feature", + "id": "430000", + "properties": { "id": "430000", "cp": [111.782279, 28.09409], "name": "湖南", "childNum": 3 }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@—n„FTs"], + ["@@ßÅÆችÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–Ģ¾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"], + [ + "@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…HËѱH•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJĪ²SÊDŽŶ¨ƚƒ’CÖŎªQؼrŭŽ­«}NÏürʬŒmjr€@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hTœ}mĉ–¹¥ě‰Dÿë©ıÓ[Oº£ž“¥ót€ł¹MՄžƪƒ`Pš…Di–ÛUŠ¾Å‌ìˆU’ñB“È£ýhe‰dy¡oċ€`pfmjP~‚kZa…ZsÐd°wj§ƒ@€Ĵ®w~^‚kÀÅKvNmX\\¨a“”сqvíó¿F„¤¡@ũÑVw}S@j}¾«pĂr–ªg àÀ²NJ¶¶Dô…K‚|^ª†Ž°LX¾ŴäPĪ±œ£EXd›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈĀ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎŪƒƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGġu…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ" + ] + ], + "encodeOffsets": [[[115640, 30489]], [[112543, 27312]], [[116690, 26230]]] + } + }, + { + "type": "Feature", + "id": "440000", + "properties": { + "id": "440000", + "cp": [113.280637, 23.125178], + "name": "广东", + "childNum": 24 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@QdˆAua"], + ["@@ƒlxDLo"], + ["@@sbhNLo"], + ["@@Ă āŸ"], + ["@@WltO[["], + ["@@Krœ]S"], + ["@@e„„I]y"], + ["@@I|„Mym"], + ["@@ƒÛ³LSŒž¼Y"], + ["@@nvºB–ëui©`¾"], + ["@@zdšÛ›Jw®"], + ["@@†°…¯"], + ["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"], + ["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"], + ["@@‹¶Ý’Ì‚vmĞh­ı‡Q"], + ["@@HœŠdSjĒ¢D}war…“u«ZqadYM"], + ["@@elŒ\\LqqU"], + ["@@~rMo\\"], + ["@@f„^ƒC"], + ["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"], + ["@@gÇƳˆŽˆ”oˆŠˆ[~tly"], + ["@@E–ÆC¿‘"], + ["@@OŽP"], + [ + "@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£L]ĈÙƺZǾĆĖMĸĤfŒÎĵl•ŨnȈ‘ĐtF”Š–FĤ–‚êk¶œ^k°f¶gŠŽœ}®Fa˜f`vXŲxl˜„¦–ÔÁ²¬ÐŸ¦pqÊ̲ˆi€XŸØRDÎ}†Ä@ZĠ’s„x®AR~®ETtĄZ†–ƈfŠŠHâÒÐA†µ\\S¸„^wĖkRzŠalŽŜ|E¨ÈNĀňZTŒ’pBh£\\ŒĎƀuXĖtKL–¶G|Ž»ĺEļĞ~ÜĢÛĊrˆO˜Ùîvd]nˆ¬VœÊĜ°R֟pM††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thœ†_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéʌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñiiÄÓVépKG½Ä‘ÓávYo–C·sit‹iaÀy„ŧΡÈYDÑům}‰ý|m[węõĉZÅxUO}÷N¹³ĉo_qtă“qwµŁYلǝŕ¹tïÛUïmRCº…ˆĭ|µ›ÕÊK™½R‘ē ó]‘–GªęAx–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i" + ] + ], + "encodeOffsets": [ + [[117381, 22988]], + [[116552, 22934]], + [[116790, 22617]], + [[116973, 22545]], + [[116444, 22536]], + [[116931, 22515]], + [[116496, 22490]], + [[116453, 22449]], + [[113301, 21439]], + [[118726, 21604]], + [[118709, 21486]], + [[113210, 20816]], + [[115482, 22082]], + [[113171, 21585]], + [[113199, 21590]], + [[115232, 22102]], + [[115739, 22373]], + [[115134, 22184]], + [[113056, 21175]], + [[119573, 21271]], + [[119957, 24020]], + [[115859, 22356]], + [[116561, 22649]], + [[116285, 22746]] + ] + } + }, + { + "type": "Feature", + "id": "450000", + "properties": { "id": "450000", "cp": [108.320004, 22.82402], "name": "广西", "childNum": 2 }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@H– TQ§•A"], + [ + "@@ĨʪƒLƒƊDÎĹĐCǦė¸zÚGn£¾›rªŀÜt¬@֛ڈSx~øOŒ˜ŶÐÂæȠ\\„ÈÜObĖw^oބLf¬°bI lTØB̈F£Ć¹gñĤaY“t¿¤VSñœK¸¤nM†¼‚JE±„½¸šŠño‹ÜCƆæĪ^ŠĚQÖ¦^‡ˆˆf´Q†üÜʝz¯šlzUĺš@쇀p¶n]sxtx¶@„~ÒĂJb©gk‚{°‚~c°`ԙ¬rV\\“la¼¤ôá`¯¹LC†ÆbŒxEræO‚v[H­˜„[~|aB£ÖsºdAĐzNÂðsŽÞƔ…Ĥªbƒ–ab`ho¡³F«èVloŽ¤™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆƌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}FĻ¼Ĺ{µHK•sLSđƃr‹č¤[Ag‘oS‹ŇYMÿ§Ç{Fśbky‰lQxĕƒ]T·¶[B…ÑÏGáşşƇe€…•ăYSs­FQ}­Bƒw‘tYğÃ@~…C̀Q ×W‡j˱rÉ¥oÏ ±«ÓÂ¥•ƒ€k—ŽwWűŒmcih³K›~‰µh¯e]lµ›él•Eģ‰•E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵűMę§]X˜Î_‚훘Û]é’ÛUćİÕBƣ±…dƒy¹T^džûÅÑŦ·‡PĻþÙ`K€¦˜…¢ÍeœĥR¿Œ³£[~Œäu¼dl‰t‚†W¸oRM¢ď\\zœ}Æzdvň–{ÎXF¶°Â_„ÒÂÏL©Ö•TmuŸ¼ãl‰›īkiqéfA„·Êµ\\őDc¥ÝF“y›Ôć˜c€űH_hL܋êĺШc}rn`½„Ì@¸¶ªVLŒŠhŒ‹\\•Ţĺk~ŽĠið°|gŒtTĭĸ^x‘vK˜VGréAé‘bUu›MJ‰VÃO¡…qĂXËS‰ģãlýàŸ_ju‡YÛÒB†œG^˜é֊¶§ŽƒEG”ÅzěƒƯ¤Ek‡N[kdåucé¬dnYpAyČ{`]þ¯T’bÜÈk‚¡Ġ•vŒàh„ÂƄ¢J" + ] + ], + "encodeOffsets": [[[111707, 21520]], [[107619, 25527]]] + } + }, + { + "type": "Feature", + "id": "460000", + "properties": { "id": "460000", "cp": [109.83119, 19.031971], "name": "海南", "childNum": 1 }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ " + ], + "encodeOffsets": [[112750, 20508]] + } + }, + { + "type": "Feature", + "id": "510000", + "properties": { + "id": "510000", + "cp": [104.065735, 30.659462], + "name": "四川", + "childNum": 2 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@LqKr"], + [ + "@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iÇ°ÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿw…ZG……Ti‹SˆsO‰žB²ŸfNmsPaˆ{M{ŠõE‘^Hj}gYpaeuž¯‘oáwHjÁ½M¡pM“–uå‡mni{fk”\\oƒÎqCw†EZ¼K›ĝŠƒAy{m÷L‡wO×SimRI¯rK™õBS«sFe‡]fµ¢óY_ÆPRcue°Cbo׌bd£ŌIHgtrnyPt¦foaXďx›lBowz‹_{ÊéWiêE„GhܸºuFĈIxf®Ž•Y½ĀǙ]¤EyŸF²ċ’w¸¿@g¢§RGv»–áŸW`ÃĵJwi]t¥wO­½a[׈]`Ãi­üL€¦LabbTÀå’c}Íh™Æhˆ‹®BH€î|Ék­¤S†y£„ia©taį·Ɖ`ō¥Uh“O…ƒĝLk}©Fos‰´›Jm„µlŁu—…ø–nÑJWΪ–YÀïAetTžŅ‚ӍG™Ë«bo‰{ıwodƟ½ƒžOġܑµxàNÖ¾P²§HKv¾–]|•B‡ÆåoZ`¡Ø`ÀmºĠ~ÌЧnDž¿¤]wğ@sƒ‰rğu‰~‘Io”[é±¹ ¿žſđӉ@q‹gˆ¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@ỗs›Zϕ‹œÅĭ€Ƌ•ěpwDóÖሯneQˌq·•GCœýS]xŸ·ý‹q³•O՜Œ¶Qzßti{ř‰áÍÇWŝŭñzÇW‹pç¿JŒ™‚Xœĩè½cŒF–ÂLiVjx}\\N†ŇĖ¥Ge–“JA¼ÄHfÈu~¸Æ«dE³ÉMA|b˜Ò…˜ćhG¬CM‚õŠ„ƤąAvƒüV€éŀ‰_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»Ÿ“˜ÕZ³ġqDo‰y`L¬gdp°şŠp¦ėìÅĮZŽ°Iä”h‚‘ˆzŠĵœf²å ›ĚрKp‹IN|‹„Ñz]ń……·FU×é»R³™MƒÉ»GM«€ki€™ér™}Ã`¹ăÞmȝnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ…þTº·àUȞÏʦ¶†I’«dĽĢdĬ¿–»Ĕ׊h\\c¬†ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvw–ˆxBèĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄmÀêErĒtD®ċæcQƒ”E®³^ĭ¥©l}äQto˜ŖÜqƎkµ–„ªÔĻĴ¡@Ċ°B²Èw^^RsºTĀ£ŚæœQP‘JvÄz„^Đ¹Æ¯fLà´GC²‘dt˜­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïžPȆ®âbMüÀXZ ¸£@Ś›»»QÉ­™]d“sÖ×_͖_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|Y‹Ô‚ZśÎs´xº±UŒ’ñˆt|O’ĩĠºNbgþŠJy^dÂY Į„]Řz¦gC‚³€R`ĀŠz’¢AjŒ¸CL„¤RÆ»@­Ŏk\\Ç´£YW}z@Z}‰Ã¶“oû¶]´^N‡Ò}èN‚ª–P˜Íy¹`S°´†ATe€VamdUĐwʄvĮÕ\\ƒu‹Æŗ¨Yp¹àZÂm™Wh{á„}WØǍ•Éüw™ga§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆL€ÜUÖ´òrÙŠxR^–†J˜k„ijnDX{Uƒ~ET{ļº¦PZc”jF²Ė@Žp˜g€ˆ¨“B{ƒu¨ŦyhoÚD®¯¢˜ WòàFΤ¨GDäz¦kŮPœġq˚¥À]€Ÿ˜eŽâÚ´ªKxī„Pˆ—Ö|æ[xäJÞĥ‚s’NÖ½ž€I†¬nĨY´®Ð—ƐŠ€mD™ŝuäđđEb…e’e_™v¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›" + ] + ], + "encodeOffsets": [[[108815, 30935]], [[110617, 31811]]] + } + }, + { + "type": "Feature", + "id": "520000", + "properties": { + "id": "520000", + "cp": [106.713478, 26.578343], + "name": "贵州", + "childNum": 3 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@†G\\†lY£‘in"], + ["@@q‚|ˆ‚mc¯tχVSÎ"], + [ + "@@hÑ£Is‡NgßH†›HªķÃh_¹ƒ¡ĝħń¦uيùŽgS¯JHŸ|sÝÅtÁïyMDč»eÕtA¤{b\\}—ƒG®u\\åPFq‹wÅaD…žK°ºâ_£ùbµ”mÁ‹ÛœĹM[q|hlaªāI}тƒµ@swtwm^oµˆD鼊yV™ky°ÉžûÛR…³‚‡eˆ‡¥]RՋěħ[ƅåÛDpŒ”J„iV™™‰ÂF²I…»mN·£›LbÒYb—WsÀbŽ™pki™TZĄă¶HŒq`……ĥ_JŸ¯ae«ƒKpÝx]aĕÛPƒÇȟ[ÁåŵÏő—÷Pw}‡TœÙ@Õs«ĿÛq©½œm¤ÙH·yǥĘĉBµĨÕnđ]K„©„œá‹ŸG纍§Õßg‡ǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊžw¶øV¤w”²Ĉ]ʚKx|`ź¦ÂÈdr„cȁbe¸›`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pН`oÒhŽ¶pa‚^ÓĔ}D»^Xyœ`d˜[Kv…JPhèhCrĂĚÂ^Êƌ wˆZL­Ġ£šÁbrzOIl’MM”ĪŐžËr×ÎeŦŽtw|Œ¢mKjSǘňĂStÎŦEtqFT†¾†E쬬ôxÌO¢Ÿ KŠ³ŀºäY†„”PVgŎ¦Ŋm޼VZwVlŒ„z¤…ž£Tl®ctĽÚó{G­A‡ŒÇgeš~Αd¿æaSba¥KKûj®_ć^\\ؾbP®¦x^sxjĶI_Ä X‚⼕Hu¨Qh¡À@Ëô}Ž±žGNìĎlT¸ˆ…`V~R°tbÕĊ`¸úÛtπFDu€[ƒMfqGH·¥yA‰ztMFe|R‚_Gk†ChZeÚ°to˜v`x‹b„ŒDnÐ{E}šZ˜è€x—†NEފREn˜[Pv@{~rĆAB§‚EO¿|UZ~ì„Uf¨J²ĂÝƀ‚sª–B`„s¶œfvö¦ŠÕ~dÔq¨¸º»uù[[§´sb¤¢zþFœ¢Æ…Àhˆ™ÂˆW\\ıŽËI݊o±ĭŠ£þˆÊs}¡R]ŒěƒD‚g´VG¢‚j±®è†ºÃmpU[Á›‘Œëº°r›ÜbNu¸}Žº¼‡`ni”ºÔXĄ¤¼Ôdaµ€Á_À…†ftQQgœR—‘·Ǔ’v”}Ýלĵ]µœ“Wc¤F²›OĩųãW½¯K‚©…]€{†LóµCIµ±Mß¿hŸ•©āq¬o‚½ž~@i~TUxŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½" + ] + ], + "encodeOffsets": [[[112158, 27383]], [[112105, 27474]], [[112095, 27476]]] + } + }, + { + "type": "Feature", + "id": "530000", + "properties": { + "id": "530000", + "cp": [101.512251, 24.740609], + "name": "云南", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@[„ùx½}ÑRH‘YīĺûsÍn‘iEoã½Ya²ė{c¬ĝg•ĂsA•ØÅwď‚õzFjw}—«Dx¿}UũlŸê™@•HÅ­F‰¨ÇoJ´Ónũuą¡Ã¢pÒŌ“Ø TF²‚xa²ËX€‚cʋlHîAßËŁkŻƑŷÉ©h™W­æßU‡“Ës¡¦}•teèƶStǀÇ}Fd£j‹ĈZĆÆ‹¤T‚č\\Dƒ}O÷š£Uˆ§~ŃG™‚åŃDĝ¸œTsd¶¶Bªš¤u¢ŌĎo~t¾ÍŶÒtD¦Ú„iôö‰€z›ØX²ghįh½Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†cÚbŒw\\zlvWžªâˆ ¦g–mĿBş£¢ƹřbĥkǫßeeZkÙIKueT»sVesb‘aĕ  ¶®dNœĄÄpªyŽ¼—„³BE˜®l‡ŽGœŭCœǶwêżĔÂe„pÍÀQƞpC„–¼ŲÈ­AÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“Æ´sâDŽŲPnÊD^¯°’Upv†}®BP̪–jǬx–Söwlfòªv€qĸ|`H€­viļ€ndĜ­Ćhň•‚em·FyށqóžSį¯‘³X_ĞçêtryvL¤§z„¦c¦¥jnŞk˜ˆlD¤øz½ĜàžĂŧMÅ|áƆàÊcðÂF܎‚áŢ¥\\\\º™İøÒÐJĴ‡„îD¦zK²ǏÎEh~’CD­hMn^ÌöÄ©ČZÀžaü„fɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~Äqššê€ljN¬¼H„ÊšNQ´ê¼VظE††^ŃÒyŒƒM{ŒJLoÒœęæŸe±Ķ›y‰’‡gã“¯JYÆĭĘëo¥Š‰o¯hcK«z_pŠrC´ĢÖY”—¼ v¸¢RŽÅW³Â§fǸYi³xR´ďUˊ`êĿU„û€uĆBƒƣö‰N€DH«Ĉg†——Ñ‚aB{ÊNF´¬c·Åv}eÇÃGB»”If•¦HňĕM…~[iwjUÁKE•Ž‹¾dĪçW›šI‹èÀŒoÈXòyŞŮÈXâÎŚŠj|àsRy‹µÖ›–Pr´þŒ ¸^wþTDŔ–Hr¸‹žRÌmf‡żÕâCôox–ĜƌÆĮŒ›Ð–œY˜tâŦÔ@]ÈǮƒ\\Ī¼Ä£UsȯLbîƲŚºyh‡rŒŠ@ĒԝƀŸÀ²º\\êp“’JŠ}ĠvŠqt„Ġ@^xÀ£È†¨mËÏğ}n¹_¿¢×Y_æpˆÅ–A^{½•Lu¨GO±Õ½ßM¶w’ÁĢۂP‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡n{‹uxţÏh™ôŝ¬ğōN“‘NJkyPaq™Âğ¤K®‡YŸxÉƋÁ]āęDqçgOg†ILu—\\_gz—]W¼ž~CÔē]bµogpў_oď`´³Țkl`IªºÎȄqÔþž»E³ĎSJ»œ_f·‚adÇqƒÇc¥Á_Źw{™L^ɱćx“U£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣG˛÷Ÿk°_^ý|_zċBZocmø¯hhcæ\\lˆMFlư£Ĝ„ÆyH“„F¨‰µêÕ]—›HA…àӄ^it `þßäkŠĤÎT~Wlÿ¨„ÔPzUC–NVv [jâôDôď[}ž‰z¿–msSh‹¯{jïğl}šĹ[–őŒ‰gK‹©U·µË@¾ƒm_~q¡f¹…ÅË^»‘f³ø}Q•„¡Ö˳gͱ^ǁ…\\ëÃA_—¿bW›Ï[¶ƛ鏝£F{īZgm@|kHǭƁć¦UĔťƒ×ë}ǝƒeďºȡȘÏíBə£āĘPªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`" + ], + "encodeOffsets": [[104636, 22969]] + } + }, + { + "type": "Feature", + "id": "540000", + "properties": { "id": "540000", "cp": [89.132212, 30.860361], "name": "西藏", "childNum": 1 }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@hžľxŽŖ‰xƒÒVŽ†ºÅâAĪÝȆµę¯Ňa±r_w~uSÕň‘qOj]ɄQ…£Z……UDûoY’»©M[‹L¼qãË{V͕çWViŽ]ë©Ä÷àyƛh›ÚU°ŒŒa”d„cQƒ~Mx¥™cc¡ÙaSyF—ցk­ŒuRýq¿Ôµ•QĽ³aG{¿FµëªéĜÿª@¬·–K‰·àariĕĀ«V»Ŷ™Ĵū˜gèLǴŇƶaf‹tŒèBŚ£^Šâ†ǐÝ®–šM¦ÁǞÿ¬LhŸŽJ¾óƾƺcxw‹f]Y…´ƒ¦|œQLn°aœdĊ…œ\\¨o’œǀÍŎœ´ĩĀd`tÊQŞŕ|‚¨C^©œĈ¦„¦ÎJĊ{ŽëĎjª²rЉšl`¼Ą[t|¦St辉PŒÜK¸€d˜Ƅı]s¤—î_v¹ÎVòŦj˜£Əsc—¬_Ğ´|Ł˜¦AvŽ¦w`ăaÝaa­¢e¤ı²©ªSªšÈMĄwžÉØŔì@T‘¤—Ę™\\õª@”þo´­xA s”ÂtŎKzó´ÇĊµ¢rž^nĊ­Æ¬×üGž¢‚³ {âĊ]š™G‚~bÀgVjzlhǶf€žOšfdŠ‰ªB]pj„•TO–tĊ‚n¤}®¦ƒČ¥d¢¼»ddš”Y¼Žt—¢eȤJ¤}Ǿ¡°§¤AГlc@ĝ”sªćļđAç‡wx•UuzEÖġ~AN¹ÄÅȀŻ¦¿ģŁéì±H…ãd«g[؉¼ēÀ•cīľġ¬cJ‘µ…ÐʥVȝ¸ßS¹†ý±ğkƁ¼ą^ɛ¤Ûÿ‰b[}¬ōõÃ]ËNm®g@•Bg}ÍF±ǐyL¥íCˆƒIij€Ï÷њį[¹¦[⚍EÛïÁÉdƅß{âNÆāŨߝ¾ě÷yC£‡k­´ÓH@¹†TZ¥¢įƒ·ÌAЧ®—Zc…v½ŸZ­¹|ŕWZqgW“|ieZÅYVӁqdq•bc²R@†c‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnwôɍėªƒ²•CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛ†ęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷‡f±iMݑ›‰@ĥ°G¬ÃM¥n£Øą‚ğ¯ß”§aëbéüÑOčœk£{\\‘eµª×M‘šÉfm«Ƒ{Å׃Gŏǩãy³©WÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔTŘvŽgÌsN@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxq¹Zo‘b‹s[׌¯cĩv‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRS~½ŠěVVŠµ‚õ‡«ŒM££µB•ĉ¥áºae~³AuĐh`Ü³ç@BۘïĿa©|z²Ý¼D”£àč²‹ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaň¨€~ªSĈ½Ž½KÙóĿeƃÆBŽ·¬ën×W|Uº}LJrƳ˜lŒµ`bÔ`QˆˆÐÓ@s¬ñIŒÍ@ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSij‚‹Yo|Ç[ǾµMW¢ĭiÕØ¿@˜šMh…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB™Š\\”qTGªÇĜçPoŠÿfñòą¦óQīÈáP•œābß{ƒZŗĸIæńhnszÁCËìñšÏ·ąĚÝUm®ó­L·ăU›Èíoù´Êj°ŁŤ_uµ^‘°Œìǖ@tĶĒ¡Æ‡M³Ģ«˜İĨÅ®ğ†RŽāð“ggheÆ¢z‚Ê©Ô\\°ÝĎz~ź¤Pn–MĪÖB£Ÿk™n鄧żćŠ˜ĆK„Ē°¼L¶è‰âz¨u¦¥LDĘz¬ýÎmĘd¾ß”Fz“hg²™Fy¦ĝ¤ċņbΛ@y‚Ąæm°NĮZRÖíŽJ²öLĸÒ¨Y®ƌÐV‰à˜tt_ڀÂyĠzž]Ţh€zĎ{†ĢX”ˆc|šÐqŽšfO¢¤ög‚ÌHNŽ„PKŖœŽ˜Uú´xx[xˆvĐCûĀŠìÖT¬¸^}Ìsòd´_Ž‡KgžLĴ…ÀBon|H@–Êx˜—¦BpŰˆŌ¿fµƌA¾zLjRxŠ¶F”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdžB’šú^´W†£–d„kɾĬpœw‚˂ØɦļĬIŚœÊ•n›Ŕa¸™~J°î”lɌxĤÊÈðhÌ®‚g˜T´øŽàCˆŽÀ^ªerrƘdž¢İP|Ė ŸWœªĦ^¶´ÂL„aT±üWƜ˜ǀRšŶUńšĖ[QhlLüA†‹Ü\\†qR›Ą©" + ], + "encodeOffsets": [[90849, 37210]] + } + }, + { + "type": "Feature", + "id": "610000", + "properties": { + "id": "610000", + "cp": [108.948024, 34.263161], + "name": "陕西", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópģ}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[€É@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭO¥lãyC§HÍ£ßEñŸX¡—­°ÙCgpťz‘ˆb`wI„vA|§”‡—hoĕ@E±“iYd¥OĻ¹S|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤh^Wx{@„¬‚­F¸¡„ķn£P|ŸªĴ@^ĠĈæb–Ôc¶l˜Yi…–^Mi˜cĎ°Â[ä€vï¶gv@À“Ĭ·lJ¸sn|¼u~a]’ÆÈtŌºJp’ƒþ£KKf~Š¦UbyäIšĺãn‡Ô¿^­žŵMT–hĠܤko¼Ŏìąǜh`[tŒRd²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj" + ], + "encodeOffsets": [[110234, 38774]] + } + }, + { + "type": "Feature", + "id": "620000", + "properties": { + "id": "620000", + "cp": [103.823557, 36.058039], + "name": "甘肃", + "childNum": 2 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@VuUv"], + [ + "@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡ŠjΑBŠ°aZˆ¢KJŽ’O[|A£žDx}Nì•HUnrk„ kp€¼Y kMJn[aG‚áÚÏ[½rc†}aQxOgsPMnUs‡nc‹Z…ž–sKúvA›t„Þġ’£®ĀYKdnFwš¢JE°”Latf`¼h¬we|€Æ‡šbj}GA€·~WŽ”—`†¢MC¤tL©IJ°qdf”O‚“bÞĬ¹ttu`^ZúE`Œ[@„Æsîz®¡’C„ƳƜG²“R‘¢R’m”fŽwĸg܃‚ą G@pzJM½mŠhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬‡²I‚¥IʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\a­‹Q\\sg_ĆǛōëp»£lğۀgS•ŶN®À]ˆÓäm™ĹãJaz¥V}‰Le¤L„ýo‘¹IsŋÅÇ^‘Žbz…³tmEÁ´aŠ¹cčecÇN•ĊãÁ\\č¯—dNj•]j†—ZµkÓda•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]Aģ±¯‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V¬âDb¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…B¯³_Tzº—ΕO©çMÑ~Mˆ³]µ^püµ”ŠÄY~y@X~¤Z³€[Èōl@®Å¼£QKƒ·Di‹¡By‘ÿ‰Q_´D¥hŗyƒ^ŸĭÁZ]cIzý‰ah¹MĪğP‘s{ò‡‹‘²Vw¹t³Ŝˁ[ŽÑ}X\\gsFŸ£sPAgěp×ëfYHāďÖqēŭOÏë“dLü•\\iŒ”t^c®šRʺ¶—¢H°mˆ‘rYŸ£BŸ¹čIoľu¶uI]vģSQ{ƒUŻ”Å}QÂ|̋°ƅ¤ĩŪU ęĄžÌZҞ\\v˜²PĔ»ƢNHƒĂyAmƂwVmž`”]ȏb•”H`‰Ì¢²ILvĜ—H®¤Dlt_„¢JJÄämèÔDëþgºƫ™”aʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b…ð÷’Žˆ‡®‚”üs”zMzÖĖQdȨý†v§Tè|ªH’þa¸|šÐ ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v†·À|\\ƁĚN´Ĝ€çèÁz]ġ¤²¨QÒŨTIl‡ªťØ}¼˗ƦvÄùØE‹’«Fï˛Iq”ōŒTvāÜŏ‚íÛߜÛV—j³âwGăÂíNOŠˆŠPìyV³ʼnĖýZso§HіiYw[߆\\X¦¥c]ÔƩÜ·«j‡ÐqvÁ¦m^ċ±R™¦΋ƈťĚgÀ»IïĨʗƮŽ°Ɲ˜ĻþÍAƉſ±tÍEÕÞāNU͗¡\\ſčåÒʻĘm ƭÌŹöʥ’ëQ¤µ­ÇcƕªoIýˆ‰Iɐ_mkl³ă‰Ɠ¦j—¡Yz•Ňi–}Msßõ–īʋ —}ƒÁVmŸ_[n}eı­Uĥ¼‘ª•I{ΧDӜƻėoj‘qYhĹT©oūĶ£]ďxĩ‹ǑMĝ‰q`B´ƃ˺Ч—ç~™²ņj@”¥@đ´ί}ĥtPńǾV¬ufӃÉC‹tÓ̻‰…¹£G³€]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼ‚ĤŊɲĖ­Kq´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY…tÁƤyAã˾J@ǝrý‹‰@¤…rz¸oP¹ɐÚyᐇHŸĀ[Jw…cVeȴϜ»ÈŽĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔ—ĹŊũ~ËUă{ŸĻƹɁύȩþĽvĽƓÉ@ē„ĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶Ž¨c~c¼īŒeXǚ‹\\đ¾JŽwÀďksãA‹fÕ¦L}wa‚o”Z’‹D½†Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LF‹LzĈ„ôe]gx}•|KK}xklL]c¦£fRtív¦†PĤoH{tK" + ] + ], + "encodeOffsets": [[[108619, 36299]], [[108589, 36341]]] + } + }, + { + "type": "Feature", + "id": "630000", + "properties": { "id": "630000", "cp": [96.778916, 35.623178], "name": "青海", "childNum": 2 }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@InJm"], + [ + "@@CƒÆ½OŃĦsΰ~Ē³¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNĪŒĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~f\\m `Un„˜~ʌŸ•ĬàöNt•~ňjy–¢Zi˜Ɣ¥ĄŠk´nl`JʇŠJþ©pdƖ®È£¶ìRʦ‘źõƮËnŸʼėæÑƀĎ[‚˜¢VÎĂMÖÝÎF²sƊƀÎBļýƞ—¯ʘƭðħ¼Jh¿ŦęΌƇš¥²Q]Č¥nuÂÏriˆ¸¬ƪÛ^Ó¦d€¥[Wà…x\\ZŽjҕ¨GtpþYŊĕ´€zUO뇉P‰îMĄÁxH´á˜iÜUà›îÜՁĂÛSuŎ‹r“œJð̬EŒ‘FÁú×uÃÎkr“Ē{V}İ«O_ÌËĬ©ŽÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u…ºµ[gt£¸OƤĿéYŸõ·kĀŸq]juw¥Dĩƍ€õÇPéĽG‘ž©ã‡¤G…uȧþRcÕĕNy“yût“ˆ­‡ø‘†ï»a½ē¿BMoį£ŸÍj}éZËqbʍš“Ƭh¹ìÿÓAçãnIáI`ƒks£CG­ě˜Uy×Cy•…’Ÿ@¶ʡÊBnāzG„ơMē¼±O÷õJËĚăVŸĪũƆ£Œ¯{ËL½Ìzż“„VR|ĠTbuvJvµhĻĖH”Aëáa…­OÇðñęNw‡…œľ·L›mI±íĠĩPÉ×®ÿs—’cB³±JKßĊ«`…ađ»·QAmO’‘Vţéÿ¤¹SQt]]Çx€±¯A@ĉij¢Óļ©•ƒl¶ÅÛr—ŕspãRk~¦ª]Į­´“FR„åd­ČsCqđéFn¿Åƃm’Éx{W©ºƝºįkÕƂƑ¸wWūЩÈFž£\\tÈ¥ÄRÈýÌJ ƒlGr^×äùyÞ³fj”c†€¨£ÂZ|ǓMĝšÏ@ëÜőR‹›ĝ‰Œ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³’­ÞIňµç½©C¡į÷¯B»|St»›]vƒųƒs»”}MÓ ÿʪƟǭA¡fs˜»PY¼c¡»¦c„ċ­¥£~msĉP•–Siƒ^o©A‰Šec‚™PeǵŽkg‚yUi¿h}aH™šĉ^|ᴟ¡HØûÅ«ĉ®]m€¡qĉ¶³ÈyôōLÁst“BŸ®wn±ă¥HSòėš£˜S’ë@לÊăxÇN©™©T±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›R¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snåA{‹eŒƭ`ǻŊĿ\\ijŬű”YÂÿ¬jĖqŽßbŠ¸•L«¸©@ěĀ©ê¶ìÀEH|´bRľž–Ó¶rÀQþ‹vl®Õ‚E˜TzÜdb ˜hw¤{LR„ƒd“c‹b¯‹ÙVgœ‚ƜßzÃô쮍^jUèXΖ|UäÌ»rKŽ\\ŒªN‘¼pZCü†VY††¤ɃRi^rPҒTÖ}|br°qňbĚ°ªiƶGQ¾²„x¦PœmlŜ‘[Ĥ¡ΞsĦŸÔÏâ\\ªÚŒU\\f…¢N²§x|¤§„xĔsZPòʛ²SÐqF`ª„VƒÞŜĶƨVZŒÌL`ˆ¢dŐIqr\\oäõ–F礻Ŷ×h¹]Clـ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ”´ÃbEÄlbʔC”|CˆŮˆk„Ʈ[ʼ¬ňœ´KŮÈΰÌĪ¶ƶlð”ļA†TUvdTŠG†º̼ŠÔ€ŒsÊDԄveOg" + ] + ], + "encodeOffsets": [[[105308, 37219]], [[95370, 40081]]] + } + }, + { + "type": "Feature", + "id": "640000", + "properties": { "id": "640000", "cp": [106.278179, 37.26637], "name": "宁夏", "childNum": 2 }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + "@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™ĚQÐZhv K°›öqÀѐS[ÃÖHƖčË‡nL]ûc…Ùß@‚“ĝ‘¾}w»»‹oģF¹œ»kÌÏ·{zPƒ§B­¢íyÅt@ƒ@áš]Yv_ssģ¼i߁”ĻL¾ġsKD£¡N_…“˜X¸}B~Haiˆ™Åf{«x»ge_bs“KF¯¡Ix™mELcÿZ¤­Ģ‘ƒÝœsuBLù•t†ŒYdˆmVtNmtOPhRw~bd…¾qÐ\\âÙH\\bImlNZŸ»loƒŸqlVm–Gā§~QCw¤™{A\\‘PKŸNY‡¯bF‡kC¥’sk‹Šs_Ã\\ă«¢ħkJi¯r›rAhĹûç£CU‡ĕĊ_ԗBixÅُĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~–hw^‚ófćƒKyEŒ­K­zuÔ¡qQ¤xZÑ¢^ļöܾEpž±âbÊÑÆ^fk¬…NC¾‘Œ“YpxbK~¥Že֎ŒäBlt¿Đx½I[ĒǙŒWž‹f»Ĭ}d§dµùEuj¨‚IÆ¢¥dXªƅx¿]mtÏwßRĶŒX¢͎vÆzƂZò®ǢÌʆCrâºMÞzžÆMҔÊÓŊZľ–r°Î®Ȉmª²ĈUªĚøºˆĮ¦ÌĘk„^FłĬhĚiĀĖ¾iİbjÕ" + ], + ["@@mfwěwMrŢªv@G‰"] + ], + "encodeOffsets": [[[109366, 40242]], [[108600, 36303]]] + } + }, + { + "type": "Feature", + "id": "650000", + "properties": { "id": "650000", "cp": [85.617733, 40.792818], "name": "新疆", "childNum": 1 }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@QØĔ²X¨”~ǘBºjʐßØvK”ƔX¨vĊOžÃƒ·¢i@~c—‡ĝe_«”Eš“}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX…ê•Îf`œC‚¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥Oéȇ¿ÖğǤǷÂF҇zÉx[]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±’ēO…¦E–•}‘`cȺrĦáŖuҞª«IJ‡πdƺÏØZƴwʄ¤ĖGЙǂZĶƒèH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYwē¨ƒ{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷QyŠěCFmĭZī—ŵVÁ™ƿQƛ—ûXS²‰b½KϽĉS›©ŷXĕŸ{ŽĕK·¥Ɨcqq©f¿]‡ßDõU³h—­gËÇïģÉɋw“k¯í}I·šœbmœÉ–ř›īJɥĻˁ×xo›ɹī‡l•c…¤³Xù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†ŽKLhˆ³`ñcËtW‚±»ÕS‰ëüÿďD‡u\\wwwù³—V›LŕƒOMËGh£õP¡™er™Ïd{“‡ġWÁ…č|yšg^ğyÁzÙs`—s|ÉåªÇ}m¢Ń¨`x¥’ù^•}ƒÌ¥H«‰Yªƅ”Aйn~ź¯šf¤áÀz„gŠÇDIԝ´AňĀ҄¶ûEYospõD[{ù°]u›Jq•U•|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw €ÞkrťË¿XGÉbřaDü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKwbm‡ÄNô‡ŠfœƫVÉvi†dz—H‘‹QµâFšù­Âœ³¦{YGžƒd¢ĚÜO „€{Ö¦ÞÍÀPŒ^b–ƾŠlŽ[„vt×ĈÍE˨¡Đ~´î¸ùÎh€uè`¸ŸHÕŔVºwĠââWò‡@{œÙNÝ´ə²ȕn{¿¥{l—÷eé^e’ďˆXj©î\\ªÑò˜Üìc\\üqˆÕ[Č¡xoÂċªbØ­Œø|€¶ȴZdÆšońéŒGš\\”¼C°ÌƁn´nxšÊOĨ’Ūƴĸ¢¸òTxÊǪMīИÖŲÃɎOvˆʦƢ~FŽ‡Rěò—¿ġ~åŊœú‰Nšžš¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾œĄYÒ©ÊfºmԈĘcDoĬMŬ’˜S¤„s²‚”ʘچžȂVŦ –ŽèW°ªB|IJXŔþÈJĦÆæFĚêŠYĂªĂ]øªŖNÞüA€’fɨJ€˜¯ÎrDDšĤ€`€mz\\„§~D¬{vJÂ˜«lµĂb–¤p€ŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMT”‡òP˜÷fØĶK¢ȝ˔Sô¹òEð­”`Ɩ½ǒÂň×äı–§ĤƝ§C~¡‚hlå‚ǺŦŞkâ’~}ŽFøàIJaĞ‚fƠ¥Ž„Ŕdž˜®U¸ˆźXœv¢aƆúŪtŠųƠjd•ƺŠƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹œ\\ĜÑŚŸ¶ZƄ³àjĨoâŠȴLʉȮŒĐ­ĚăŽÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTŠiƢ¾ªì°`öøu®Ê¾ãØ" + ], + "encodeOffsets": [[88824, 50096]] + } + }, + { + "type": "Feature", + "id": "110000", + "properties": { + "id": "110000", + "cp": [116.405285, 39.904989], + "name": "北京", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@ĽOÁ›ûtŷmiÍt_H»Ĩ±d`Š¹­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpŢZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwŚ¨Ud®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}" + ], + "encodeOffsets": [[120023, 41045]] + } + }, + { + "type": "Feature", + "id": "120000", + "properties": { + "id": "120000", + "cp": [117.190182, 39.125596], + "name": "天津", + "childNum": 1 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + "@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥs¡bġ«@dekąI[nlPqCnp{ˆō³°`{PNdƗqSÄĻNNâyj]äžÒD ĬH°Æ]~¡HO¾ŒX}ÐxŒgp“gWˆrDGˆŒpù‚Š^L‚ˆrzWxˆZ^¨´T\\|~@I‰zƒ–bĤ‹œjeĊªz£®Ĕvě€L†mV¾Ô_ȔNW~zbĬvG†²ZmDM~”~" + ], + "encodeOffsets": [[120237, 41215]] + } + }, + { + "type": "Feature", + "id": "310000", + "properties": { + "id": "310000", + "cp": [121.472644, 31.231706], + "name": "上海", + "childNum": 6 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@ɧư¬EpƸÁxc‡"], + ["@@©„ªƒ"], + ["@@”MA‹‘š"], + ["@@Qp݁E§ÉC¾"], + ["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"], + ["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"] + ], + "encodeOffsets": [ + [[124702, 32062]], + [[124547, 32200]], + [[124808, 31991]], + [[124726, 32110]], + [[124903, 32376]], + [[124438, 32149]] + ] + } + }, + { + "type": "Feature", + "id": "500000", + "properties": { + "id": "500000", + "cp": [107.304962, 29.533155], + "name": "重庆", + "childNum": 2 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + "@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~šuf`‘‚†fa‚ĔJåĊ„nÖ]„jƎćÊ@Š£¾a®£Ű{ŶĕF‹ègLk{Y|¡ĜWƔtƬJÑxq‹±ĢN´‰òK‰™–LÈüD|s`ŋ’ć]ƒÃ‰`đŒMûƱ½~Y°ħ`ƏíW‰½eI‹½{aŸ‘OIrÏ¡ĕŇa†p†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØ͙²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ƒ•At©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBŠ¦zG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°wećJEž·vÝ·Hgƒ‚éFXjÉê`|yŒpxkAwœWĐpb¥eOsmzwqChóUQl¥F^laf‹anòsr›EvfQdÁUVf—ÎvÜ^efˆtET¬ôA\\œ¢sJŽnQTjP؈xøK|nBz‰„œĞ»LY‚…FDxӄvr“[ehľš•vN”¢o¾NiÂxGp⬐z›bfZo~hGi’]öF|‰|Nb‡tOMn eA±ŠtPT‡LjpYQ|†SH††YĀxinzDJ€Ìg¢và¥Pg‰_–ÇzII‹€II•„£®S¬„Øs쐣ŒN" + ], + ["@@ifjN@s"] + ], + "encodeOffsets": [[[109628, 30765]], [[111725, 31320]]] + } + }, + { + "type": "Feature", + "id": "810000", + "properties": { + "id": "810000", + "cp": [114.173355, 22.320048], + "name": "香港", + "childNum": 5 + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + ["@@AlBk"], + ["@@mŽn"], + ["@@EpFo"], + ["@@ea¢pl¸Eõ¹‡hj[ƒ]ÔCΖ@lj˜¡uBXŸ…•´‹AI¹…[‹yDUˆ]W`çwZkmc–…M›žp€Åv›}I‹oJlcaƒfёKŽ°ä¬XJmРđhI®æÔtSHn€Eˆ„ÒrÈc"], + ["@@rMUw‡AS®€e"] + ], + "encodeOffsets": [ + [[117111, 23002]], + [[117072, 22876]], + [[117045, 22887]], + [[116975, 23082]], + [[116882, 22747]] + ] + } + }, + { + "type": "Feature", + "id": "820000", + "properties": { "id": "820000", "cp": [113.54909, 22.198951], "name": "澳门", "childNum": 1 }, + "geometry": { + "type": "Polygon", + "coordinates": ["@@kÊd°å§s"], + "encodeOffsets": [[116279, 22639]] + } + } + ], + "UTF8Encoding": true +} diff --git a/src/assets/svgs/403.svg b/src/assets/svgs/403.svg new file mode 100644 index 0000000..4500596 --- /dev/null +++ b/src/assets/svgs/403.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/404.svg b/src/assets/svgs/404.svg new file mode 100644 index 0000000..5244d8d --- /dev/null +++ b/src/assets/svgs/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/500.svg b/src/assets/svgs/500.svg new file mode 100644 index 0000000..9c02092 --- /dev/null +++ b/src/assets/svgs/500.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/add-user.svg b/src/assets/svgs/bpm/add-user.svg new file mode 100644 index 0000000..bc7bdbf --- /dev/null +++ b/src/assets/svgs/bpm/add-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/approve.svg b/src/assets/svgs/bpm/approve.svg new file mode 100644 index 0000000..06aa09d --- /dev/null +++ b/src/assets/svgs/bpm/approve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/auditor.svg b/src/assets/svgs/bpm/auditor.svg new file mode 100644 index 0000000..66d2c2c --- /dev/null +++ b/src/assets/svgs/bpm/auditor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/cancel.svg b/src/assets/svgs/bpm/cancel.svg new file mode 100644 index 0000000..ab9b155 --- /dev/null +++ b/src/assets/svgs/bpm/cancel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/condition.svg b/src/assets/svgs/bpm/condition.svg new file mode 100644 index 0000000..41ea85d --- /dev/null +++ b/src/assets/svgs/bpm/condition.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/copy.svg b/src/assets/svgs/bpm/copy.svg new file mode 100644 index 0000000..8ff3bba --- /dev/null +++ b/src/assets/svgs/bpm/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/delay.svg b/src/assets/svgs/bpm/delay.svg new file mode 100644 index 0000000..cbc31df --- /dev/null +++ b/src/assets/svgs/bpm/delay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/finish.svg b/src/assets/svgs/bpm/finish.svg new file mode 100644 index 0000000..674c6df --- /dev/null +++ b/src/assets/svgs/bpm/finish.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/parallel.svg b/src/assets/svgs/bpm/parallel.svg new file mode 100644 index 0000000..ba0ac67 --- /dev/null +++ b/src/assets/svgs/bpm/parallel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/reject.svg b/src/assets/svgs/bpm/reject.svg new file mode 100644 index 0000000..21fd5f6 --- /dev/null +++ b/src/assets/svgs/bpm/reject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/running.svg b/src/assets/svgs/bpm/running.svg new file mode 100644 index 0000000..5908c13 --- /dev/null +++ b/src/assets/svgs/bpm/running.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/simple-process-bg.svg b/src/assets/svgs/bpm/simple-process-bg.svg new file mode 100644 index 0000000..eb23ab5 --- /dev/null +++ b/src/assets/svgs/bpm/simple-process-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/bpm/starter.svg b/src/assets/svgs/bpm/starter.svg new file mode 100644 index 0000000..c12c712 --- /dev/null +++ b/src/assets/svgs/bpm/starter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/icon.svg b/src/assets/svgs/icon.svg new file mode 100644 index 0000000..7024bec --- /dev/null +++ b/src/assets/svgs/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/login-bg.svg b/src/assets/svgs/login-bg.svg new file mode 100644 index 0000000..bbe06c1 --- /dev/null +++ b/src/assets/svgs/login-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/login-box-bg.svg b/src/assets/svgs/login-box-bg.svg new file mode 100644 index 0000000..ab10040 --- /dev/null +++ b/src/assets/svgs/login-box-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/member_balance.svg b/src/assets/svgs/member_balance.svg new file mode 100644 index 0000000..5395b23 --- /dev/null +++ b/src/assets/svgs/member_balance.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/member_expenditure_balance.svg b/src/assets/svgs/member_expenditure_balance.svg new file mode 100644 index 0000000..02d498c --- /dev/null +++ b/src/assets/svgs/member_expenditure_balance.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/member_level.svg b/src/assets/svgs/member_level.svg new file mode 100644 index 0000000..cbcc686 --- /dev/null +++ b/src/assets/svgs/member_level.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/member_point.svg b/src/assets/svgs/member_point.svg new file mode 100644 index 0000000..b849ddb --- /dev/null +++ b/src/assets/svgs/member_point.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/member_recharge_balance.svg b/src/assets/svgs/member_recharge_balance.svg new file mode 100644 index 0000000..7519bb2 --- /dev/null +++ b/src/assets/svgs/member_recharge_balance.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/message.svg b/src/assets/svgs/message.svg new file mode 100644 index 0000000..14ca817 --- /dev/null +++ b/src/assets/svgs/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/money.svg b/src/assets/svgs/money.svg new file mode 100644 index 0000000..c1580de --- /dev/null +++ b/src/assets/svgs/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_app.svg b/src/assets/svgs/pay/icon/alipay_app.svg new file mode 100644 index 0000000..ebf1188 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_bar.svg b/src/assets/svgs/pay/icon/alipay_bar.svg new file mode 100644 index 0000000..eb1e1e8 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_bar.svg @@ -0,0 +1,2 @@ + diff --git a/src/assets/svgs/pay/icon/alipay_pc.svg b/src/assets/svgs/pay/icon/alipay_pc.svg new file mode 100644 index 0000000..2a75277 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_qr.svg b/src/assets/svgs/pay/icon/alipay_qr.svg new file mode 100644 index 0000000..4833750 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_qr.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_wap.svg b/src/assets/svgs/pay/icon/alipay_wap.svg new file mode 100644 index 0000000..87075db --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_wap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/mock.svg b/src/assets/svgs/pay/icon/mock.svg new file mode 100644 index 0000000..27b09ea --- /dev/null +++ b/src/assets/svgs/pay/icon/mock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_app.svg b/src/assets/svgs/pay/icon/wx_app.svg new file mode 100644 index 0000000..ad40b2a --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_app.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_bar.svg b/src/assets/svgs/pay/icon/wx_bar.svg new file mode 100644 index 0000000..11292e6 --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_bar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_lite.svg b/src/assets/svgs/pay/icon/wx_lite.svg new file mode 100644 index 0000000..0c925cf --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_lite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_native.svg b/src/assets/svgs/pay/icon/wx_native.svg new file mode 100644 index 0000000..bf3ba2b --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_native.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_pub.svg b/src/assets/svgs/pay/icon/wx_pub.svg new file mode 100644 index 0000000..3a6d15b --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_pub.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/svgs/peoples.svg b/src/assets/svgs/peoples.svg new file mode 100644 index 0000000..aab852e --- /dev/null +++ b/src/assets/svgs/peoples.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/send.svg b/src/assets/svgs/send.svg new file mode 100644 index 0000000..6fbc984 --- /dev/null +++ b/src/assets/svgs/send.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/shopping.svg b/src/assets/svgs/shopping.svg new file mode 100644 index 0000000..f395bc7 --- /dev/null +++ b/src/assets/svgs/shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/AppLinkInput/AppLinkSelectDialog.vue b/src/components/AppLinkInput/AppLinkSelectDialog.vue new file mode 100644 index 0000000..63f1966 --- /dev/null +++ b/src/components/AppLinkInput/AppLinkSelectDialog.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/components/AppLinkInput/data.ts b/src/components/AppLinkInput/data.ts new file mode 100644 index 0000000..c9e3678 --- /dev/null +++ b/src/components/AppLinkInput/data.ts @@ -0,0 +1,236 @@ +// APP 链接分组 +export interface AppLinkGroup { + // 分组名称 + name: string + // 链接列表 + links: AppLink[] +} + +// APP 链接 +export interface AppLink { + // 链接名称 + name: string + // 链接地址 + path: string + // 链接的类型 + type?: APP_LINK_TYPE_ENUM +} + +// APP 链接类型(需要特殊处理,例如商品详情) +export const enum APP_LINK_TYPE_ENUM { + // 拼团活动 + ACTIVITY_COMBINATION, + // 秒杀活动 + ACTIVITY_SECKILL, + // 积分商城活动 + ACTIVITY_POINT, + // 文章详情 + ARTICLE_DETAIL, + // 优惠券详情 + COUPON_DETAIL, + // 自定义页面详情 + DIY_PAGE_DETAIL, + // 品类列表 + PRODUCT_CATEGORY_LIST, + // 商品列表 + PRODUCT_LIST, + // 商品详情 + PRODUCT_DETAIL_NORMAL, + // 拼团商品详情 + PRODUCT_DETAIL_COMBINATION, + // 秒杀商品详情 + PRODUCT_DETAIL_SECKILL +} + +// APP 链接列表(做一下持久化?) +export const APP_LINK_GROUP_LIST = [ + { + name: '商城', + links: [ + { + name: '首页', + path: '/pages/index/index' + }, + { + name: '商品分类', + path: '/pages/index/category', + type: APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST + }, + { + name: '购物车', + path: '/pages/index/cart' + }, + { + name: '个人中心', + path: '/pages/index/user' + }, + { + name: '商品搜索', + path: '/pages/index/search' + }, + { + name: '自定义页面', + path: '/pages/index/page', + type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL + }, + { + name: '客服', + path: '/pages/chat/index' + }, + { + name: '系统设置', + path: '/pages/public/setting' + }, + { + name: '常见问题', + path: '/pages/public/faq' + } + ] + }, + { + name: '商品', + links: [ + { + name: '商品列表', + path: '/pages/goods/list', + type: APP_LINK_TYPE_ENUM.PRODUCT_LIST + }, + { + name: '商品详情', + path: '/pages/goods/index', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_NORMAL + }, + { + name: '拼团商品详情', + path: '/pages/goods/groupon', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_COMBINATION + }, + { + name: '秒杀商品详情', + path: '/pages/goods/seckill', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL + } + ] + }, + { + name: '营销活动', + links: [ + { + name: '拼团订单', + path: '/pages/activity/groupon/order' + }, + { + name: '营销商品', + path: '/pages/activity/index' + }, + { + name: '拼团活动', + path: '/pages/activity/groupon/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_COMBINATION + }, + { + name: '秒杀活动', + path: '/pages/activity/seckill/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_SECKILL + }, + { + name: '积分商城活动', + path: '/pages/activity/point/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_POINT + }, + { + name: '签到中心', + path: '/pages/app/sign' + }, + { + name: '优惠券中心', + path: '/pages/coupon/list' + }, + { + name: '优惠券详情', + path: '/pages/coupon/detail', + type: APP_LINK_TYPE_ENUM.COUPON_DETAIL + }, + { + name: '文章详情', + path: '/pages/public/richtext', + type: APP_LINK_TYPE_ENUM.ARTICLE_DETAIL + } + ] + }, + { + name: '分销商城', + links: [ + { + name: '分销中心', + path: '/pages/commission/index' + }, + { + name: '推广商品', + path: '/pages/commission/goods' + }, + { + name: '分销订单', + path: '/pages/commission/order' + }, + { + name: '我的团队', + path: '/pages/commission/team' + } + ] + }, + { + name: '支付', + links: [ + { + name: '充值余额', + path: '/pages/pay/recharge' + }, + { + name: '充值记录', + path: '/pages/pay/recharge-log' + } + ] + }, + { + name: '用户中心', + links: [ + { + name: '用户信息', + path: '/pages/user/info' + }, + { + name: '用户订单', + path: '/pages/order/list' + }, + { + name: '售后订单', + path: '/pages/order/aftersale/list' + }, + { + name: '商品收藏', + path: '/pages/user/goods-collect' + }, + { + name: '浏览记录', + path: '/pages/user/goods-log' + }, + { + name: '地址管理', + path: '/pages/user/address/list' + }, + { + name: '用户佣金', + path: '/pages/user/wallet/commission' + }, + { + name: '用户余额', + path: '/pages/user/wallet/money' + }, + { + name: '用户积分', + path: '/pages/user/wallet/score' + } + ] + } +] as AppLinkGroup[] diff --git a/src/components/AppLinkInput/index.vue b/src/components/AppLinkInput/index.vue new file mode 100644 index 0000000..ff71382 --- /dev/null +++ b/src/components/AppLinkInput/index.vue @@ -0,0 +1,43 @@ + + diff --git a/src/components/Backtop/index.ts b/src/components/Backtop/index.ts new file mode 100644 index 0000000..96de88d --- /dev/null +++ b/src/components/Backtop/index.ts @@ -0,0 +1,3 @@ +import Backtop from './src/Backtop.vue' + +export { Backtop } diff --git a/src/components/Backtop/src/Backtop.vue b/src/components/Backtop/src/Backtop.vue new file mode 100644 index 0000000..5d79f51 --- /dev/null +++ b/src/components/Backtop/src/Backtop.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/Card/index.ts b/src/components/Card/index.ts new file mode 100644 index 0000000..f4c0d86 --- /dev/null +++ b/src/components/Card/index.ts @@ -0,0 +1,3 @@ +import CardTitle from './src/CardTitle.vue' + +export { CardTitle } diff --git a/src/components/Card/src/CardTitle.vue b/src/components/Card/src/CardTitle.vue new file mode 100644 index 0000000..76a8356 --- /dev/null +++ b/src/components/Card/src/CardTitle.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/components/ColorInput/index.vue b/src/components/ColorInput/index.vue new file mode 100644 index 0000000..63ff73c --- /dev/null +++ b/src/components/ColorInput/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/ConfigGlobal/index.ts b/src/components/ConfigGlobal/index.ts new file mode 100644 index 0000000..dda2462 --- /dev/null +++ b/src/components/ConfigGlobal/index.ts @@ -0,0 +1,3 @@ +import ConfigGlobal from './src/ConfigGlobal.vue' + +export { ConfigGlobal } diff --git a/src/components/ConfigGlobal/src/ConfigGlobal.vue b/src/components/ConfigGlobal/src/ConfigGlobal.vue new file mode 100644 index 0000000..af543df --- /dev/null +++ b/src/components/ConfigGlobal/src/ConfigGlobal.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/components/ContentDetailWrap/index.ts b/src/components/ContentDetailWrap/index.ts new file mode 100644 index 0000000..1871cac --- /dev/null +++ b/src/components/ContentDetailWrap/index.ts @@ -0,0 +1,3 @@ +import ContentDetailWrap from './src/ContentDetailWrap.vue' + +export { ContentDetailWrap } diff --git a/src/components/ContentDetailWrap/src/ContentDetailWrap.vue b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue new file mode 100644 index 0000000..a9eacc0 --- /dev/null +++ b/src/components/ContentDetailWrap/src/ContentDetailWrap.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/components/ContentWrap/index.ts b/src/components/ContentWrap/index.ts new file mode 100644 index 0000000..8c22cc8 --- /dev/null +++ b/src/components/ContentWrap/index.ts @@ -0,0 +1,3 @@ +import ContentWrap from './src/ContentWrap.vue' + +export { ContentWrap } diff --git a/src/components/ContentWrap/src/ContentWrap.vue b/src/components/ContentWrap/src/ContentWrap.vue new file mode 100644 index 0000000..e603596 --- /dev/null +++ b/src/components/ContentWrap/src/ContentWrap.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/CountTo/index.ts b/src/components/CountTo/index.ts new file mode 100644 index 0000000..2119f02 --- /dev/null +++ b/src/components/CountTo/index.ts @@ -0,0 +1,3 @@ +import CountTo from './src/CountTo.vue' + +export { CountTo } diff --git a/src/components/CountTo/src/CountTo.vue b/src/components/CountTo/src/CountTo.vue new file mode 100644 index 0000000..7a19bec --- /dev/null +++ b/src/components/CountTo/src/CountTo.vue @@ -0,0 +1,182 @@ + + + diff --git a/src/components/Crontab/index.ts b/src/components/Crontab/index.ts new file mode 100644 index 0000000..6beeef8 --- /dev/null +++ b/src/components/Crontab/index.ts @@ -0,0 +1,2 @@ +import Crontab from './src/Crontab.vue' +export { Crontab } diff --git a/src/components/Crontab/src/Crontab.vue b/src/components/Crontab/src/Crontab.vue new file mode 100644 index 0000000..0914bb7 --- /dev/null +++ b/src/components/Crontab/src/Crontab.vue @@ -0,0 +1,1015 @@ + + + + diff --git a/src/components/Cropper/index.ts b/src/components/Cropper/index.ts new file mode 100644 index 0000000..8fcc618 --- /dev/null +++ b/src/components/Cropper/index.ts @@ -0,0 +1,4 @@ +import CropperImage from './src/Cropper.vue' +import CropperAvatar from './src/CropperAvatar.vue' + +export { CropperImage, CropperAvatar } diff --git a/src/components/Cropper/src/CopperModal.vue b/src/components/Cropper/src/CopperModal.vue new file mode 100644 index 0000000..27052b8 --- /dev/null +++ b/src/components/Cropper/src/CopperModal.vue @@ -0,0 +1,261 @@ + + + diff --git a/src/components/Cropper/src/Cropper.vue b/src/components/Cropper/src/Cropper.vue new file mode 100644 index 0000000..871aed8 --- /dev/null +++ b/src/components/Cropper/src/Cropper.vue @@ -0,0 +1,183 @@ + + + diff --git a/src/components/Cropper/src/CropperAvatar.vue b/src/components/Cropper/src/CropperAvatar.vue new file mode 100644 index 0000000..9464c2a --- /dev/null +++ b/src/components/Cropper/src/CropperAvatar.vue @@ -0,0 +1,142 @@ + + + diff --git a/src/components/Cropper/src/types.ts b/src/components/Cropper/src/types.ts new file mode 100644 index 0000000..bcad3b4 --- /dev/null +++ b/src/components/Cropper/src/types.ts @@ -0,0 +1,8 @@ +import type Cropper from 'cropperjs' + +export interface CropendResult { + imgBase64: string + imgInfo: Cropper.Data +} + +export type { Cropper } diff --git a/src/components/Descriptions/index.ts b/src/components/Descriptions/index.ts new file mode 100644 index 0000000..243bc39 --- /dev/null +++ b/src/components/Descriptions/index.ts @@ -0,0 +1,4 @@ +import Descriptions from './src/Descriptions.vue' +import DescriptionsItemLabel from './src/DescriptionsItemLabel.vue' + +export { Descriptions, DescriptionsItemLabel } diff --git a/src/components/Descriptions/src/Descriptions.vue b/src/components/Descriptions/src/Descriptions.vue new file mode 100644 index 0000000..184d95c --- /dev/null +++ b/src/components/Descriptions/src/Descriptions.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/src/components/Descriptions/src/DescriptionsItemLabel.vue b/src/components/Descriptions/src/DescriptionsItemLabel.vue new file mode 100644 index 0000000..4efb2fb --- /dev/null +++ b/src/components/Descriptions/src/DescriptionsItemLabel.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/Dialog/index.ts b/src/components/Dialog/index.ts new file mode 100644 index 0000000..1655dad --- /dev/null +++ b/src/components/Dialog/index.ts @@ -0,0 +1,3 @@ +import Dialog from './src/Dialog.vue' + +export { Dialog } diff --git a/src/components/Dialog/src/Dialog.vue b/src/components/Dialog/src/Dialog.vue new file mode 100644 index 0000000..a1eb550 --- /dev/null +++ b/src/components/Dialog/src/Dialog.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/src/components/DictTag/index.ts b/src/components/DictTag/index.ts new file mode 100644 index 0000000..4db2742 --- /dev/null +++ b/src/components/DictTag/index.ts @@ -0,0 +1,3 @@ +import DictTag from './src/DictTag.vue' + +export { DictTag } diff --git a/src/components/DictTag/src/DictTag.vue b/src/components/DictTag/src/DictTag.vue new file mode 100644 index 0000000..6414eaa --- /dev/null +++ b/src/components/DictTag/src/DictTag.vue @@ -0,0 +1,90 @@ + diff --git a/src/components/DiyEditor/components/ComponentContainer.vue b/src/components/DiyEditor/components/ComponentContainer.vue new file mode 100644 index 0000000..4856722 --- /dev/null +++ b/src/components/DiyEditor/components/ComponentContainer.vue @@ -0,0 +1,239 @@ + + + + + + diff --git a/src/components/DiyEditor/components/ComponentContainerProperty.vue b/src/components/DiyEditor/components/ComponentContainerProperty.vue new file mode 100644 index 0000000..5d18785 --- /dev/null +++ b/src/components/DiyEditor/components/ComponentContainerProperty.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/src/components/DiyEditor/components/ComponentLibrary.vue b/src/components/DiyEditor/components/ComponentLibrary.vue new file mode 100644 index 0000000..fdb0b1d --- /dev/null +++ b/src/components/DiyEditor/components/ComponentLibrary.vue @@ -0,0 +1,211 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/Carousel/config.ts b/src/components/DiyEditor/components/mobile/Carousel/config.ts new file mode 100644 index 0000000..3e74a51 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Carousel/config.ts @@ -0,0 +1,50 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 轮播图属性 */ +export interface CarouselProperty { + // 类型:默认 | 卡片 + type: 'default' | 'card' + // 指示器样式:点 | 数字 + indicator: 'dot' | 'number' + // 是否自动播放 + autoplay: boolean + // 播放间隔 + interval: number + // 轮播内容 + items: CarouselItemProperty[] + // 组件样式 + style: ComponentStyle +} +// 轮播内容属性 +export interface CarouselItemProperty { + // 类型:图片 | 视频 + type: 'img' | 'video' + // 图片链接 + imgUrl: string + // 视频链接 + videoUrl: string + // 跳转链接 + url: string +} + +// 定义组件 +export const component = { + id: 'Carousel', + name: '轮播图', + icon: 'system-uicons:carousel', + property: { + type: 'default', + indicator: 'dot', + autoplay: false, + interval: 3, + items: [ + { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-01.jpg', videoUrl: '' }, + { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-02.jpg', videoUrl: '' } + ] as CarouselItemProperty[], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/Carousel/index.vue b/src/components/DiyEditor/components/mobile/Carousel/index.vue new file mode 100644 index 0000000..360b4a4 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Carousel/index.vue @@ -0,0 +1,43 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/Carousel/property.vue b/src/components/DiyEditor/components/mobile/Carousel/property.vue new file mode 100644 index 0000000..06cfda4 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Carousel/property.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/CouponCard/component.tsx b/src/components/DiyEditor/components/mobile/CouponCard/component.tsx new file mode 100644 index 0000000..689690b --- /dev/null +++ b/src/components/DiyEditor/components/mobile/CouponCard/component.tsx @@ -0,0 +1,73 @@ +import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate' +import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from '@/utils/constants' +import { floatToFixed2 } from '@/utils' +import { formatDate } from '@/utils/formatTime' +import { object } from 'vue-types' + +// 优惠值 +export const CouponDiscount = defineComponent({ + name: 'CouponDiscount', + props: { + coupon: object() + }, + setup(props) { + const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO + // 折扣 + let value = coupon.discountPercent + '' + let suffix = ' 折' + // 满减 + if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) { + value = floatToFixed2(coupon.discountPrice) + suffix = ' 元' + } + return () => ( +
+ {value} + {suffix} +
+ ) + } +}) + +// 优惠描述 +export const CouponDiscountDesc = defineComponent({ + name: 'CouponDiscountDesc', + props: { + coupon: object() + }, + setup(props) { + const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO + // 使用条件 + const useCondition = coupon.usePrice > 0 ? `满${floatToFixed2(coupon.usePrice)}元,` : '' + // 优惠描述 + const discountDesc = + coupon.discountType === PromotionDiscountTypeEnum.PRICE.type + ? `减${floatToFixed2(coupon.discountPrice)}元` + : `打${coupon.discountPercent}折` + return () => ( +
+ {useCondition} + {discountDesc} +
+ ) + } +}) + +// 有效期 +export const CouponValidTerm = defineComponent({ + name: 'CouponValidTerm', + props: { + coupon: object() + }, + setup(props) { + const coupon = props.coupon as CouponTemplateApi.CouponTemplateVO + const text = + coupon.validityType === CouponTemplateValidityTypeEnum.DATE.type + ? `有效期:${formatDate(coupon.validStartTime, 'YYYY-MM-DD')} 至 ${formatDate( + coupon.validEndTime, + 'YYYY-MM-DD' + )}` + : `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用` + return () =>
{text}
+ } +}) diff --git a/src/components/DiyEditor/components/mobile/CouponCard/config.ts b/src/components/DiyEditor/components/mobile/CouponCard/config.ts new file mode 100644 index 0000000..304533d --- /dev/null +++ b/src/components/DiyEditor/components/mobile/CouponCard/config.ts @@ -0,0 +1,47 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 商品卡片属性 */ +export interface CouponCardProperty { + // 列数 + columns: number + // 背景图 + bgImg: string + // 文字颜色 + textColor: string + // 按钮样式 + button: { + // 颜色 + color: string + // 背景颜色 + bgColor: string + } + // 间距 + space: number + // 优惠券编号列表 + couponIds: number[] + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'CouponCard', + name: '优惠券', + icon: 'ep:ticket', + property: { + columns: 1, + bgImg: '', + textColor: '#E9B461', + button: { + color: '#434343', + bgColor: '' + }, + space: 0, + couponIds: [], + style: { + bgType: 'color', + bgColor: '', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/CouponCard/index.vue b/src/components/DiyEditor/components/mobile/CouponCard/index.vue new file mode 100644 index 0000000..3e2302a --- /dev/null +++ b/src/components/DiyEditor/components/mobile/CouponCard/index.vue @@ -0,0 +1,142 @@ + + + diff --git a/src/components/DiyEditor/components/mobile/CouponCard/property.vue b/src/components/DiyEditor/components/mobile/CouponCard/property.vue new file mode 100644 index 0000000..604afe9 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/CouponCard/property.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/Divider/config.ts b/src/components/DiyEditor/components/mobile/Divider/config.ts new file mode 100644 index 0000000..9b55360 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Divider/config.ts @@ -0,0 +1,29 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +/** 分割线属性 */ +export interface DividerProperty { + // 高度 + height: number + // 线宽 + lineWidth: number + // 边距类型 + paddingType: 'none' | 'horizontal' + // 颜色 + lineColor: string + // 类型 + borderType: 'solid' | 'dashed' | 'dotted' | 'none' +} + +// 定义组件 +export const component = { + id: 'Divider', + name: '分割线', + icon: 'tdesign:component-divider-vertical', + property: { + height: 30, + lineWidth: 1, + paddingType: 'none', + lineColor: '#dcdfe6', + borderType: 'solid' + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/Divider/index.vue b/src/components/DiyEditor/components/mobile/Divider/index.vue new file mode 100644 index 0000000..f778504 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Divider/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/Divider/property.vue b/src/components/DiyEditor/components/mobile/Divider/property.vue new file mode 100644 index 0000000..dc2a4da --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Divider/property.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/FloatingActionButton/config.ts b/src/components/DiyEditor/components/mobile/FloatingActionButton/config.ts new file mode 100644 index 0000000..fcf129f --- /dev/null +++ b/src/components/DiyEditor/components/mobile/FloatingActionButton/config.ts @@ -0,0 +1,36 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +// 悬浮按钮属性 +export interface FloatingActionButtonProperty { + // 展开方向 + direction: 'horizontal' | 'vertical' + // 是否显示文字 + showText: boolean + // 按钮列表 + list: FloatingActionButtonItemProperty[] +} + +// 悬浮按钮项属性 +export interface FloatingActionButtonItemProperty { + // 图片地址 + imgUrl: string + // 跳转连接 + url: string + // 文字 + text: string + // 文字颜色 + textColor: string +} + +// 定义组件 +export const component = { + id: 'FloatingActionButton', + name: '悬浮按钮', + icon: 'tabler:float-right', + position: 'fixed', + property: { + direction: 'vertical', + showText: true, + list: [{ textColor: '#fff' }] + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/FloatingActionButton/index.vue b/src/components/DiyEditor/components/mobile/FloatingActionButton/index.vue new file mode 100644 index 0000000..c2b9926 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/FloatingActionButton/index.vue @@ -0,0 +1,74 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/FloatingActionButton/property.vue b/src/components/DiyEditor/components/mobile/FloatingActionButton/property.vue new file mode 100644 index 0000000..6eeb217 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/FloatingActionButton/property.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts b/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts new file mode 100644 index 0000000..a7bd762 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts @@ -0,0 +1,143 @@ +import { HotZoneItemProperty } from '@/components/DiyEditor/components/mobile/HotZone/config' +import { StyleValue } from 'vue' + +// 热区的最小宽高 +export const HOT_ZONE_MIN_SIZE = 100 + +// 控制的类型 +export enum CONTROL_TYPE_ENUM { + LEFT, + TOP, + WIDTH, + HEIGHT +} + +// 定义热区的控制点 +export interface ControlDot { + position: string + types: CONTROL_TYPE_ENUM[] + style: StyleValue +} + +// 热区的8个控制点 +export const CONTROL_DOT_LIST = [ + { + position: '左上角', + types: [ + CONTROL_TYPE_ENUM.LEFT, + CONTROL_TYPE_ENUM.TOP, + CONTROL_TYPE_ENUM.WIDTH, + CONTROL_TYPE_ENUM.HEIGHT + ], + style: { left: '-5px', top: '-5px', cursor: 'nwse-resize' } + }, + { + position: '上方中间', + types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.HEIGHT], + style: { left: '50%', top: '-5px', cursor: 'n-resize', transform: 'translateX(-50%)' } + }, + { + position: '右上角', + types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT], + style: { right: '-5px', top: '-5px', cursor: 'nesw-resize' } + }, + { + position: '右侧中间', + types: [CONTROL_TYPE_ENUM.WIDTH], + style: { right: '-5px', top: '50%', cursor: 'e-resize', transform: 'translateX(-50%)' } + }, + { + position: '右下角', + types: [CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT], + style: { right: '-5px', bottom: '-5px', cursor: 'nwse-resize' } + }, + { + position: '下方中间', + types: [CONTROL_TYPE_ENUM.HEIGHT], + style: { left: '50%', bottom: '-5px', cursor: 's-resize', transform: 'translateX(-50%)' } + }, + { + position: '左下角', + types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT], + style: { left: '-5px', bottom: '-5px', cursor: 'nesw-resize' } + }, + { + position: '左侧中间', + types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH], + style: { left: '-5px', top: '50%', cursor: 'w-resize', transform: 'translateX(-50%)' } + } +] as ControlDot[] + +//region 热区的缩放 +// 热区的缩放比例 +export const HOT_ZONE_SCALE_RATE = 2 +// 缩小:缩回适合手机屏幕的大小 +export const zoomOut = (list?: HotZoneItemProperty[]) => { + return ( + list?.map((hotZone) => ({ + ...hotZone, + left: (hotZone.left /= HOT_ZONE_SCALE_RATE), + top: (hotZone.top /= HOT_ZONE_SCALE_RATE), + width: (hotZone.width /= HOT_ZONE_SCALE_RATE), + height: (hotZone.height /= HOT_ZONE_SCALE_RATE) + })) || [] + ) +} +// 放大:作用是为了方便在电脑屏幕上编辑 +export const zoomIn = (list?: HotZoneItemProperty[]) => { + return ( + list?.map((hotZone) => ({ + ...hotZone, + left: (hotZone.left *= HOT_ZONE_SCALE_RATE), + top: (hotZone.top *= HOT_ZONE_SCALE_RATE), + width: (hotZone.width *= HOT_ZONE_SCALE_RATE), + height: (hotZone.height *= HOT_ZONE_SCALE_RATE) + })) || [] + ) +} +//endregion + +/** + * 封装热区拖拽 + * + * 注:为什么不使用vueuse的useDraggable。在本场景下,其使用方式比较复杂 + * @param hotZone 热区 + * @param downEvent 鼠标按下事件 + * @param callback 回调函数 + */ +export const useDraggable = ( + hotZone: HotZoneItemProperty, + downEvent: MouseEvent, + callback: ( + left: number, + top: number, + width: number, + height: number, + moveWidth: number, + moveHeight: number + ) => void +) => { + // 阻止事件冒泡 + downEvent.stopPropagation() + + // 移动前的鼠标坐标 + const { clientX: startX, clientY: startY } = downEvent + // 移动前的热区坐标、大小 + const { left, top, width, height } = hotZone + + // 监听鼠标移动 + document.onmousemove = (e) => { + // 移动宽度 + const moveWidth = e.clientX - startX + // 移动高度 + const moveHeight = e.clientY - startY + // 移动回调 + callback(left, top, width, height, moveWidth, moveHeight) + } + + // 松开鼠标后,结束拖拽 + document.onmouseup = () => { + document.onmousemove = null + document.onmouseup = null + } +} diff --git a/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue b/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue new file mode 100644 index 0000000..3925057 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue @@ -0,0 +1,236 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/HotZone/config.ts b/src/components/DiyEditor/components/mobile/HotZone/config.ts new file mode 100644 index 0000000..80ed855 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/HotZone/config.ts @@ -0,0 +1,43 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 热区属性 */ +export interface HotZoneProperty { + // 图片地址 + imgUrl: string + // 导航菜单列表 + list: HotZoneItemProperty[] + // 组件样式 + style: ComponentStyle +} + +/** 热区项目属性 */ +export interface HotZoneItemProperty { + // 链接的名称 + name: string + // 链接 + url: string + // 宽 + width: number + // 高 + height: number + // 上 + top: number + // 左 + left: number +} + +// 定义组件 +export const component = { + id: 'HotZone', + name: '热区', + icon: 'tabler:hand-click', + property: { + imgUrl: '', + list: [] as HotZoneItemProperty[], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/HotZone/index.vue b/src/components/DiyEditor/components/mobile/HotZone/index.vue new file mode 100644 index 0000000..3a9b842 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/HotZone/index.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/HotZone/property.vue b/src/components/DiyEditor/components/mobile/HotZone/property.vue new file mode 100644 index 0000000..65892f8 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/HotZone/property.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/ImageBar/config.ts b/src/components/DiyEditor/components/mobile/ImageBar/config.ts new file mode 100644 index 0000000..68edf72 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ImageBar/config.ts @@ -0,0 +1,27 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 图片展示属性 */ +export interface ImageBarProperty { + // 图片链接 + imgUrl: string + // 跳转链接 + url: string + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'ImageBar', + name: '图片展示', + icon: 'ep:picture', + property: { + imgUrl: '', + url: '', + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/ImageBar/index.vue b/src/components/DiyEditor/components/mobile/ImageBar/index.vue new file mode 100644 index 0000000..d9685b5 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ImageBar/index.vue @@ -0,0 +1,24 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/ImageBar/property.vue b/src/components/DiyEditor/components/mobile/ImageBar/property.vue new file mode 100644 index 0000000..fe08756 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ImageBar/property.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MagicCube/config.ts b/src/components/DiyEditor/components/mobile/MagicCube/config.ts new file mode 100644 index 0000000..5e10ab5 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MagicCube/config.ts @@ -0,0 +1,49 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 广告魔方属性 */ +export interface MagicCubeProperty { + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间隔 + space: number + // 导航菜单列表 + list: MagicCubeItemProperty[] + // 组件样式 + style: ComponentStyle +} + +/** 广告魔方项目属性 */ +export interface MagicCubeItemProperty { + // 图标链接 + imgUrl: string + // 链接 + url: string + // 宽 + width: number + // 高 + height: number + // 上 + top: number + // 左 + left: number +} + +// 定义组件 +export const component = { + id: 'MagicCube', + name: '广告魔方', + icon: 'bi:columns', + property: { + borderRadiusTop: 0, + borderRadiusBottom: 0, + space: 0, + list: [], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/MagicCube/index.vue b/src/components/DiyEditor/components/mobile/MagicCube/index.vue new file mode 100644 index 0000000..48fb6c7 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MagicCube/index.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MagicCube/property.vue b/src/components/DiyEditor/components/mobile/MagicCube/property.vue new file mode 100644 index 0000000..dee3117 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MagicCube/property.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuGrid/config.ts b/src/components/DiyEditor/components/mobile/MenuGrid/config.ts new file mode 100644 index 0000000..9f91ceb --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuGrid/config.ts @@ -0,0 +1,79 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' +import { cloneDeep } from 'lodash-es' + +/** 宫格导航属性 */ +export interface MenuGridProperty { + // 列数 + column: number + // 导航菜单列表 + list: MenuGridItemProperty[] + // 组件样式 + style: ComponentStyle +} + +/** 宫格导航项目属性 */ +export interface MenuGridItemProperty { + // 图标链接 + iconUrl: string + // 标题 + title: string + // 标题颜色 + titleColor: string + // 副标题 + subtitle: string + // 副标题颜色 + subtitleColor: string + // 链接 + url: string + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标文字 + text: string + // 角标文字颜色 + textColor: string + // 角标背景颜色 + bgColor: string + } +} + +export const EMPTY_MENU_GRID_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + subtitle: '副标题', + subtitleColor: '#bbb', + badge: { + show: false, + textColor: '#fff', + bgColor: '#FF6000' + } +} as MenuGridItemProperty + +// 定义组件 +export const component = { + id: 'MenuGrid', + name: '宫格导航', + icon: 'bi:grid-3x3-gap', + property: { + column: 3, + list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + marginLeft: 8, + marginRight: 8, + padding: 8, + paddingTop: 8, + paddingRight: 8, + paddingBottom: 8, + paddingLeft: 8, + borderRadius: 8, + borderTopLeftRadius: 8, + borderTopRightRadius: 8, + borderBottomRightRadius: 8, + borderBottomLeftRadius: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/MenuGrid/index.vue b/src/components/DiyEditor/components/mobile/MenuGrid/index.vue new file mode 100644 index 0000000..1c5ef1d --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuGrid/index.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuGrid/property.vue b/src/components/DiyEditor/components/mobile/MenuGrid/property.vue new file mode 100644 index 0000000..e05988e --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuGrid/property.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuList/config.ts b/src/components/DiyEditor/components/mobile/MenuList/config.ts new file mode 100644 index 0000000..f96fd0a --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuList/config.ts @@ -0,0 +1,48 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' +import { cloneDeep } from 'lodash-es' + +/** 列表导航属性 */ +export interface MenuListProperty { + // 导航菜单列表 + list: MenuListItemProperty[] + // 组件样式 + style: ComponentStyle +} + +/** 列表导航项目属性 */ +export interface MenuListItemProperty { + // 图标链接 + iconUrl: string + // 标题 + title: string + // 标题颜色 + titleColor: string + // 副标题 + subtitle: string + // 副标题颜色 + subtitleColor: string + // 链接 + url: string +} + +export const EMPTY_MENU_LIST_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + subtitle: '副标题', + subtitleColor: '#bbb' +} + +// 定义组件 +export const component = { + id: 'MenuList', + name: '列表导航', + icon: 'fa-solid:list', + property: { + list: [cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/MenuList/index.vue b/src/components/DiyEditor/components/mobile/MenuList/index.vue new file mode 100644 index 0000000..9a56fd9 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuList/index.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuList/property.vue b/src/components/DiyEditor/components/mobile/MenuList/property.vue new file mode 100644 index 0000000..b665b32 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuList/property.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuSwiper/config.ts b/src/components/DiyEditor/components/mobile/MenuSwiper/config.ts new file mode 100644 index 0000000..fe5f4e8 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuSwiper/config.ts @@ -0,0 +1,66 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' +import { cloneDeep } from 'lodash-es' + +/** 菜单导航属性 */ +export interface MenuSwiperProperty { + // 布局: 图标+文字 | 图标 + layout: 'iconText' | 'icon' + // 行数 + row: number + // 列数 + column: number + // 导航菜单列表 + list: MenuSwiperItemProperty[] + // 组件样式 + style: ComponentStyle +} +/** 菜单导航项目属性 */ +export interface MenuSwiperItemProperty { + // 图标链接 + iconUrl: string + // 标题 + title: string + // 标题颜色 + titleColor: string + // 链接 + url: string + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标文字 + text: string + // 角标文字颜色 + textColor: string + // 角标背景颜色 + bgColor: string + } +} + +export const EMPTY_MENU_SWIPER_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + badge: { + show: false, + textColor: '#fff', + bgColor: '#FF6000' + } +} as MenuSwiperItemProperty + +// 定义组件 +export const component = { + id: 'MenuSwiper', + name: '菜单导航', + icon: 'bi:grid-3x2-gap', + property: { + layout: 'iconText', + row: 1, + column: 3, + list: [cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/MenuSwiper/index.vue b/src/components/DiyEditor/components/mobile/MenuSwiper/index.vue new file mode 100644 index 0000000..f8e2bbc --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuSwiper/index.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/MenuSwiper/property.vue b/src/components/DiyEditor/components/mobile/MenuSwiper/property.vue new file mode 100644 index 0000000..3dd3f7c --- /dev/null +++ b/src/components/DiyEditor/components/mobile/MenuSwiper/property.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue b/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue new file mode 100644 index 0000000..ea0e7ca --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/NavigationBar/config.ts b/src/components/DiyEditor/components/mobile/NavigationBar/config.ts new file mode 100644 index 0000000..36612a3 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NavigationBar/config.ts @@ -0,0 +1,82 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +/** 顶部导航栏属性 */ +export interface NavigationBarProperty { + // 背景类型 + bgType: 'color' | 'img' + // 背景颜色 + bgColor: string + // 图片链接 + bgImg: string + // 样式类型:默认 | 沉浸式 + styleType: 'normal' | 'inner' + // 常驻显示 + alwaysShow: boolean + // 小程序单元格列表 + mpCells: NavigationBarCellProperty[] + // 其它平台单元格列表 + otherCells: NavigationBarCellProperty[] + // 本地变量 + _local: { + // 预览顶部导航(小程序) + previewMp: boolean + // 预览顶部导航(非小程序) + previewOther: boolean + } +} + +/** 顶部导航栏 - 单元格 属性 */ +export interface NavigationBarCellProperty { + // 类型:文字 | 图片 | 搜索框 + type: 'text' | 'image' | 'search' + // 宽度 + width: number + // 高度 + height: number + // 顶部位置 + top: number + // 左侧位置 + left: number + // 文字内容 + text: string + // 文字颜色 + textColor: string + // 图片地址 + imgUrl: string + // 图片链接 + url: string + // 搜索框:提示文字 + placeholder: string + // 搜索框:边框圆角半径 + borderRadius: number +} + +// 定义组件 +export const component = { + id: 'NavigationBar', + name: '顶部导航栏', + icon: 'tabler:layout-navbar', + property: { + bgType: 'color', + bgColor: '#fff', + bgImg: '', + styleType: 'normal', + alwaysShow: true, + mpCells: [ + { + type: 'text', + textColor: '#111111' + } + ], + otherCells: [ + { + type: 'text', + textColor: '#111111' + } + ], + _local: { + previewMp: true, + previewOther: false + } + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/NavigationBar/index.vue b/src/components/DiyEditor/components/mobile/NavigationBar/index.vue new file mode 100644 index 0000000..c5a92b3 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NavigationBar/index.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/components/DiyEditor/components/mobile/NavigationBar/property.vue b/src/components/DiyEditor/components/mobile/NavigationBar/property.vue new file mode 100644 index 0000000..17534cf --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NavigationBar/property.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/NoticeBar/config.ts b/src/components/DiyEditor/components/mobile/NoticeBar/config.ts new file mode 100644 index 0000000..b6b0860 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NoticeBar/config.ts @@ -0,0 +1,46 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 公告栏属性 */ +export interface NoticeBarProperty { + // 图标地址 + iconUrl: string + // 公告内容列表 + contents: NoticeContentProperty[] + // 背景颜色 + backgroundColor: string + // 文字颜色 + textColor: string + // 组件样式 + style: ComponentStyle +} + +/** 内容属性 */ +export interface NoticeContentProperty { + // 内容文字 + text: string + // 链接地址 + url: string +} + +// 定义组件 +export const component = { + id: 'NoticeBar', + name: '公告栏', + icon: 'ep:bell', + property: { + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/xinjian.png', + contents: [ + { + text: '', + url: '' + } + ], + backgroundColor: '#fff', + textColor: '#333', + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/NoticeBar/index.vue b/src/components/DiyEditor/components/mobile/NoticeBar/index.vue new file mode 100644 index 0000000..fce1afb --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NoticeBar/index.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/NoticeBar/property.vue b/src/components/DiyEditor/components/mobile/NoticeBar/property.vue new file mode 100644 index 0000000..99d04b0 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/NoticeBar/property.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/PageConfig/config.ts b/src/components/DiyEditor/components/mobile/PageConfig/config.ts new file mode 100644 index 0000000..f8e45e4 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PageConfig/config.ts @@ -0,0 +1,23 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +/** 页面设置属性 */ +export interface PageConfigProperty { + // 页面描述 + description: string + // 页面背景颜色 + backgroundColor: string + // 页面背景图片 + backgroundImage: string +} + +// 定义页面组件 +export const component = { + id: 'PageConfig', + name: '页面设置', + icon: 'ep:document', + property: { + description: '', + backgroundColor: '#f5f5f5', + backgroundImage: '' + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/PageConfig/property.vue b/src/components/DiyEditor/components/mobile/PageConfig/property.vue new file mode 100644 index 0000000..d8f51d2 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PageConfig/property.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/Popover/config.ts b/src/components/DiyEditor/components/mobile/Popover/config.ts new file mode 100644 index 0000000..e814090 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Popover/config.ts @@ -0,0 +1,26 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +/** 弹窗广告属性 */ +export interface PopoverProperty { + list: PopoverItemProperty[] +} + +export interface PopoverItemProperty { + // 图片地址 + imgUrl: string + // 跳转连接 + url: string + // 显示类型:仅显示一次、每次启动都会显示 + showType: 'once' | 'always' +} + +// 定义组件 +export const component = { + id: 'Popover', + name: '弹窗广告', + icon: 'carbon:popup', + position: 'fixed', + property: { + list: [{ showType: 'once' }] + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/Popover/index.vue b/src/components/DiyEditor/components/mobile/Popover/index.vue new file mode 100644 index 0000000..347599b --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Popover/index.vue @@ -0,0 +1,38 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/Popover/property.vue b/src/components/DiyEditor/components/mobile/Popover/property.vue new file mode 100644 index 0000000..21be46e --- /dev/null +++ b/src/components/DiyEditor/components/mobile/Popover/property.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/ProductCard/config.ts b/src/components/DiyEditor/components/mobile/ProductCard/config.ts new file mode 100644 index 0000000..735b6ba --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductCard/config.ts @@ -0,0 +1,97 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 商品卡片属性 */ +export interface ProductCardProperty { + // 布局类型:单列大图 | 单列小图 | 双列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol' + // 商品字段 + fields: { + // 商品名称 + name: ProductCardFieldProperty + // 商品简介 + introduction: ProductCardFieldProperty + // 商品价格 + price: ProductCardFieldProperty + // 商品市场价 + marketPrice: ProductCardFieldProperty + // 商品销量 + salesCount: ProductCardFieldProperty + // 商品库存 + stock: ProductCardFieldProperty + } + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标图片 + imgUrl: string + } + // 按钮 + btnBuy: { + // 类型:文字 | 图片 + type: 'text' | 'img' + // 文字 + text: string + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string + // 文字按钮:背景渐变结束颜色 + bgEndColor: string + // 图片按钮:图片地址 + imgUrl: string + } + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间距 + space: number + // 商品编号列表 + spuIds: number[] + // 组件样式 + style: ComponentStyle +} +// 商品字段 +export interface ProductCardFieldProperty { + // 是否显示 + show: boolean + // 颜色 + color: string +} + +// 定义组件 +export const component = { + id: 'ProductCard', + name: '商品卡片', + icon: 'fluent:text-column-two-left-24-filled', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' } + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即购买', + // todo: @owen 根据主题色配置 + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '' + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + spuIds: [], + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/ProductCard/index.vue b/src/components/DiyEditor/components/mobile/ProductCard/index.vue new file mode 100644 index 0000000..25f8cb8 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductCard/index.vue @@ -0,0 +1,167 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/ProductCard/property.vue b/src/components/DiyEditor/components/mobile/ProductCard/property.vue new file mode 100644 index 0000000..91846e6 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductCard/property.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/ProductList/config.ts b/src/components/DiyEditor/components/mobile/ProductList/config.ts new file mode 100644 index 0000000..1f16832 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductList/config.ts @@ -0,0 +1,64 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 商品栏属性 */ +export interface ProductListProperty { + // 布局类型:双列 | 三列 | 水平滑动 + layoutType: 'twoCol' | 'threeCol' | 'horizSwiper' + // 商品字段 + fields: { + // 商品名称 + name: ProductListFieldProperty + // 商品价格 + price: ProductListFieldProperty + } + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标图片 + imgUrl: string + } + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间距 + space: number + // 商品编号列表 + spuIds: number[] + // 组件样式 + style: ComponentStyle +} +// 商品字段 +export interface ProductListFieldProperty { + // 是否显示 + show: boolean + // 颜色 + color: string +} + +// 定义组件 +export const component = { + id: 'ProductList', + name: '商品栏', + icon: 'fluent:text-column-two-24-filled', + property: { + layoutType: 'twoCol', + fields: { + name: { show: true, color: '#000' }, + price: { show: true, color: '#ff3000' } + }, + badge: { show: false, imgUrl: '' }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + spuIds: [], + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/ProductList/index.vue b/src/components/DiyEditor/components/mobile/ProductList/index.vue new file mode 100644 index 0000000..a51fc07 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductList/index.vue @@ -0,0 +1,132 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/ProductList/property.vue b/src/components/DiyEditor/components/mobile/ProductList/property.vue new file mode 100644 index 0000000..d7a5a7c --- /dev/null +++ b/src/components/DiyEditor/components/mobile/ProductList/property.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionArticle/config.ts b/src/components/DiyEditor/components/mobile/PromotionArticle/config.ts new file mode 100644 index 0000000..c6270c2 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionArticle/config.ts @@ -0,0 +1,25 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 营销文章属性 */ +export interface PromotionArticleProperty { + // 文章编号 + id: number + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'PromotionArticle', + name: '营销文章', + icon: 'ph:article-medium', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/PromotionArticle/index.vue b/src/components/DiyEditor/components/mobile/PromotionArticle/index.vue new file mode 100644 index 0000000..e003b08 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionArticle/index.vue @@ -0,0 +1,27 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionArticle/property.vue b/src/components/DiyEditor/components/mobile/PromotionArticle/property.vue new file mode 100644 index 0000000..10c5840 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionArticle/property.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionCombination/config.ts b/src/components/DiyEditor/components/mobile/PromotionCombination/config.ts new file mode 100644 index 0000000..f4fdf6e --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionCombination/config.ts @@ -0,0 +1,96 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 拼团属性 */ +export interface PromotionCombinationProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol' + // 商品字段 + fields: { + // 商品名称 + name: PromotionCombinationFieldProperty + // 商品简介 + introduction: PromotionCombinationFieldProperty + // 商品价格 + price: PromotionCombinationFieldProperty + // 市场价 + marketPrice: PromotionCombinationFieldProperty + // 商品销量 + salesCount: PromotionCombinationFieldProperty + // 商品库存 + stock: PromotionCombinationFieldProperty + } + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标图片 + imgUrl: string + } + // 按钮 + btnBuy: { + // 类型:文字 | 图片 + type: 'text' | 'img' + // 文字 + text: string + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string + // 文字按钮:背景渐变结束颜色 + bgEndColor: string + // 图片按钮:图片地址 + imgUrl: string + } + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间距 + space: number + // 拼团活动编号 + activityIds: number[] + // 组件样式 + style: ComponentStyle +} + +// 商品字段 +export interface PromotionCombinationFieldProperty { + // 是否显示 + show: boolean + // 颜色 + color: string +} + +// 定义组件 +export const component = { + id: 'PromotionCombination', + name: '拼团', + icon: 'mdi:account-group', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' } + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '去拼团', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '' + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue b/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue new file mode 100644 index 0000000..d41bf1c --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue @@ -0,0 +1,201 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionCombination/property.vue b/src/components/DiyEditor/components/mobile/PromotionCombination/property.vue new file mode 100644 index 0000000..b796e6a --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionCombination/property.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionPoint/config.ts b/src/components/DiyEditor/components/mobile/PromotionPoint/config.ts new file mode 100644 index 0000000..75aa0ff --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionPoint/config.ts @@ -0,0 +1,96 @@ +import {ComponentStyle, DiyComponent} from '@/components/DiyEditor/util' + +/** 积分商城属性 */ +export interface PromotionPointProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol' + // 商品字段 + fields: { + // 商品名称 + name: PromotionPointFieldProperty + // 商品简介 + introduction: PromotionPointFieldProperty + // 商品价格 + price: PromotionPointFieldProperty + // 市场价 + marketPrice: PromotionPointFieldProperty + // 商品销量 + salesCount: PromotionPointFieldProperty + // 商品库存 + stock: PromotionPointFieldProperty + } + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标图片 + imgUrl: string + } + // 按钮 + btnBuy: { + // 类型:文字 | 图片 + type: 'text' | 'img' + // 文字 + text: string + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string + // 文字按钮:背景渐变结束颜色 + bgEndColor: string + // 图片按钮:图片地址 + imgUrl: string + } + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间距 + space: number + // 秒杀活动编号 + activityIds: number[] + // 组件样式 + style: ComponentStyle +} + +// 商品字段 +export interface PromotionPointFieldProperty { + // 是否显示 + show: boolean + // 颜色 + color: string +} + +// 定义组件 +export const component = { + id: 'PromotionPoint', + name: '积分商城', + icon: 'ep:present', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' } + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即兑换', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '' + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/PromotionPoint/index.vue b/src/components/DiyEditor/components/mobile/PromotionPoint/index.vue new file mode 100644 index 0000000..4acd93f --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionPoint/index.vue @@ -0,0 +1,202 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionPoint/property.vue b/src/components/DiyEditor/components/mobile/PromotionPoint/property.vue new file mode 100644 index 0000000..ea20776 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionPoint/property.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionSeckill/config.ts b/src/components/DiyEditor/components/mobile/PromotionSeckill/config.ts new file mode 100644 index 0000000..022be92 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionSeckill/config.ts @@ -0,0 +1,96 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 秒杀属性 */ +export interface PromotionSeckillProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol' + // 商品字段 + fields: { + // 商品名称 + name: PromotionSeckillFieldProperty + // 商品简介 + introduction: PromotionSeckillFieldProperty + // 商品价格 + price: PromotionSeckillFieldProperty + // 市场价 + marketPrice: PromotionSeckillFieldProperty + // 商品销量 + salesCount: PromotionSeckillFieldProperty + // 商品库存 + stock: PromotionSeckillFieldProperty + } + // 角标 + badge: { + // 是否显示 + show: boolean + // 角标图片 + imgUrl: string + } + // 按钮 + btnBuy: { + // 类型:文字 | 图片 + type: 'text' | 'img' + // 文字 + text: string + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string + // 文字按钮:背景渐变结束颜色 + bgEndColor: string + // 图片按钮:图片地址 + imgUrl: string + } + // 上圆角 + borderRadiusTop: number + // 下圆角 + borderRadiusBottom: number + // 间距 + space: number + // 秒杀活动编号 + activityIds: number[] + // 组件样式 + style: ComponentStyle +} + +// 商品字段 +export interface PromotionSeckillFieldProperty { + // 是否显示 + show: boolean + // 颜色 + color: string +} + +// 定义组件 +export const component = { + id: 'PromotionSeckill', + name: '秒杀', + icon: 'mdi:calendar-time', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' } + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即秒杀', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '' + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/PromotionSeckill/index.vue b/src/components/DiyEditor/components/mobile/PromotionSeckill/index.vue new file mode 100644 index 0000000..3d34a3d --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionSeckill/index.vue @@ -0,0 +1,201 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/PromotionSeckill/property.vue b/src/components/DiyEditor/components/mobile/PromotionSeckill/property.vue new file mode 100644 index 0000000..594c10b --- /dev/null +++ b/src/components/DiyEditor/components/mobile/PromotionSeckill/property.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/SearchBar/config.ts b/src/components/DiyEditor/components/mobile/SearchBar/config.ts new file mode 100644 index 0000000..ef47b27 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/SearchBar/config.ts @@ -0,0 +1,43 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 搜索框属性 */ +export interface SearchProperty { + height: number // 搜索栏高度 + showScan: boolean // 显示扫一扫 + borderRadius: number // 框体样式 + placeholder: string // 占位文字 + placeholderPosition: PlaceholderPosition // 占位文字位置 + backgroundColor: string // 框体颜色 + textColor: string // 字体颜色 + hotKeywords: string[] // 热词 + style: ComponentStyle +} + +// 文字位置 +export type PlaceholderPosition = 'left' | 'center' + +// 定义组件 +export const component = { + id: 'SearchBar', + name: '搜索框', + icon: 'ep:search', + property: { + height: 28, + showScan: false, + borderRadius: 0, + placeholder: '搜索商品', + placeholderPosition: 'left', + backgroundColor: 'rgb(238, 238, 238)', + textColor: 'rgb(150, 151, 153)', + hotKeywords: [], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + paddingTop: 8, + paddingRight: 8, + paddingBottom: 8, + paddingLeft: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/SearchBar/index.vue b/src/components/DiyEditor/components/mobile/SearchBar/index.vue new file mode 100644 index 0000000..9de261a --- /dev/null +++ b/src/components/DiyEditor/components/mobile/SearchBar/index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/SearchBar/property.vue b/src/components/DiyEditor/components/mobile/SearchBar/property.vue new file mode 100644 index 0000000..48441d0 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/SearchBar/property.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/TabBar/config.ts b/src/components/DiyEditor/components/mobile/TabBar/config.ts new file mode 100644 index 0000000..88d706f --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TabBar/config.ts @@ -0,0 +1,97 @@ +import { DiyComponent } from '@/components/DiyEditor/util' + +/** 底部导航菜单属性 */ +export interface TabBarProperty { + // 选项列表 + items: TabBarItemProperty[] + // 主题 + theme: string + // 样式 + style: TabBarStyle +} + +// 选项属性 +export interface TabBarItemProperty { + // 标签文字 + text: string + // 链接 + url: string + // 默认图标链接 + iconUrl: string + // 选中的图标链接 + activeIconUrl: string +} + +// 样式 +export interface TabBarStyle { + // 背景类型 + bgType: 'color' | 'img' + // 背景颜色 + bgColor: string + // 图片链接 + bgImg: string + // 默认颜色 + color: string + // 选中的颜色 + activeColor: string +} + +// 定义组件 +export const component = { + id: 'TabBar', + name: '底部导航', + icon: 'fluent:table-bottom-row-16-filled', + property: { + theme: 'red', + style: { + bgType: 'color', + bgColor: '#fff', + color: '#282828', + activeColor: '#fc4141' + }, + items: [ + { + text: '首页', + url: '/pages/index/index', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/1-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/1-002.png' + }, + { + text: '分类', + url: '/pages/index/category?id=3', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/2-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/2-002.png' + }, + { + text: '购物车', + url: '/pages/index/cart', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/3-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/3-002.png' + }, + { + text: '我的', + url: '/pages/index/user', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-002.png' + } + ] + } +} as DiyComponent + +export const THEME_LIST = [ + { id: 'red', name: '中国红', icon: 'icon-park-twotone:theme', color: '#d10019' }, + { id: 'orange', name: '桔橙', icon: 'icon-park-twotone:theme', color: '#f37b1d' }, + { id: 'gold', name: '明黄', icon: 'icon-park-twotone:theme', color: '#fbbd08' }, + { id: 'green', name: '橄榄绿', icon: 'icon-park-twotone:theme', color: '#8dc63f' }, + { id: 'cyan', name: '天青', icon: 'icon-park-twotone:theme', color: '#1cbbb4' }, + { id: 'blue', name: '海蓝', icon: 'icon-park-twotone:theme', color: '#0081ff' }, + { id: 'purple', name: '姹紫', icon: 'icon-park-twotone:theme', color: '#6739b6' }, + { id: 'brightRed', name: '嫣红', icon: 'icon-park-twotone:theme', color: '#e54d42' }, + { id: 'forestGreen', name: '森绿', icon: 'icon-park-twotone:theme', color: '#39b54a' }, + { id: 'mauve', name: '木槿', icon: 'icon-park-twotone:theme', color: '#9c26b0' }, + { id: 'pink', name: '桃粉', icon: 'icon-park-twotone:theme', color: '#e03997' }, + { id: 'brown', name: '棕褐', icon: 'icon-park-twotone:theme', color: '#a5673f' }, + { id: 'grey', name: '玄灰', icon: 'icon-park-twotone:theme', color: '#8799a3' }, + { id: 'gray', name: '草灰', icon: 'icon-park-twotone:theme', color: '#aaaaaa' }, + { id: 'black', name: '墨黑', icon: 'icon-park-twotone:theme', color: '#333333' } +] diff --git a/src/components/DiyEditor/components/mobile/TabBar/index.vue b/src/components/DiyEditor/components/mobile/TabBar/index.vue new file mode 100644 index 0000000..44ba43c --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TabBar/index.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/components/DiyEditor/components/mobile/TabBar/property.vue b/src/components/DiyEditor/components/mobile/TabBar/property.vue new file mode 100644 index 0000000..e435012 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TabBar/property.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/TitleBar/config.ts b/src/components/DiyEditor/components/mobile/TitleBar/config.ts new file mode 100644 index 0000000..0c104c9 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TitleBar/config.ts @@ -0,0 +1,67 @@ +import {ComponentStyle, DiyComponent} from '@/components/DiyEditor/util' + +/** 标题栏属性 */ +export interface TitleBarProperty { + // 偏移 + marginLeft: number + // 显示位置 + textAlign: 'left' | 'center' + // 主标题 + title: string + // 副标题 + description: string + // 标题大小 + titleSize: number + // 描述大小 + descriptionSize: number + // 标题粗细 + titleWeight: number + // 描述粗细 + descriptionWeight: number + // 标题颜色 + titleColor: string + // 描述颜色 + descriptionColor: string + // 查看更多 + more: { + // 是否显示查看更多 + show: false + // 样式选择 + type: 'text' | 'icon' | 'all' + // 自定义文字 + text: string + // 链接 + url: string + } + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'TitleBar', + name: '标题栏', + icon: 'material-symbols:line-start', + property: { + title: '主标题', + description: '副标题', + titleSize: 16, + descriptionSize: 12, + titleWeight: 400, + textAlign: 'left', + descriptionWeight: 200, + titleColor: 'rgba(50, 50, 51, 10)', + descriptionColor: 'rgba(150, 151, 153, 10)', + more: { + //查看更多 + show: false, + type: 'icon', + text: '查看更多', + url: '' + }, + style: { + bgType: 'color', + bgColor: '#fff' + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/TitleBar/index.vue b/src/components/DiyEditor/components/mobile/TitleBar/index.vue new file mode 100644 index 0000000..7b90729 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TitleBar/index.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/components/DiyEditor/components/mobile/TitleBar/property.vue b/src/components/DiyEditor/components/mobile/TitleBar/property.vue new file mode 100644 index 0000000..b31b1e2 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/TitleBar/property.vue @@ -0,0 +1,116 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/UserCard/config.ts b/src/components/DiyEditor/components/mobile/UserCard/config.ts new file mode 100644 index 0000000..7b33776 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCard/config.ts @@ -0,0 +1,21 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 用户卡片属性 */ +export interface UserCardProperty { + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'UserCard', + name: '用户卡片', + icon: 'mdi:user-card-details', + property: { + style: { + bgType: 'color', + bgColor: '', + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/UserCard/index.vue b/src/components/DiyEditor/components/mobile/UserCard/index.vue new file mode 100644 index 0000000..14b447c --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCard/index.vue @@ -0,0 +1,29 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/UserCard/property.vue b/src/components/DiyEditor/components/mobile/UserCard/property.vue new file mode 100644 index 0000000..50ecb55 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCard/property.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/UserCoupon/config.ts b/src/components/DiyEditor/components/mobile/UserCoupon/config.ts new file mode 100644 index 0000000..92eba9b --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCoupon/config.ts @@ -0,0 +1,23 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 用户卡券属性 */ +export interface UserCouponProperty { + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'UserCoupon', + name: '用户卡券', + icon: 'ep:ticket', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/UserCoupon/index.vue b/src/components/DiyEditor/components/mobile/UserCoupon/index.vue new file mode 100644 index 0000000..27ad310 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCoupon/index.vue @@ -0,0 +1,15 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/UserCoupon/property.vue b/src/components/DiyEditor/components/mobile/UserCoupon/property.vue new file mode 100644 index 0000000..221cc90 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserCoupon/property.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/UserOrder/config.ts b/src/components/DiyEditor/components/mobile/UserOrder/config.ts new file mode 100644 index 0000000..f9c5a6d --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserOrder/config.ts @@ -0,0 +1,23 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 用户订单属性 */ +export interface UserOrderProperty { + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'UserOrder', + name: '用户订单', + icon: 'ep:list', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/UserOrder/index.vue b/src/components/DiyEditor/components/mobile/UserOrder/index.vue new file mode 100644 index 0000000..450ae54 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserOrder/index.vue @@ -0,0 +1,13 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/UserOrder/property.vue b/src/components/DiyEditor/components/mobile/UserOrder/property.vue new file mode 100644 index 0000000..d315db6 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserOrder/property.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/UserWallet/config.ts b/src/components/DiyEditor/components/mobile/UserWallet/config.ts new file mode 100644 index 0000000..4e0955f --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserWallet/config.ts @@ -0,0 +1,23 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 用户资产属性 */ +export interface UserWalletProperty { + // 组件样式 + style: ComponentStyle +} + +// 定义组件 +export const component = { + id: 'UserWallet', + name: '用户资产', + icon: 'ep:wallet-filled', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8 + } as ComponentStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/UserWallet/index.vue b/src/components/DiyEditor/components/mobile/UserWallet/index.vue new file mode 100644 index 0000000..0efc937 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserWallet/index.vue @@ -0,0 +1,15 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/UserWallet/property.vue b/src/components/DiyEditor/components/mobile/UserWallet/property.vue new file mode 100644 index 0000000..e0ac83e --- /dev/null +++ b/src/components/DiyEditor/components/mobile/UserWallet/property.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/VideoPlayer/config.ts b/src/components/DiyEditor/components/mobile/VideoPlayer/config.ts new file mode 100644 index 0000000..02f0374 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/VideoPlayer/config.ts @@ -0,0 +1,37 @@ +import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util' + +/** 视频播放属性 */ +export interface VideoPlayerProperty { + // 视频链接 + videoUrl: string + // 封面链接 + posterUrl: string + // 是否自动播放 + autoplay: boolean + // 组件样式 + style: VideoPlayerStyle +} + +// 视频播放样式 +export interface VideoPlayerStyle extends ComponentStyle { + // 视频高度 + height: number +} + +// 定义组件 +export const component = { + id: 'VideoPlayer', + name: '视频播放', + icon: 'ep:video-play', + property: { + videoUrl: '', + posterUrl: '', + autoplay: false, + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + height: 300 + } as VideoPlayerStyle + } +} as DiyComponent diff --git a/src/components/DiyEditor/components/mobile/VideoPlayer/index.vue b/src/components/DiyEditor/components/mobile/VideoPlayer/index.vue new file mode 100644 index 0000000..fa9a914 --- /dev/null +++ b/src/components/DiyEditor/components/mobile/VideoPlayer/index.vue @@ -0,0 +1,30 @@ + + + + diff --git a/src/components/DiyEditor/components/mobile/VideoPlayer/property.vue b/src/components/DiyEditor/components/mobile/VideoPlayer/property.vue new file mode 100644 index 0000000..1c3deec --- /dev/null +++ b/src/components/DiyEditor/components/mobile/VideoPlayer/property.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/DiyEditor/components/mobile/index.ts b/src/components/DiyEditor/components/mobile/index.ts new file mode 100644 index 0000000..c0dc67d --- /dev/null +++ b/src/components/DiyEditor/components/mobile/index.ts @@ -0,0 +1,61 @@ +/* + * 组件注册 + * + * 组件规范: + * 1. 每个子目录就是一个独立的组件,每个目录包括以下三个文件: + * 2. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型 + * 3. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可 + * 4. property.vue:组件属性表单,用于配置组件,必选, + * + * 注: + * 组件ID以config.ts中配置的id为准,与组件目录的名称无关,但还是建议组件目录的名称与组件ID保持一致 + */ + +// 导入组件界面模块 +const viewModules: Record = import.meta.glob('./*/*.vue') +// 导入配置模块 +const configModules: Record = import.meta.glob('./*/config.ts', { eager: true }) + +// 界面模块 +const components = {} +// 组件配置模块 +const componentConfigs = {} + +// 组件界面的类型 +type ViewType = 'index' | 'property' + +/** + * 注册组件的界面模块 + * + * @param componentId 组件ID + * @param configPath 配置模块的文件路径 + * @param viewType 组件界面的类型 + */ +const registerComponentViewModule = ( + componentId: string, + configPath: string, + viewType: ViewType +) => { + const viewPath = configPath.replace('config.ts', `${viewType}.vue`) + const viewModule = viewModules[viewPath] + if (viewModule) { + // 定义异步组件 + components[componentId] = defineAsyncComponent(viewModule) + } +} + +// 注册 +Object.keys(configModules).forEach((modulePath: string) => { + const component = configModules[modulePath].component + const componentId = component?.id + if (componentId) { + // 注册组件 + componentConfigs[componentId] = component + // 注册预览界面 + registerComponentViewModule(componentId, modulePath, 'index') + // 注册属性配置表单 + registerComponentViewModule(`${componentId}Property`, modulePath, 'property') + } +}) + +export { components, componentConfigs } diff --git a/src/components/DiyEditor/index.vue b/src/components/DiyEditor/index.vue new file mode 100644 index 0000000..27d3fc1 --- /dev/null +++ b/src/components/DiyEditor/index.vue @@ -0,0 +1,599 @@ + diff --git a/src/components/Icon/index.ts b/src/components/Icon/index.ts new file mode 100644 index 0000000..33d1de3 --- /dev/null +++ b/src/components/Icon/index.ts @@ -0,0 +1,4 @@ +import Icon from './src/Icon.vue' +import IconSelect from './src/IconSelect.vue' + +export { Icon, IconSelect } diff --git a/src/components/Icon/src/Icon.vue b/src/components/Icon/src/Icon.vue new file mode 100644 index 0000000..a90bb37 --- /dev/null +++ b/src/components/Icon/src/Icon.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/components/Icon/src/IconSelect.vue b/src/components/Icon/src/IconSelect.vue new file mode 100644 index 0000000..76cc6d5 --- /dev/null +++ b/src/components/Icon/src/IconSelect.vue @@ -0,0 +1,239 @@ + + + + + diff --git a/src/components/Icon/src/data.ts b/src/components/Icon/src/data.ts new file mode 100644 index 0000000..2a4ed5a --- /dev/null +++ b/src/components/Icon/src/data.ts @@ -0,0 +1,1961 @@ +export const IconJson = { + 'ep:': [ + 'add-location', + 'aim', + 'alarm-clock', + 'apple', + 'arrow-down', + 'arrow-down-bold', + 'arrow-left', + 'arrow-left-bold', + 'arrow-right', + 'arrow-right-bold', + 'arrow-up', + 'arrow-up-bold', + 'avatar', + 'back', + 'baseball', + 'basketball', + 'bell', + 'bell-filled', + 'bicycle', + 'bottom', + 'bottom-left', + 'bottom-right', + 'bowl', + 'box', + 'briefcase', + 'brush', + 'brush-filled', + 'burger', + 'calendar', + 'camera', + 'camera-filled', + 'caret-bottom', + 'caret-left', + 'caret-right', + 'caret-top', + 'cellphone', + 'chat-dot-round', + 'chat-dot-square', + 'chat-line-round', + 'chat-line-square', + 'chat-round', + 'chat-square', + 'check', + 'checked', + 'cherry', + 'chicken', + 'circle-check', + 'circle-check-filled', + 'circle-close', + 'circle-close-filled', + 'circle-plus', + 'circle-plus-filled', + 'clock', + 'close', + 'close-bold', + 'cloudy', + 'coffee', + 'coffee-cup', + 'coin', + 'cold-drink', + 'collection', + 'collection-tag', + 'comment', + 'compass', + 'connection', + 'coordinate', + 'copy-document', + 'cpu', + 'credit-card', + 'crop', + 'd-arrow-left', + 'd-arrow-right', + 'd-caret', + 'data-analysis', + 'data-board', + 'data-line', + 'delete', + 'delete-filled', + 'delete-location', + 'dessert', + 'discount', + 'dish', + 'dish-dot', + 'document', + 'document-add', + 'document-checked', + 'document-copy', + 'document-delete', + 'document-remove', + 'download', + 'drizzling', + 'edit', + 'edit-pen', + 'eleme', + 'eleme-filled', + 'expand', + 'failed', + 'female', + 'files', + 'film', + 'filter', + 'finished', + 'first-aid-kit', + 'flag', + 'fold', + 'folder', + 'folder-add', + 'folder-checked', + 'folder-delete', + 'folder-opened', + 'folder-remove', + 'food', + 'football', + 'fork-spoon', + 'fries', + 'full-screen', + 'goblet', + 'goblet-full', + 'goblet-square', + 'goblet-square-full', + 'goods', + 'goods-filled', + 'grape', + 'grid', + 'guide', + 'headset', + 'help', + 'help-filled', + 'histogram', + 'home-filled', + 'hot-water', + 'house', + 'ice-cream', + 'ice-cream-round', + 'ice-cream-square', + 'ice-drink', + 'ice-tea', + 'info-filled', + 'iphone', + 'key', + 'knife-fork', + 'lightning', + 'link', + 'list', + 'loading', + 'location', + 'location-filled', + 'location-information', + 'lock', + 'lollipop', + 'magic-stick', + 'magnet', + 'male', + 'management', + 'map-location', + 'medal', + 'menu', + 'message', + 'message-box', + 'mic', + 'microphone', + 'milk-tea', + 'minus', + 'money', + 'monitor', + 'moon', + 'moon-night', + 'more', + 'more-filled', + 'mostly-cloudy', + 'mouse', + 'mug', + 'mute', + 'mute-notification', + 'no-smoking', + 'notebook', + 'notification', + 'odometer', + 'office-building', + 'open', + 'operation', + 'opportunity', + 'orange', + 'paperclip', + 'partly-cloudy', + 'pear', + 'phone', + 'phone-filled', + 'picture', + 'picture-filled', + 'picture-rounded', + 'pie-chart', + 'place', + 'platform', + 'plus', + 'pointer', + 'position', + 'postcard', + 'pouring', + 'present', + 'price-tag', + 'printer', + 'promotion', + 'question-filled', + 'rank', + 'reading', + 'reading-lamp', + 'refresh', + 'refresh-left', + 'refresh-right', + 'refrigerator', + 'remove', + 'remove-filled', + 'right', + 'scale-to-original', + 'school', + 'scissor', + 'search', + 'select', + 'sell', + 'semi-select', + 'service', + 'set-up', + 'setting', + 'share', + 'ship', + 'shop', + 'shopping-bag', + 'shopping-cart', + 'shopping-cart-full', + 'smoking', + 'soccer', + 'sold-out', + 'sort', + 'sort-down', + 'sort-up', + 'stamp', + 'star', + 'star-filled', + 'stopwatch', + 'success-filled', + 'sugar', + 'suitcase', + 'sunny', + 'sunrise', + 'sunset', + 'switch', + 'switch-button', + 'takeaway-box', + 'ticket', + 'tickets', + 'timer', + 'toilet-paper', + 'tools', + 'top', + 'top-left', + 'top-right', + 'trend-charts', + 'trophy', + 'turn-off', + 'umbrella', + 'unlock', + 'upload', + 'upload-filled', + 'user', + 'user-filled', + 'van', + 'video-camera', + 'video-camera-filled', + 'video-pause', + 'video-play', + 'view', + 'wallet', + 'wallet-filled', + 'warning', + 'warning-filled', + 'watch', + 'watermelon', + 'wind-power', + 'zoom-in', + 'zoom-out' + ], + 'fa:': [ + '500px', + 'address-book', + 'address-book-o', + 'address-card', + 'address-card-o', + 'adjust', + 'adn', + 'align-center', + 'align-justify', + 'align-left', + 'amazon', + 'ambulance', + 'american-sign-language-interpreting', + 'anchor', + 'android', + 'angellist', + 'angle-double-left', + 'angle-double-up', + 'angle-down', + 'angle-left', + 'angle-up', + 'apple', + 'archive', + 'area-chart', + 'arrow-circle-left', + 'arrow-circle-o-left', + 'arrow-circle-o-up', + 'arrow-circle-up', + 'arrow-left', + 'arrow-up', + 'arrows', + 'arrows-alt', + 'arrows-h', + 'arrows-v', + 'assistive-listening-systems', + 'asterisk', + 'at', + 'audio-description', + 'automobile', + 'backward', + 'balance-scale', + 'ban', + 'bandcamp', + 'bank', + 'bar-chart', + 'barcode', + 'bars', + 'bath', + 'battery', + 'battery-0', + 'battery-1', + 'battery-2', + 'battery-3', + 'bed', + 'beer', + 'behance', + 'behance-square', + 'bell', + 'bell-o', + 'bell-slash', + 'bell-slash-o', + 'bicycle', + 'binoculars', + 'birthday-cake', + 'bitbucket', + 'bitbucket-square', + 'bitcoin', + 'black-tie', + 'blind', + 'bluetooth', + 'bluetooth-b', + 'bold', + 'bolt', + 'bomb', + 'book', + 'bookmark', + 'bookmark-o', + 'braille', + 'briefcase', + 'bug', + 'building', + 'building-o', + 'bullhorn', + 'bullseye', + 'bus', + 'buysellads', + 'cab', + 'calculator', + 'calendar', + 'calendar-check-o', + 'calendar-minus-o', + 'calendar-o', + 'calendar-plus-o', + 'calendar-times-o', + 'camera', + 'camera-retro', + 'caret-down', + 'caret-left', + 'caret-square-o-left', + 'caret-square-o-up', + 'caret-up', + 'cart-arrow-down', + 'cart-plus', + 'cc', + 'cc-amex', + 'cc-diners-club', + 'cc-discover', + 'cc-jcb', + 'cc-mastercard', + 'cc-paypal', + 'cc-stripe', + 'cc-visa', + 'certificate', + 'chain', + 'chain-broken', + 'check', + 'check-circle', + 'check-circle-o', + 'check-square', + 'check-square-o', + 'chevron-circle-left', + 'chevron-circle-up', + 'chevron-down', + 'chevron-left', + 'chevron-up', + 'child', + 'chrome', + 'circle', + 'circle-o', + 'circle-o-notch', + 'circle-thin', + 'clipboard', + 'clock-o', + 'clone', + 'close', + 'cloud', + 'cloud-download', + 'cloud-upload', + 'cny', + 'code', + 'code-fork', + 'codepen', + 'codiepie', + 'coffee', + 'cog', + 'cogs', + 'columns', + 'comment', + 'comment-o', + 'commenting', + 'commenting-o', + 'comments', + 'comments-o', + 'compass', + 'compress', + 'connectdevelop', + 'contao', + 'copy', + 'copyright', + 'creative-commons', + 'credit-card', + 'credit-card-alt', + 'crop', + 'crosshairs', + 'css3', + 'cube', + 'cubes', + 'cut', + 'cutlery', + 'dashboard', + 'dashcube', + 'database', + 'deaf', + 'dedent', + 'delicious', + 'desktop', + 'deviantart', + 'diamond', + 'digg', + 'dollar', + 'dot-circle-o', + 'download', + 'dribbble', + 'drivers-license', + 'drivers-license-o', + 'dropbox', + 'drupal', + 'edge', + 'edit', + 'eercast', + 'eject', + 'ellipsis-h', + 'ellipsis-v', + 'empire', + 'envelope', + 'envelope-o', + 'envelope-open', + 'envelope-open-o', + 'envelope-square', + 'envira', + 'eraser', + 'etsy', + 'eur', + 'exchange', + 'exclamation', + 'exclamation-circle', + 'exclamation-triangle', + 'expand', + 'expeditedssl', + 'external-link', + 'external-link-square', + 'eye', + 'eye-slash', + 'eyedropper', + 'fa', + 'facebook', + 'facebook-official', + 'facebook-square', + 'fast-backward', + 'fax', + 'feed', + 'female', + 'fighter-jet', + 'file', + 'file-archive-o', + 'file-audio-o', + 'file-code-o', + 'file-excel-o', + 'file-image-o', + 'file-movie-o', + 'file-o', + 'file-pdf-o', + 'file-powerpoint-o', + 'file-text', + 'file-text-o', + 'file-word-o', + 'film', + 'filter', + 'fire', + 'fire-extinguisher', + 'firefox', + 'first-order', + 'flag', + 'flag-checkered', + 'flag-o', + 'flask', + 'flickr', + 'floppy-o', + 'folder', + 'folder-o', + 'folder-open', + 'folder-open-o', + 'font', + 'fonticons', + 'fort-awesome', + 'forumbee', + 'foursquare', + 'free-code-camp', + 'frown-o', + 'futbol-o', + 'gamepad', + 'gavel', + 'gbp', + 'genderless', + 'get-pocket', + 'gg', + 'gg-circle', + 'gift', + 'git', + 'git-square', + 'github', + 'github-alt', + 'github-square', + 'gitlab', + 'gittip', + 'glass', + 'glide', + 'glide-g', + 'globe', + 'google', + 'google-plus', + 'google-plus-circle', + 'google-plus-square', + 'google-wallet', + 'graduation-cap', + 'grav', + 'group', + 'h-square', + 'hacker-news', + 'hand-grab-o', + 'hand-lizard-o', + 'hand-o-left', + 'hand-o-up', + 'hand-paper-o', + 'hand-peace-o', + 'hand-pointer-o', + 'hand-scissors-o', + 'hand-spock-o', + 'handshake-o', + 'hashtag', + 'hdd-o', + 'header', + 'headphones', + 'heart', + 'heart-o', + 'heartbeat', + 'history', + 'home', + 'hospital-o', + 'hourglass', + 'hourglass-1', + 'hourglass-2', + 'hourglass-3', + 'hourglass-o', + 'houzz', + 'html5', + 'i-cursor', + 'id-badge', + 'ils', + 'image', + 'imdb', + 'inbox', + 'indent', + 'industry', + 'info', + 'info-circle', + 'inr', + 'instagram', + 'internet-explorer', + 'intersex', + 'ioxhost', + 'italic', + 'joomla', + 'jsfiddle', + 'key', + 'keyboard-o', + 'krw', + 'language', + 'laptop', + 'lastfm', + 'lastfm-square', + 'leaf', + 'leanpub', + 'lemon-o', + 'level-up', + 'life-bouy', + 'lightbulb-o', + 'line-chart', + 'linkedin', + 'linkedin-square', + 'linode', + 'linux', + 'list', + 'list-alt', + 'list-ol', + 'list-ul', + 'location-arrow', + 'lock', + 'long-arrow-left', + 'long-arrow-up', + 'low-vision', + 'magic', + 'magnet', + 'mail-forward', + 'mail-reply', + 'mail-reply-all', + 'male', + 'map', + 'map-marker', + 'map-o', + 'map-pin', + 'map-signs', + 'mars', + 'mars-double', + 'mars-stroke', + 'mars-stroke-h', + 'mars-stroke-v', + 'maxcdn', + 'meanpath', + 'medium', + 'medkit', + 'meetup', + 'meh-o', + 'mercury', + 'microchip', + 'microphone', + 'microphone-slash', + 'minus', + 'minus-circle', + 'minus-square', + 'minus-square-o', + 'mixcloud', + 'mobile', + 'modx', + 'money', + 'moon-o', + 'motorcycle', + 'mouse-pointer', + 'music', + 'neuter', + 'newspaper-o', + 'object-group', + 'object-ungroup', + 'odnoklassniki', + 'odnoklassniki-square', + 'opencart', + 'openid', + 'opera', + 'optin-monster', + 'pagelines', + 'paint-brush', + 'paper-plane', + 'paper-plane-o', + 'paperclip', + 'paragraph', + 'pause', + 'pause-circle', + 'pause-circle-o', + 'paw', + 'paypal', + 'pencil', + 'pencil-square', + 'percent', + 'phone', + 'phone-square', + 'pie-chart', + 'pied-piper', + 'pied-piper-alt', + 'pied-piper-pp', + 'pinterest', + 'pinterest-p', + 'pinterest-square', + 'plane', + 'play', + 'play-circle', + 'play-circle-o', + 'plug', + 'plus', + 'plus-circle', + 'plus-square', + 'plus-square-o', + 'podcast', + 'power-off', + 'print', + 'product-hunt', + 'puzzle-piece', + 'qq', + 'qrcode', + 'question', + 'question-circle', + 'question-circle-o', + 'quora', + 'quote-left', + 'quote-right', + 'ra', + 'random', + 'ravelry', + 'recycle', + 'reddit', + 'reddit-alien', + 'reddit-square', + 'refresh', + 'registered', + 'renren', + 'repeat', + 'retweet', + 'road', + 'rocket', + 'rotate-left', + 'rouble', + 'rss-square', + 'safari', + 'scribd', + 'search', + 'search-minus', + 'search-plus', + 'sellsy', + 'server', + 'share-alt', + 'share-alt-square', + 'share-square', + 'share-square-o', + 'shield', + 'ship', + 'shirtsinbulk', + 'shopping-bag', + 'shopping-basket', + 'shopping-cart', + 'shower', + 'sign-in', + 'sign-language', + 'sign-out', + 'signal', + 'simplybuilt', + 'sitemap', + 'skyatlas', + 'skype', + 'slack', + 'sliders', + 'slideshare', + 'smile-o', + 'snapchat', + 'snapchat-ghost', + 'snapchat-square', + 'snowflake-o', + 'sort', + 'sort-alpha-asc', + 'sort-alpha-desc', + 'sort-amount-asc', + 'sort-amount-desc', + 'sort-asc', + 'sort-numeric-asc', + 'sort-numeric-desc', + 'soundcloud', + 'space-shuttle', + 'spinner', + 'spoon', + 'spotify', + 'square', + 'square-o', + 'stack-exchange', + 'stack-overflow', + 'star', + 'star-half', + 'star-half-empty', + 'star-o', + 'steam', + 'steam-square', + 'step-backward', + 'stethoscope', + 'sticky-note', + 'sticky-note-o', + 'stop', + 'stop-circle', + 'stop-circle-o', + 'street-view', + 'strikethrough', + 'stumbleupon', + 'stumbleupon-circle', + 'subscript', + 'subway', + 'suitcase', + 'sun-o', + 'superpowers', + 'superscript', + 'table', + 'tablet', + 'tag', + 'tags', + 'tasks', + 'telegram', + 'television', + 'tencent-weibo', + 'terminal', + 'text-height', + 'text-width', + 'th', + 'th-large', + 'th-list', + 'themeisle', + 'thermometer', + 'thermometer-0', + 'thermometer-1', + 'thermometer-2', + 'thermometer-3', + 'thumb-tack', + 'thumbs-down', + 'thumbs-o-up', + 'thumbs-up', + 'ticket', + 'times-circle', + 'times-circle-o', + 'times-rectangle', + 'times-rectangle-o', + 'tint', + 'toggle-off', + 'toggle-on', + 'trademark', + 'train', + 'transgender-alt', + 'trash', + 'trash-o', + 'tree', + 'trello', + 'tripadvisor', + 'trophy', + 'truck', + 'try', + 'tty', + 'tumblr', + 'tumblr-square', + 'twitch', + 'twitter', + 'twitter-square', + 'umbrella', + 'underline', + 'universal-access', + 'unlock', + 'unlock-alt', + 'upload', + 'usb', + 'user', + 'user-circle', + 'user-circle-o', + 'user-md', + 'user-o', + 'user-plus', + 'user-secret', + 'user-times', + 'venus', + 'venus-double', + 'venus-mars', + 'viacoin', + 'viadeo', + 'viadeo-square', + 'video-camera', + 'vimeo', + 'vimeo-square', + 'vine', + 'vk', + 'volume-control-phone', + 'volume-down', + 'volume-off', + 'volume-up', + 'wechat', + 'weibo', + 'whatsapp', + 'wheelchair', + 'wheelchair-alt', + 'wifi', + 'wikipedia-w', + 'window-maximize', + 'window-minimize', + 'window-restore', + 'windows', + 'wordpress', + 'wpbeginner', + 'wpexplorer', + 'wpforms', + 'wrench', + 'xing', + 'xing-square', + 'y-combinator', + 'yahoo', + 'yelp', + 'yoast', + 'youtube', + 'youtube-play', + 'youtube-square' + ], + 'fa-solid:': [ + 'abacus', + 'ad', + 'address-book', + 'address-card', + 'adjust', + 'air-freshener', + 'align-center', + 'align-justify', + 'align-left', + 'align-right', + 'allergies', + 'ambulance', + 'american-sign-language-interpreting', + 'anchor', + 'angle-double-down', + 'angle-double-left', + 'angle-double-right', + 'angle-double-up', + 'angle-down', + 'angle-left', + 'angle-right', + 'angle-up', + 'angry', + 'ankh', + 'apple-alt', + 'archive', + 'archway', + 'arrow-alt-circle-down', + 'arrow-alt-circle-left', + 'arrow-alt-circle-right', + 'arrow-alt-circle-up', + 'arrow-circle-down', + 'arrow-circle-left', + 'arrow-circle-right', + 'arrow-circle-up', + 'arrow-down', + 'arrow-left', + 'arrow-right', + 'arrow-up', + 'arrows-alt', + 'arrows-alt-h', + 'arrows-alt-v', + 'assistive-listening-systems', + 'asterisk', + 'at', + 'atlas', + 'atom', + 'audio-description', + 'award', + 'baby', + 'baby-carriage', + 'backspace', + 'backward', + 'bacon', + 'bacteria', + 'bacterium', + 'bahai', + 'balance-scale', + 'balance-scale-left', + 'balance-scale-right', + 'ban', + 'band-aid', + 'barcode', + 'bars', + 'baseball-ball', + 'basketball-ball', + 'bath', + 'battery-empty', + 'battery-full', + 'battery-half', + 'battery-quarter', + 'battery-three-quarters', + 'bed', + 'beer', + 'bell', + 'bell-slash', + 'bezier-curve', + 'bible', + 'bicycle', + 'biking', + 'binoculars', + 'biohazard', + 'birthday-cake', + 'blender', + 'blender-phone', + 'blind', + 'blog', + 'bold', + 'bolt', + 'bomb', + 'bone', + 'bong', + 'book', + 'book-dead', + 'book-medical', + 'book-open', + 'book-reader', + 'bookmark', + 'border-all', + 'border-none', + 'border-style', + 'bowling-ball', + 'box', + 'box-open', + 'box-tissue', + 'boxes', + 'braille', + 'brain', + 'bread-slice', + 'briefcase', + 'briefcase-medical', + 'broadcast-tower', + 'broom', + 'brush', + 'bug', + 'building', + 'bullhorn', + 'bullseye', + 'burn', + 'bus', + 'bus-alt', + 'business-time', + 'calculator', + 'calculator-alt', + 'calendar', + 'calendar-alt', + 'calendar-check', + 'calendar-day', + 'calendar-minus', + 'calendar-plus', + 'calendar-times', + 'calendar-week', + 'camera', + 'camera-retro', + 'campground', + 'candy-cane', + 'cannabis', + 'capsules', + 'car', + 'car-alt', + 'car-battery', + 'car-crash', + 'car-side', + 'caravan', + 'caret-down', + 'caret-left', + 'caret-right', + 'caret-square-down', + 'caret-square-left', + 'caret-square-right', + 'caret-square-up', + 'caret-up', + 'carrot', + 'cart-arrow-down', + 'cart-plus', + 'cash-register', + 'cat', + 'certificate', + 'chair', + 'chalkboard', + 'chalkboard-teacher', + 'charging-station', + 'chart-area', + 'chart-bar', + 'chart-line', + 'chart-pie', + 'check', + 'check-circle', + 'check-double', + 'check-square', + 'cheese', + 'chess', + 'chess-bishop', + 'chess-board', + 'chess-king', + 'chess-knight', + 'chess-pawn', + 'chess-queen', + 'chess-rook', + 'chevron-circle-down', + 'chevron-circle-left', + 'chevron-circle-right', + 'chevron-circle-up', + 'chevron-down', + 'chevron-left', + 'chevron-right', + 'chevron-up', + 'child', + 'church', + 'circle', + 'circle-notch', + 'city', + 'clinic-medical', + 'clipboard', + 'clipboard-check', + 'clipboard-list', + 'clock', + 'clone', + 'closed-captioning', + 'cloud', + 'cloud-download-alt', + 'cloud-meatball', + 'cloud-moon', + 'cloud-moon-rain', + 'cloud-rain', + 'cloud-showers-heavy', + 'cloud-sun', + 'cloud-sun-rain', + 'cloud-upload-alt', + 'cocktail', + 'code', + 'code-branch', + 'coffee', + 'cog', + 'cogs', + 'coins', + 'columns', + 'comment', + 'comment-alt', + 'comment-dollar', + 'comment-dots', + 'comment-medical', + 'comment-slash', + 'comments', + 'comments-dollar', + 'compact-disc', + 'compass', + 'compress', + 'compress-alt', + 'compress-arrows-alt', + 'concierge-bell', + 'cookie', + 'cookie-bite', + 'copy', + 'copyright', + 'couch', + 'credit-card', + 'crop', + 'crop-alt', + 'cross', + 'crosshairs', + 'crow', + 'crown', + 'crutch', + 'cube', + 'cubes', + 'cut', + 'database', + 'deaf', + 'democrat', + 'desktop', + 'dharmachakra', + 'diagnoses', + 'dice', + 'dice-d20', + 'dice-d6', + 'dice-five', + 'dice-four', + 'dice-one', + 'dice-six', + 'dice-three', + 'dice-two', + 'digital-tachograph', + 'directions', + 'disease', + 'divide', + 'dizzy', + 'dna', + 'dog', + 'dollar-sign', + 'dolly', + 'dolly-flatbed', + 'donate', + 'door-closed', + 'door-open', + 'dot-circle', + 'dove', + 'download', + 'drafting-compass', + 'dragon', + 'draw-polygon', + 'drum', + 'drum-steelpan', + 'drumstick-bite', + 'dumbbell', + 'dumpster', + 'dumpster-fire', + 'dungeon', + 'edit', + 'egg', + 'eject', + 'ellipsis-h', + 'ellipsis-v', + 'empty-set', + 'envelope', + 'envelope-open', + 'envelope-open-text', + 'envelope-square', + 'equals', + 'eraser', + 'ethernet', + 'euro-sign', + 'exchange-alt', + 'exclamation', + 'exclamation-circle', + 'exclamation-triangle', + 'expand', + 'expand-alt', + 'expand-arrows-alt', + 'external-link-alt', + 'external-link-square-alt', + 'eye', + 'eye-dropper', + 'eye-slash', + 'fan', + 'fast-backward', + 'fast-forward', + 'faucet', + 'fax', + 'feather', + 'feather-alt', + 'female', + 'fighter-jet', + 'file', + 'file-alt', + 'file-archive', + 'file-audio', + 'file-code', + 'file-contract', + 'file-csv', + 'file-download', + 'file-excel', + 'file-export', + 'file-image', + 'file-import', + 'file-invoice', + 'file-invoice-dollar', + 'file-medical', + 'file-medical-alt', + 'file-pdf', + 'file-powerpoint', + 'file-prescription', + 'file-signature', + 'file-upload', + 'file-video', + 'file-word', + 'fill', + 'fill-drip', + 'film', + 'filter', + 'fingerprint', + 'fire', + 'fire-alt', + 'fire-extinguisher', + 'first-aid', + 'fish', + 'fist-raised', + 'flag', + 'flag-checkered', + 'flag-usa', + 'flask', + 'flushed', + 'folder', + 'folder-minus', + 'folder-open', + 'folder-plus', + 'font', + 'football-ball', + 'forward', + 'frog', + 'frown', + 'frown-open', + 'function', + 'funnel-dollar', + 'futbol', + 'gamepad', + 'gas-pump', + 'gavel', + 'gem', + 'genderless', + 'ghost', + 'gift', + 'gifts', + 'glass-cheers', + 'glass-martini', + 'glass-martini-alt', + 'glass-whiskey', + 'glasses', + 'globe', + 'globe-africa', + 'globe-americas', + 'globe-asia', + 'globe-europe', + 'golf-ball', + 'gopuram', + 'graduation-cap', + 'greater-than', + 'greater-than-equal', + 'grimace', + 'grin', + 'grin-alt', + 'grin-beam', + 'grin-beam-sweat', + 'grin-hearts', + 'grin-squint', + 'grin-squint-tears', + 'grin-stars', + 'grin-tears', + 'grin-tongue', + 'grin-tongue-squint', + 'grin-tongue-wink', + 'grin-wink', + 'grip-horizontal', + 'grip-lines', + 'grip-lines-vertical', + 'grip-vertical', + 'guitar', + 'h-square', + 'hamburger', + 'hammer', + 'hamsa', + 'hand-holding', + 'hand-holding-heart', + 'hand-holding-medical', + 'hand-holding-usd', + 'hand-holding-water', + 'hand-lizard', + 'hand-middle-finger', + 'hand-paper', + 'hand-peace', + 'hand-point-down', + 'hand-point-left', + 'hand-point-right', + 'hand-point-up', + 'hand-pointer', + 'hand-rock', + 'hand-scissors', + 'hand-sparkles', + 'hand-spock', + 'hands', + 'hands-helping', + 'hands-wash', + 'handshake', + 'handshake-alt-slash', + 'handshake-slash', + 'hanukiah', + 'hard-hat', + 'hashtag', + 'hat-cowboy', + 'hat-cowboy-side', + 'hat-wizard', + 'hdd', + 'head-side-cough', + 'head-side-cough-slash', + 'head-side-mask', + 'head-side-virus', + 'heading', + 'headphones', + 'headphones-alt', + 'headset', + 'heart', + 'heart-broken', + 'heartbeat', + 'helicopter', + 'highlighter', + 'hiking', + 'hippo', + 'history', + 'hockey-puck', + 'holly-berry', + 'home', + 'horse', + 'horse-head', + 'hospital', + 'hospital-alt', + 'hospital-symbol', + 'hospital-user', + 'hot-tub', + 'hotdog', + 'hotel', + 'hourglass', + 'hourglass-end', + 'hourglass-half', + 'hourglass-start', + 'house-damage', + 'house-user', + 'hryvnia', + 'i-cursor', + 'ice-cream', + 'icicles', + 'icons', + 'id-badge', + 'id-card', + 'id-card-alt', + 'igloo', + 'image', + 'images', + 'inbox', + 'indent', + 'industry', + 'infinity', + 'info', + 'info-circle', + 'integral', + 'intersection', + 'italic', + 'jedi', + 'joint', + 'journal-whills', + 'kaaba', + 'key', + 'keyboard', + 'khanda', + 'kiss', + 'kiss-beam', + 'kiss-wink-heart', + 'kiwi-bird', + 'lambda', + 'landmark', + 'language', + 'laptop', + 'laptop-code', + 'laptop-house', + 'laptop-medical', + 'laugh', + 'laugh-beam', + 'laugh-squint', + 'laugh-wink', + 'layer-group', + 'leaf', + 'lemon', + 'less-than', + 'less-than-equal', + 'level-down-alt', + 'level-up-alt', + 'life-ring', + 'lightbulb', + 'link', + 'lira-sign', + 'list', + 'list-alt', + 'list-ol', + 'list-ul', + 'location-arrow', + 'lock', + 'lock-open', + 'long-arrow-alt-down', + 'long-arrow-alt-left', + 'long-arrow-alt-right', + 'long-arrow-alt-up', + 'low-vision', + 'luggage-cart', + 'lungs', + 'lungs-virus', + 'magic', + 'magnet', + 'mail-bulk', + 'male', + 'map', + 'map-marked', + 'map-marked-alt', + 'map-marker', + 'map-marker-alt', + 'map-pin', + 'map-signs', + 'marker', + 'mars', + 'mars-double', + 'mars-stroke', + 'mars-stroke-h', + 'mars-stroke-v', + 'mask', + 'medal', + 'medkit', + 'meh', + 'meh-blank', + 'meh-rolling-eyes', + 'memory', + 'menorah', + 'mercury', + 'meteor', + 'microchip', + 'microphone', + 'microphone-alt', + 'microphone-alt-slash', + 'microphone-slash', + 'microscope', + 'minus', + 'minus-circle', + 'minus-square', + 'mitten', + 'mobile', + 'mobile-alt', + 'money-bill', + 'money-bill-alt', + 'money-bill-wave', + 'money-bill-wave-alt', + 'money-check', + 'money-check-alt', + 'monument', + 'moon', + 'mortar-pestle', + 'mosque', + 'motorcycle', + 'mountain', + 'mouse', + 'mouse-pointer', + 'mug-hot', + 'music', + 'network-wired', + 'neuter', + 'newspaper', + 'not-equal', + 'notes-medical', + 'object-group', + 'object-ungroup', + 'oil-can', + 'om', + 'omega', + 'otter', + 'outdent', + 'pager', + 'paint-brush', + 'paint-roller', + 'palette', + 'pallet', + 'paper-plane', + 'paperclip', + 'parachute-box', + 'paragraph', + 'parking', + 'passport', + 'pastafarianism', + 'paste', + 'pause', + 'pause-circle', + 'paw', + 'peace', + 'pen', + 'pen-alt', + 'pen-fancy', + 'pen-nib', + 'pen-square', + 'pencil-alt', + 'pencil-ruler', + 'people-arrows', + 'people-carry', + 'pepper-hot', + 'percent', + 'percentage', + 'person-booth', + 'phone', + 'phone-alt', + 'phone-slash', + 'phone-square', + 'phone-square-alt', + 'phone-volume', + 'photo-video', + 'pi', + 'piggy-bank', + 'pills', + 'pizza-slice', + 'place-of-worship', + 'plane', + 'plane-arrival', + 'plane-departure', + 'plane-slash', + 'play', + 'play-circle', + 'plug', + 'plus', + 'plus-circle', + 'plus-square', + 'podcast', + 'poll', + 'poll-h', + 'poo', + 'poo-storm', + 'poop', + 'portrait', + 'pound-sign', + 'power-off', + 'pray', + 'praying-hands', + 'prescription', + 'prescription-bottle', + 'prescription-bottle-alt', + 'print', + 'procedures', + 'project-diagram', + 'pump-medical', + 'pump-soap', + 'puzzle-piece', + 'qrcode', + 'question', + 'question-circle', + 'quidditch', + 'quote-left', + 'quote-right', + 'quran', + 'radiation', + 'radiation-alt', + 'rainbow', + 'random', + 'receipt', + 'record-vinyl', + 'recycle', + 'redo', + 'redo-alt', + 'registered', + 'remove-format', + 'reply', + 'reply-all', + 'republican', + 'restroom', + 'retweet', + 'ribbon', + 'ring', + 'road', + 'robot', + 'rocket', + 'route', + 'rss', + 'rss-square', + 'ruble-sign', + 'ruler', + 'ruler-combined', + 'ruler-horizontal', + 'ruler-vertical', + 'running', + 'rupee-sign', + 'sad-cry', + 'sad-tear', + 'satellite', + 'satellite-dish', + 'save', + 'school', + 'screwdriver', + 'scroll', + 'sd-card', + 'search', + 'search-dollar', + 'search-location', + 'search-minus', + 'search-plus', + 'seedling', + 'server', + 'shapes', + 'share', + 'share-alt', + 'share-alt-square', + 'share-square', + 'shekel-sign', + 'shield-alt', + 'shield-virus', + 'ship', + 'shipping-fast', + 'shoe-prints', + 'shopping-bag', + 'shopping-basket', + 'shopping-cart', + 'shower', + 'shuttle-van', + 'sigma', + 'sign', + 'sign-in-alt', + 'sign-language', + 'sign-out-alt', + 'signal', + 'signal-alt', + 'signal-alt-slash', + 'signal-slash', + 'signature', + 'sim-card', + 'sink', + 'sitemap', + 'skating', + 'skiing', + 'skiing-nordic', + 'skull', + 'skull-crossbones', + 'slash', + 'sleigh', + 'sliders-h', + 'smile', + 'smile-beam', + 'smile-wink', + 'smog', + 'smoking', + 'smoking-ban', + 'sms', + 'snowboarding', + 'snowflake', + 'snowman', + 'snowplow', + 'soap', + 'socks', + 'solar-panel', + 'sort', + 'sort-alpha-down', + 'sort-alpha-down-alt', + 'sort-alpha-up', + 'sort-alpha-up-alt', + 'sort-amount-down', + 'sort-amount-down-alt', + 'sort-amount-up', + 'sort-amount-up-alt', + 'sort-down', + 'sort-numeric-down', + 'sort-numeric-down-alt', + 'sort-numeric-up', + 'sort-numeric-up-alt', + 'sort-up', + 'spa', + 'space-shuttle', + 'spell-check', + 'spider', + 'spinner', + 'splotch', + 'spray-can', + 'square', + 'square-full', + 'square-root', + 'square-root-alt', + 'stamp', + 'star', + 'star-and-crescent', + 'star-half', + 'star-half-alt', + 'star-of-david', + 'star-of-life', + 'step-backward', + 'step-forward', + 'stethoscope', + 'sticky-note', + 'stop', + 'stop-circle', + 'stopwatch', + 'stopwatch-20', + 'store', + 'store-alt', + 'store-alt-slash', + 'store-slash', + 'stream', + 'street-view', + 'strikethrough', + 'stroopwafel', + 'subscript', + 'subway', + 'suitcase', + 'suitcase-rolling', + 'sun', + 'superscript', + 'surprise', + 'swatchbook', + 'swimmer', + 'swimming-pool', + 'synagogue', + 'sync', + 'sync-alt', + 'syringe', + 'table', + 'table-tennis', + 'tablet', + 'tablet-alt', + 'tablets', + 'tachometer-alt', + 'tag', + 'tags', + 'tally', + 'tape', + 'tasks', + 'taxi', + 'teeth', + 'teeth-open', + 'temperature-high', + 'temperature-low', + 'tenge', + 'terminal', + 'text-height', + 'text-width', + 'th', + 'th-large', + 'th-list', + 'theater-masks', + 'thermometer', + 'thermometer-empty', + 'thermometer-full', + 'thermometer-half', + 'thermometer-quarter', + 'thermometer-three-quarters', + 'theta', + 'thumbs-down', + 'thumbs-up', + 'thumbtack', + 'ticket-alt', + 'tilde', + 'times', + 'times-circle', + 'tint', + 'tint-slash', + 'tired', + 'toggle-off', + 'toggle-on', + 'toilet', + 'toilet-paper', + 'toilet-paper-slash', + 'toolbox', + 'tools', + 'tooth', + 'torah', + 'torii-gate', + 'tractor', + 'trademark', + 'traffic-light', + 'trailer', + 'train', + 'tram', + 'transgender', + 'transgender-alt', + 'trash', + 'trash-alt', + 'trash-restore', + 'trash-restore-alt', + 'tree', + 'trophy', + 'truck', + 'truck-loading', + 'truck-monster', + 'truck-moving', + 'truck-pickup', + 'tshirt', + 'tty', + 'tv', + 'umbrella', + 'umbrella-beach', + 'underline', + 'undo', + 'undo-alt', + 'union', + 'universal-access', + 'university', + 'unlink', + 'unlock', + 'unlock-alt', + 'upload', + 'user', + 'user-alt', + 'user-alt-slash', + 'user-astronaut', + 'user-check', + 'user-circle', + 'user-clock', + 'user-cog', + 'user-edit', + 'user-friends', + 'user-graduate', + 'user-injured', + 'user-lock', + 'user-md', + 'user-minus', + 'user-ninja', + 'user-nurse', + 'user-plus', + 'user-secret', + 'user-shield', + 'user-slash', + 'user-tag', + 'user-tie', + 'user-times', + 'users', + 'users-cog', + 'users-slash', + 'utensil-spoon', + 'utensils', + 'value-absolute', + 'vector-square', + 'venus', + 'venus-double', + 'venus-mars', + 'vest', + 'vest-patches', + 'vial', + 'vials', + 'video', + 'video-slash', + 'vihara', + 'virus', + 'virus-slash', + 'viruses', + 'voicemail', + 'volleyball-ball', + 'volume', + 'volume-down', + 'volume-mute', + 'volume-off', + 'volume-slash', + 'volume-up', + 'vote-yea', + 'vr-cardboard', + 'walking', + 'wallet', + 'warehouse', + 'water', + 'wave-square', + 'weight', + 'weight-hanging', + 'wheelchair', + 'wifi', + 'wifi-slash', + 'wind', + 'window-close', + 'window-maximize', + 'window-minimize', + 'window-restore', + 'wine-bottle', + 'wine-glass', + 'wine-glass-alt', + 'won-sign', + 'wrench', + 'x-ray', + 'yen-sign', + 'yin-yang' + ] +} diff --git a/src/components/ImageViewer/index.ts b/src/components/ImageViewer/index.ts new file mode 100644 index 0000000..35764d6 --- /dev/null +++ b/src/components/ImageViewer/index.ts @@ -0,0 +1,33 @@ +import ImageViewer from './src/ImageViewer.vue' +import { isClient } from '@/utils/is' +import { createVNode, render, VNode } from 'vue' +import { ImageViewerProps } from './src/types' + +let instance: Nullable = null + +export function createImageViewer(options: ImageViewerProps) { + if (!isClient) return + const { + urlList, + initialIndex = 0, + infinite = true, + hideOnClickModal = false, + teleported = false, + zIndex = 2000, + show = true + } = options + + const propsData: Partial = {} + const container = document.createElement('div') + propsData.urlList = urlList + propsData.initialIndex = initialIndex + propsData.infinite = infinite + propsData.hideOnClickModal = hideOnClickModal + propsData.teleported = teleported + propsData.zIndex = zIndex + propsData.show = show + + document.body.appendChild(container) + instance = createVNode(ImageViewer, propsData) + render(instance, container) +} diff --git a/src/components/ImageViewer/src/ImageViewer.vue b/src/components/ImageViewer/src/ImageViewer.vue new file mode 100644 index 0000000..c84d06b --- /dev/null +++ b/src/components/ImageViewer/src/ImageViewer.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/components/ImageViewer/src/types.ts b/src/components/ImageViewer/src/types.ts new file mode 100644 index 0000000..2fff4c0 --- /dev/null +++ b/src/components/ImageViewer/src/types.ts @@ -0,0 +1,9 @@ +export interface ImageViewerProps { + urlList?: string[] + zIndex?: number + initialIndex?: number + infinite?: boolean + hideOnClickModal?: boolean + teleported?: boolean + show?: boolean +} diff --git a/src/components/Infotip/index.ts b/src/components/Infotip/index.ts new file mode 100644 index 0000000..413fa5f --- /dev/null +++ b/src/components/Infotip/index.ts @@ -0,0 +1,3 @@ +import Infotip from './src/Infotip.vue' + +export { Infotip } diff --git a/src/components/Infotip/src/Infotip.vue b/src/components/Infotip/src/Infotip.vue new file mode 100644 index 0000000..0afd692 --- /dev/null +++ b/src/components/Infotip/src/Infotip.vue @@ -0,0 +1,54 @@ + + + diff --git a/src/components/InputPassword/index.ts b/src/components/InputPassword/index.ts new file mode 100644 index 0000000..1dcc38e --- /dev/null +++ b/src/components/InputPassword/index.ts @@ -0,0 +1,3 @@ +import InputPassword from './src/InputPassword.vue' + +export { InputPassword } diff --git a/src/components/InputPassword/src/InputPassword.vue b/src/components/InputPassword/src/InputPassword.vue new file mode 100644 index 0000000..b8c93e7 --- /dev/null +++ b/src/components/InputPassword/src/InputPassword.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/components/InputWithColor/index.vue b/src/components/InputWithColor/index.vue new file mode 100644 index 0000000..1311a55 --- /dev/null +++ b/src/components/InputWithColor/index.vue @@ -0,0 +1,35 @@ + + + + diff --git a/src/components/MagicCubeEditor/index.vue b/src/components/MagicCubeEditor/index.vue new file mode 100644 index 0000000..9b9a43c --- /dev/null +++ b/src/components/MagicCubeEditor/index.vue @@ -0,0 +1,270 @@ + + + diff --git a/src/components/MagicCubeEditor/util.ts b/src/components/MagicCubeEditor/util.ts new file mode 100644 index 0000000..e7c6465 --- /dev/null +++ b/src/components/MagicCubeEditor/util.ts @@ -0,0 +1,72 @@ +// 坐标点 +export interface Point { + x: number + y: number +} + +// 矩形 +export interface Rect { + // 左上角 X 轴坐标 + left: number + // 左上角 Y 轴坐标 + top: number + // 右下角 X 轴坐标 + right: number + // 右下角 Y 轴坐标 + bottom: number + // 矩形宽度 + width: number + // 矩形高度 + height: number +} + +/** + * 判断两个矩形是否重叠 + * @param a 矩形 A + * @param b 矩形 B + */ +export const isOverlap = (a: Rect, b: Rect): boolean => { + return ( + a.left < b.left + b.width && + a.left + a.width > b.left && + a.top < b.top + b.height && + a.height + a.top > b.top + ) +} +/** + * 检查坐标点是否在矩形内 + * @param hotArea 矩形 + * @param point 坐标 + */ +export const isContains = (hotArea: Rect, point: Point): boolean => { + return ( + point.x >= hotArea.left && + point.x < hotArea.right && + point.y >= hotArea.top && + point.y < hotArea.bottom + ) +} + +/** + * 在两个坐标点中间,创建一个矩形 + * + * 存在以下情况: + * 1. 两个坐标点是同一个位置,只占一个位置的正方形,宽高都为 1 + * 2. X 轴坐标相同,只占一行的矩形,高度为 1 + * 3. Y 轴坐标相同,只占一列的矩形,宽度为 1 + * 4. 多行多列的矩形 + * + * @param a 坐标点一 + * @param b 坐标点二 + */ +export const createRect = (a: Point, b: Point): Rect => { + // 计算矩形的范围 + const [left, left2] = [a.x, b.x].sort() + const [top, top2] = [a.y, b.y].sort() + const right = left2 + 1 + const bottom = top2 + 1 + const height = bottom - top + const width = right - left + + return { left, right, top, bottom, height, width } +} diff --git a/src/components/MarkdownView/index.vue b/src/components/MarkdownView/index.vue new file mode 100644 index 0000000..74764d5 --- /dev/null +++ b/src/components/MarkdownView/index.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/src/components/OperateLogV2/index.ts b/src/components/OperateLogV2/index.ts new file mode 100644 index 0000000..f69c222 --- /dev/null +++ b/src/components/OperateLogV2/index.ts @@ -0,0 +1,3 @@ +import OperateLogV2 from './src/OperateLogV2.vue' + +export { OperateLogV2 } diff --git a/src/components/OperateLogV2/src/OperateLogV2.vue b/src/components/OperateLogV2/src/OperateLogV2.vue new file mode 100644 index 0000000..6acc1cc --- /dev/null +++ b/src/components/OperateLogV2/src/OperateLogV2.vue @@ -0,0 +1,105 @@ + + + + + + diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue new file mode 100644 index 0000000..6bb00b3 --- /dev/null +++ b/src/components/Pagination/index.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/components/Qrcode/index.ts b/src/components/Qrcode/index.ts new file mode 100644 index 0000000..ce46161 --- /dev/null +++ b/src/components/Qrcode/index.ts @@ -0,0 +1,3 @@ +import Qrcode from './src/Qrcode.vue' + +export { Qrcode } diff --git a/src/components/Qrcode/src/Qrcode.vue b/src/components/Qrcode/src/Qrcode.vue new file mode 100644 index 0000000..f0ce7b7 --- /dev/null +++ b/src/components/Qrcode/src/Qrcode.vue @@ -0,0 +1,253 @@ + + + + + diff --git a/src/components/RouterSearch/index.vue b/src/components/RouterSearch/index.vue new file mode 100644 index 0000000..42a4174 --- /dev/null +++ b/src/components/RouterSearch/index.vue @@ -0,0 +1,119 @@ + + + diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts new file mode 100644 index 0000000..fcc6f16 --- /dev/null +++ b/src/components/Search/index.ts @@ -0,0 +1,3 @@ +import Search from './src/Search.vue' + +export { Search } diff --git a/src/components/Search/src/Search.vue b/src/components/Search/src/Search.vue new file mode 100644 index 0000000..3218a63 --- /dev/null +++ b/src/components/Search/src/Search.vue @@ -0,0 +1,157 @@ + + + diff --git a/src/components/ShortcutDateRangePicker/index.vue b/src/components/ShortcutDateRangePicker/index.vue new file mode 100644 index 0000000..78c5130 --- /dev/null +++ b/src/components/ShortcutDateRangePicker/index.vue @@ -0,0 +1,84 @@ + + diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue new file mode 100644 index 0000000..4dfd51a --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -0,0 +1,231 @@ + + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue new file mode 100644 index 0000000..419501a --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue @@ -0,0 +1,125 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue new file mode 100644 index 0000000..22e6073 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -0,0 +1,306 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue new file mode 100644 index 0000000..ccd1f10 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue new file mode 100644 index 0000000..abf73b4 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue @@ -0,0 +1,48 @@ + + + +p diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts new file mode 100644 index 0000000..10d8a21 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -0,0 +1,606 @@ +// @ts-ignore +import { DictDataVO } from '@/api/system/dict/types' +import { TaskStatusEnum } from '@/api/bpm/task' +/** + * 节点类型 + */ +export enum NodeType { + /** + * 结束节点 + */ + END_EVENT_NODE = 1, + /** + * 发起人节点 + */ + START_USER_NODE = 10, + /** + * 审批人节点 + */ + USER_TASK_NODE = 11, + + /** + * 抄送人节点 + */ + COPY_TASK_NODE = 12, + + /** + * 延迟器节点 + */ + DELAY_TIMER_NODE = 14, + + /** + * 条件节点 + */ + CONDITION_NODE = 50, + /** + * 条件分支节点 (对应排他网关) + */ + CONDITION_BRANCH_NODE = 51, + /** + * 并行分支节点 (对应并行网关) + */ + PARALLEL_BRANCH_NODE = 52, + + /** + * 包容分支节点 (对应包容网关) + */ + INCLUSIVE_BRANCH_NODE = 53 +} + +export enum NodeId { + /** + * 发起人节点 Id + */ + START_USER_NODE_ID = 'StartUserNode', + + /** + * 发起人节点 Id + */ + END_EVENT_NODE_ID = 'EndEvent' +} + +/** + * 节点结构定义 + */ +export interface SimpleFlowNode { + id: string + type: NodeType + name: string + showText?: string + // 孩子节点 + childNode?: SimpleFlowNode + // 条件节点 + conditionNodes?: SimpleFlowNode[] + // 审批类型 + approveType?: ApproveType + // 候选人策略 + candidateStrategy?: number + // 候选人参数 + candidateParam?: string + // 多人审批方式 + approveMethod?: ApproveMethodType + //通过比例 + approveRatio?: number + // 审批按钮设置 + buttonsSetting?: any[] + // 表单权限 + fieldsPermission?: Array> + // 审批任务超时处理 + timeoutHandler?: TimeoutHandler + // 审批任务拒绝处理 + rejectHandler?: RejectHandler + // 审批人为空的处理 + assignEmptyHandler?: AssignEmptyHandler + // 审批节点的审批人与发起人相同时,对应的处理类型 + assignStartUserHandlerType?: number + // 条件类型 + conditionType?: ConditionType + // 条件表达式 + conditionExpression?: string + // 条件组 + conditionGroups?: ConditionGroup + // 是否默认的条件 + defaultFlow?: boolean + // 活动的状态,用于前端节点状态展示 + activityStatus?: TaskStatusEnum + // 延迟设置 + delaySetting?: DelaySetting +} +// 候选人策略枚举 ( 用于审批节点。抄送节点 ) +export enum CandidateStrategy { + /** + * 指定角色 + */ + ROLE = 10, + /** + * 部门成员 + */ + DEPT_MEMBER = 20, + /** + * 部门的负责人 + */ + DEPT_LEADER = 21, + /** + * 连续多级部门的负责人 + */ + MULTI_LEVEL_DEPT_LEADER = 23, + /** + * 指定岗位 + */ + POST = 22, + /** + * 指定用户 + */ + USER = 30, + /** + * 发起人自选 + */ + START_USER_SELECT = 35, + /** + * 发起人自己 + */ + START_USER = 36, + /** + * 发起人部门负责人 + */ + START_USER_DEPT_LEADER = 37, + /** + * 发起人连续多级部门的负责人 + */ + START_USER_MULTI_LEVEL_DEPT_LEADER = 38, + /** + * 指定用户组 + */ + USER_GROUP = 40, + /** + * 表单内用户字段 + */ + FORM_USER = 50, + /** + * 表单内部门负责人 + */ + FORM_DEPT_LEADER = 51, + /** + * 流程表达式 + */ + EXPRESSION = 60 +} + +// 多人审批方式类型枚举 ( 用于审批节点 ) +export enum ApproveMethodType { + /** + * 随机挑选一人审批 + */ + RANDOM_SELECT_ONE_APPROVE = 1, + + /** + * 多人会签(按通过比例) + */ + APPROVE_BY_RATIO = 2, + + /** + * 多人或签(通过只需一人,拒绝只需一人) + */ + ANY_APPROVE = 3, + /** + * 多人依次审批 + */ + SEQUENTIAL_APPROVE = 4 +} + +/** + * 审批拒绝结构定义 + */ +export type RejectHandler = { + // 审批拒绝类型 + type: RejectHandlerType + // 退回节点 Id + returnNodeId?: string +} + +/** + * 审批超时结构定义 + */ +export type TimeoutHandler = { + // 是否开启超时处理 + enable: boolean + // 超时执行的动作 + type?: number + // 超时时间设置 + timeDuration?: string + // 执行动作是自动提醒, 最大提醒次数 + maxRemindCount?: number +} + +/** + * 审批人为空的结构定义 + */ +export type AssignEmptyHandler = { + // 审批人为空的处理类型 + type: AssignEmptyHandlerType + // 指定用户的编号数组 + userIds?: number[] +} + +// 审批拒绝类型枚举 +export enum RejectHandlerType { + /** + * 结束流程 + */ + FINISH_PROCESS = 1, + /** + * 驳回到指定节点 + */ + RETURN_USER_TASK = 2 +} +// 用户任务超时处理类型枚举 +export enum TimeoutHandlerType { + /** + * 自动提醒 + */ + REMINDER = 1, + /** + * 自动同意 + */ + APPROVE = 2, + /** + * 自动拒绝 + */ + REJECT = 3 +} +// 用户任务的审批人为空时,处理类型枚举 +export enum AssignEmptyHandlerType { + /** + * 自动通过 + */ + APPROVE = 1, + /** + * 自动拒绝 + */ + REJECT = 2, + /** + * 指定人员审批 + */ + ASSIGN_USER, + /** + * 转交给流程管理员 + */ + ASSIGN_ADMIN = 4 +} +// 用户任务的审批人与发起人相同时,处理类型枚举 +export enum AssignStartUserHandlerType { + /** + * 由发起人对自己审批 + */ + START_USER_AUDIT = 1, + /** + * 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过 + */ + SKIP = 2, + /** + * 转交给部门负责人审批 + */ + ASSIGN_DEPT_LEADER = 3 +} + +// 用户任务的审批类型。 【参考飞书】 +export enum ApproveType { + /** + * 人工审批 + */ + USER = 1, + /** + * 自动通过 + */ + AUTO_APPROVE = 2, + /** + * 自动拒绝 + */ + AUTO_REJECT = 3 +} + +// 时间单位枚举 +export enum TimeUnitType { + /** + * 分钟 + */ + MINUTE = 1, + /** + * 小时 + */ + HOUR = 2, + /** + * 天 + */ + DAY = 3 +} + +// 条件配置类型 ( 用于条件节点配置 ) +export enum ConditionType { + /** + * 条件表达式 + */ + EXPRESSION = 1, + + /** + * 条件规则 + */ + RULE = 2 +} +/** + * 表单权限的枚举 + */ +export enum FieldPermissionType { + /** + * 只读 + */ + READ = '1', + /** + * 编辑 + */ + WRITE = '2', + /** + * 隐藏 + */ + NONE = '3' +} +/** + * 操作按钮权限结构定义 + */ +export type ButtonSetting = { + id: OperationButtonType + displayName: string + enable: boolean +} + +// 操作按钮类型枚举 (用于审批节点) +export enum OperationButtonType { + /** + * 通过 + */ + APPROVE = 1, + /** + * 拒绝 + */ + REJECT = 2, + /** + * 转办 + */ + TRANSFER = 3, + /** + * 委派 + */ + DELEGATE = 4, + /** + * 加签 + */ + ADD_SIGN = 5, + /** + * 退回 + */ + RETURN = 6, + /** + * 抄送 + */ + COPY = 7 +} + +/** + * 条件规则结构定义 + */ +export type ConditionRule = { + type: number + opName: string + opCode: string + leftSide: string + rightSide: string +} + +/** + * 条件组结构定义 + */ +export type ConditionGroup = { + // 条件组的逻辑关系是否为且 + and: boolean + // 条件数组 + conditions: Condition[] +} + +/** + * 条件结构定义 + */ +export type Condition = { + // 条件规则的逻辑关系是否为且 + and: boolean + rules: ConditionRule[] +} + +export const NODE_DEFAULT_TEXT = new Map() +NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置审批人') +NODE_DEFAULT_TEXT.set(NodeType.COPY_TASK_NODE, '请配置抄送人') +NODE_DEFAULT_TEXT.set(NodeType.CONDITION_NODE, '请设置条件') +NODE_DEFAULT_TEXT.set(NodeType.START_USER_NODE, '请设置发起人') +NODE_DEFAULT_TEXT.set(NodeType.DELAY_TIMER_NODE, '请设置延迟器') + +export const NODE_DEFAULT_NAME = new Map() +NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人') +NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人') +NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') +NODE_DEFAULT_NAME.set(NodeType.START_USER_NODE, '发起人') +NODE_DEFAULT_NAME.set(NodeType.DELAY_TIMER_NODE, '延迟器') + +// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序 +export const CANDIDATE_STRATEGY: DictDataVO[] = [ + { label: '指定成员', value: CandidateStrategy.USER }, + { label: '指定角色', value: CandidateStrategy.ROLE }, + { label: '部门成员', value: CandidateStrategy.DEPT_MEMBER }, + { label: '部门负责人', value: CandidateStrategy.DEPT_LEADER }, + { label: '连续多级部门负责人', value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER }, + { label: '发起人自选', value: CandidateStrategy.START_USER_SELECT }, + { label: '发起人本人', value: CandidateStrategy.START_USER }, + { label: '发起人部门负责人', value: CandidateStrategy.START_USER_DEPT_LEADER }, + { label: '发起人连续部门负责人', value: CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER }, + { label: '用户组', value: CandidateStrategy.USER_GROUP }, + { label: '表单内用户字段', value: CandidateStrategy.FORM_USER }, + { label: '表单内部门负责人', value: CandidateStrategy.FORM_DEPT_LEADER }, + { label: '流程表达式', value: CandidateStrategy.EXPRESSION } +] +// 审批节点 的审批类型 +export const APPROVE_TYPE: DictDataVO[] = [ + { label: '人工审批', value: ApproveType.USER }, + { label: '自动通过', value: ApproveType.AUTO_APPROVE }, + { label: '自动拒绝', value: ApproveType.AUTO_REJECT } +] + +export const APPROVE_METHODS: DictDataVO[] = [ + { label: '按顺序依次审批', value: ApproveMethodType.SEQUENTIAL_APPROVE }, + { label: '会签(可同时审批,至少 % 人必须审批通过)', value: ApproveMethodType.APPROVE_BY_RATIO }, + { label: '或签(可同时审批,有一人通过即可)', value: ApproveMethodType.ANY_APPROVE }, + { label: '随机挑选一人审批', value: ApproveMethodType.RANDOM_SELECT_ONE_APPROVE } +] + +export const CONDITION_CONFIG_TYPES: DictDataVO[] = [ + { label: '条件表达式', value: ConditionType.EXPRESSION }, + { label: '条件规则', value: ConditionType.RULE } +] + +// 时间单位类型 +export const TIME_UNIT_TYPES: DictDataVO[] = [ + { label: '分钟', value: TimeUnitType.MINUTE }, + { label: '小时', value: TimeUnitType.HOUR }, + { label: '天', value: TimeUnitType.DAY } +] +// 超时处理执行动作类型 +export const TIMEOUT_HANDLER_TYPES: DictDataVO[] = [ + { label: '自动提醒', value: 1 }, + { label: '自动同意', value: 2 }, + { label: '自动拒绝', value: 3 } +] +export const REJECT_HANDLER_TYPES: DictDataVO[] = [ + { label: '终止流程', value: RejectHandlerType.FINISH_PROCESS }, + { label: '驳回到指定节点', value: RejectHandlerType.RETURN_USER_TASK } + // { label: '结束任务', value: RejectHandlerType.FINISH_TASK } +] +export const ASSIGN_EMPTY_HANDLER_TYPES: DictDataVO[] = [ + { label: '自动通过', value: 1 }, + { label: '自动拒绝', value: 2 }, + { label: '指定成员审批', value: 3 }, + { label: '转交给流程管理员', value: 4 } +] +export const ASSIGN_START_USER_HANDLER_TYPES: DictDataVO[] = [ + { label: '由发起人对自己审批', value: 1 }, + { label: '自动跳过', value: 2 }, + { label: '转交给部门负责人审批', value: 3 } +] + +// 比较运算符 +export const COMPARISON_OPERATORS: DictDataVO = [ + { + value: '==', + label: '等于' + }, + { + value: '!=', + label: '不等于' + }, + { + value: '>', + label: '大于' + }, + { + value: '>=', + label: '大于等于' + }, + { + value: '<', + label: '小于' + }, + { + value: '<=', + label: '小于等于' + } +] +// 审批操作按钮名称 +export const OPERATION_BUTTON_NAME = new Map() +OPERATION_BUTTON_NAME.set(OperationButtonType.APPROVE, '通过') +OPERATION_BUTTON_NAME.set(OperationButtonType.REJECT, '拒绝') +OPERATION_BUTTON_NAME.set(OperationButtonType.TRANSFER, '转办') +OPERATION_BUTTON_NAME.set(OperationButtonType.DELEGATE, '委派') +OPERATION_BUTTON_NAME.set(OperationButtonType.ADD_SIGN, '加签') +OPERATION_BUTTON_NAME.set(OperationButtonType.RETURN, '退回') +OPERATION_BUTTON_NAME.set(OperationButtonType.COPY, '抄送') + +// 默认的按钮权限设置 +export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [ + { id: OperationButtonType.APPROVE, displayName: '通过', enable: true }, + { id: OperationButtonType.REJECT, displayName: '拒绝', enable: true }, + { id: OperationButtonType.TRANSFER, displayName: '转办', enable: true }, + { id: OperationButtonType.DELEGATE, displayName: '委派', enable: true }, + { id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: true }, + { id: OperationButtonType.RETURN, displayName: '退回', enable: true } +] + +// 发起人的按钮权限。暂时定死,不可以编辑 +export const START_USER_BUTTON_SETTING: ButtonSetting[] = [ + { id: OperationButtonType.APPROVE, displayName: '提交', enable: true }, + { id: OperationButtonType.REJECT, displayName: '拒绝', enable: false }, + { id: OperationButtonType.TRANSFER, displayName: '转办', enable: false }, + { id: OperationButtonType.DELEGATE, displayName: '委派', enable: false }, + { id: OperationButtonType.ADD_SIGN, displayName: '加签', enable: false }, + { id: OperationButtonType.RETURN, displayName: '退回', enable: false } +] + +export const MULTI_LEVEL_DEPT: DictDataVO = [ + { label: '第 1 级部门', value: 1 }, + { label: '第 2 级部门', value: 2 }, + { label: '第 3 级部门', value: 3 }, + { label: '第 4 级部门', value: 4 }, + { label: '第 5 级部门', value: 5 }, + { label: '第 6 级部门', value: 6 }, + { label: '第 7 级部门', value: 7 }, + { label: '第 8 级部门', value: 8 }, + { label: '第 9 级部门', value: 9 }, + { label: '第 10 级部门', value: 10 }, + { label: '第 11 级部门', value: 11 }, + { label: '第 12 级部门', value: 12 }, + { label: '第 13 级部门', value: 13 }, + { label: '第 14 级部门', value: 14 }, + { label: '第 15 级部门', value: 15 } +] + +/** + * 流程实例的变量枚举 + */ +export enum ProcessVariableEnum { + /** + * 发起用户 ID + */ + START_USER_ID = 'PROCESS_START_USER_ID' +} + +/** + * 延迟设置 + */ +export type DelaySetting = { + // 延迟类型 + delayType: number + // 延迟时间表达式 + delayTime: string +} +/** + * 延迟类型 + */ +export enum DelayTypeEnum { + /** + * 固定时长 + */ + FIXED_TIME_DURATION = 1, + /** + * 固定日期时间 + */ + FIXED_DATE_TIME = 2 +} +export const DELAY_TYPE = [ + { label: '固定时长', value: DelayTypeEnum.FIXED_TIME_DURATION }, + { label: '固定日期', value: DelayTypeEnum.FIXED_DATE_TIME } +] diff --git a/src/components/SimpleProcessDesignerV2/src/index.ts b/src/components/SimpleProcessDesignerV2/src/index.ts new file mode 100644 index 0000000..88de07f --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/index.ts @@ -0,0 +1,5 @@ +import SimpleProcessDesigner from './SimpleProcessDesigner.vue' +import SimpleProcessViewer from './SimpleProcessViewer.vue' +import '../theme/simple-process-designer.scss' + +export { SimpleProcessDesigner, SimpleProcessViewer} diff --git a/src/components/SimpleProcessDesignerV2/src/node.ts b/src/components/SimpleProcessDesignerV2/src/node.ts new file mode 100644 index 0000000..b3cfc97 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/node.ts @@ -0,0 +1,511 @@ +import { cloneDeep } from 'lodash-es' +import { TaskStatusEnum } from '@/api/bpm/task' +import * as RoleApi from '@/api/system/role' +import * as DeptApi from '@/api/system/dept' +import * as PostApi from '@/api/system/post' +import * as UserApi from '@/api/system/user' +import * as UserGroupApi from '@/api/bpm/userGroup' +import { + SimpleFlowNode, + CandidateStrategy, + NodeType, + ApproveMethodType, + RejectHandlerType, + NODE_DEFAULT_NAME, + AssignStartUserHandlerType, + AssignEmptyHandlerType, + FieldPermissionType +} from './consts' +import { parseFormFields } from '@/components/FormCreate/src/utils/index' +export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref { + const node = ref(props.flowNode) + watch( + () => props.flowNode, + (newValue) => { + node.value = newValue + } + ) + return node +} + +// 解析 formCreate 所有表单字段, 并返回 +const parseFormCreateFields = (formFields?: string[]) => { + const result: Array> = [] + if (formFields) { + formFields.forEach((fieldStr: string) => { + parseFormFields(JSON.parse(fieldStr), result) + }) + } + return result +} + +/** + * @description 表单数据权限配置,用于发起人节点 、审批节点、抄送节点 + */ +export function useFormFieldsPermission(defaultPermission: FieldPermissionType) { + // 字段权限配置. 需要有 field, title, permissioin 属性 + const fieldsPermissionConfig = ref>>([]) + + const formType = inject>('formType') // 表单类型 + + const formFields = inject>('formFields') // 流程表单字段 + + const getNodeConfigFormFields = (nodeFormFields?: Array>) => { + nodeFormFields = toRaw(nodeFormFields) + if (!nodeFormFields || nodeFormFields.length === 0) { + fieldsPermissionConfig.value = getDefaultFieldsPermission(unref(formFields)) + } else { + fieldsPermissionConfig.value = mergeFieldsPermission(nodeFormFields, unref(formFields)) + } + } + // 合并已经设置的表单字段权限,当前流程表单字段 (可能新增,或删除了字段) + const mergeFieldsPermission = ( + formFieldsPermisson: Array>, + formFields?: string[] + ) => { + let mergedFieldsPermission: Array> = [] + if (formFields) { + mergedFieldsPermission = parseFormCreateFields(formFields).map((item) => { + const found = formFieldsPermisson.find( + (fieldPermission) => fieldPermission.field == item.field + ) + return { + field: item.field, + title: item.title, + permission: found ? found.permission : defaultPermission + } + }) + } + return mergedFieldsPermission + } + + // 默认的表单权限: 获取表单的所有字段,设置字段默认权限为只读 + const getDefaultFieldsPermission = (formFields?: string[]) => { + let defaultFieldsPermission: Array> = [] + if (formFields) { + defaultFieldsPermission = parseFormCreateFields(formFields).map((item) => { + return { + field: item.field, + title: item.title, + permission: defaultPermission + } + }) + } + return defaultFieldsPermission + } + + // 获取表单的所有字段,作为下拉框选项 + const formFieldOptions = parseFormCreateFields(unref(formFields)) + + return { + formType, + fieldsPermissionConfig, + formFieldOptions, + getNodeConfigFormFields + } +} +/** + * @description 获取表单的字段 + */ +export function useFormFields() { + const formFields = inject>('formFields') // 流程表单字段 + return parseFormCreateFields(unref(formFields)) +} + +export type UserTaskFormType = { + //candidateParamArray: any[] + candidateStrategy: CandidateStrategy + approveMethod: ApproveMethodType + roleIds?: number[] // 角色 + deptIds?: number[] // 部门 + deptLevel?: number // 部门层级 + userIds?: number[] // 用户 + userGroups?: number[] // 用户组 + postIds?: number[] // 岗位 + expression?: string // 流程表达式 + formUser?: string // 表单内用户字段 + formDept?: string // 表单内部门字段 + approveRatio?: number + rejectHandlerType?: RejectHandlerType + returnNodeId?: string + timeoutHandlerEnable?: boolean + timeoutHandlerType?: number + assignEmptyHandlerType?: AssignEmptyHandlerType + assignEmptyHandlerUserIds?: number[] + assignStartUserHandlerType?: AssignStartUserHandlerType + timeDuration?: number + maxRemindCount?: number + buttonsSetting: any[] +} + +export type CopyTaskFormType = { + // candidateParamArray: any[] + candidateStrategy: CandidateStrategy + roleIds?: number[] // 角色 + deptIds?: number[] // 部门 + deptLevel?: number // 部门层级 + userIds?: number[] // 用户 + userGroups?: number[] // 用户组 + postIds?: number[] // 岗位 + formUser?: string // 表单内用户字段 + formDept?: string // 表单内部门字段 + expression?: string // 流程表达式 +} + +/** + * @description 节点表单数据。 用于审批节点、抄送节点 + */ +export function useNodeForm(nodeType: NodeType) { + const roleOptions = inject>('roleList') // 角色列表 + const postOptions = inject>('postList') // 岗位列表 + const userOptions = inject>('userList') // 用户列表 + const deptOptions = inject>('deptList') // 部门列表 + const userGroupOptions = inject>('userGroupList') // 用户组列表 + const deptTreeOptions = inject('deptTree') // 部门树 + const formFields = inject>('formFields') // 流程表单字段 + const configForm = ref() + if (nodeType === NodeType.USER_TASK_NODE) { + configForm.value = { + candidateStrategy: CandidateStrategy.USER, + approveMethod: ApproveMethodType.SEQUENTIAL_APPROVE, + approveRatio: 100, + rejectHandlerType: RejectHandlerType.FINISH_PROCESS, + assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT, + returnNodeId: '', + timeoutHandlerEnable: false, + timeoutHandlerType: 1, + timeDuration: 6, // 默认 6小时 + maxRemindCount: 1, // 默认 提醒 1次 + buttonsSetting: [] + } + } else { + configForm.value = { + candidateStrategy: CandidateStrategy.USER + } + } + + const getShowText = (): string => { + let showText = '' + // 指定成员 + if (configForm.value?.candidateStrategy === CandidateStrategy.USER) { + if (configForm.value?.userIds!.length > 0) { + const candidateNames: string[] = [] + userOptions?.value.forEach((item) => { + if (configForm.value?.userIds!.includes(item.id)) { + candidateNames.push(item.nickname) + } + }) + showText = `指定成员:${candidateNames.join(',')}` + } + } + // 指定角色 + if (configForm.value?.candidateStrategy === CandidateStrategy.ROLE) { + if (configForm.value.roleIds!.length > 0) { + const candidateNames: string[] = [] + roleOptions?.value.forEach((item) => { + if (configForm.value?.roleIds!.includes(item.id)) { + candidateNames.push(item.name) + } + }) + showText = `指定角色:${candidateNames.join(',')}` + } + } + // 指定部门 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER || + configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER || + configForm.value?.candidateStrategy === CandidateStrategy.MULTI_LEVEL_DEPT_LEADER + ) { + if (configForm.value?.deptIds!.length > 0) { + const candidateNames: string[] = [] + deptOptions?.value.forEach((item) => { + if (configForm.value?.deptIds!.includes(item.id!)) { + candidateNames.push(item.name) + } + }) + if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) { + showText = `部门成员:${candidateNames.join(',')}` + } else if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER) { + showText = `部门的负责人:${candidateNames.join(',')}` + } else { + showText = `多级部门的负责人:${candidateNames.join(',')}` + } + } + } + + // 指定岗位 + if (configForm.value?.candidateStrategy === CandidateStrategy.POST) { + if (configForm.value.postIds!.length > 0) { + const candidateNames: string[] = [] + postOptions?.value.forEach((item) => { + if (configForm.value?.postIds!.includes(item.id!)) { + candidateNames.push(item.name) + } + }) + showText = `指定岗位: ${candidateNames.join(',')}` + } + } + // 指定用户组 + if (configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP) { + if (configForm.value?.userGroups!.length > 0) { + const candidateNames: string[] = [] + userGroupOptions?.value.forEach((item) => { + if (configForm.value?.userGroups!.includes(item.id)) { + candidateNames.push(item.name) + } + }) + showText = `指定用户组: ${candidateNames.join(',')}` + } + } + + // 表单内用户字段 + if (configForm.value?.candidateStrategy === CandidateStrategy.FORM_USER) { + const formFieldOptions = parseFormCreateFields(unref(formFields)) + const item = formFieldOptions.find((item) => item.field === configForm.value?.formUser) + showText = `表单用户:${item?.title}` + } + + // 表单内部门负责人 + if (configForm.value?.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER) { + showText = `表单内部门负责人` + } + + // 发起人自选 + if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_SELECT) { + showText = `发起人自选` + } + // 发起人自己 + if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) { + showText = `发起人自己` + } + // 发起人的部门负责人 + if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_DEPT_LEADER) { + showText = `发起人的部门负责人` + } + // 发起人的部门负责人 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER + ) { + showText = `发起人连续部门负责人` + } + // 流程表达式 + if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) { + showText = `流程表达式:${configForm.value.expression}` + } + return showText + } + + /** + * 处理候选人参数的赋值 + */ + const handleCandidateParam = () => { + let candidateParam: undefined | string = undefined + if (!configForm.value) { + return candidateParam + } + switch (configForm.value.candidateStrategy) { + case CandidateStrategy.USER: + candidateParam = configForm.value.userIds!.join(',') + break + case CandidateStrategy.ROLE: + candidateParam = configForm.value.roleIds!.join(',') + break + case CandidateStrategy.POST: + candidateParam = configForm.value.postIds!.join(',') + break + case CandidateStrategy.USER_GROUP: + candidateParam = configForm.value.userGroups!.join(',') + break + case CandidateStrategy.FORM_USER: + candidateParam = configForm.value.formUser! + break + case CandidateStrategy.EXPRESSION: + candidateParam = configForm.value.expression! + break + case CandidateStrategy.DEPT_MEMBER: + case CandidateStrategy.DEPT_LEADER: + candidateParam = configForm.value.deptIds!.join(',') + break + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: + candidateParam = configForm.value.deptLevel + '' + break + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级 + const deptIds = configForm.value.deptIds!.join(',') + candidateParam = deptIds.concat('|' + configForm.value.deptLevel + '') + break + } + // 表单内部门的负责人 + case CandidateStrategy.FORM_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为表单内部门字段。 右边为部门层级 + const deptFieldOnForm = configForm.value.formDept! + candidateParam = deptFieldOnForm.concat('|' + configForm.value.deptLevel + '') + break + } + default: + break + } + return candidateParam + } + /** + * 解析候选人参数 + */ + const parseCandidateParam = ( + candidateStrategy: CandidateStrategy, + candidateParam: string | undefined + ) => { + if (!configForm.value || !candidateParam) { + return + } + switch (candidateStrategy) { + case CandidateStrategy.USER: { + configForm.value.userIds = candidateParam.split(',').map((item) => +item) + break + } + case CandidateStrategy.ROLE: + configForm.value.roleIds = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.POST: + configForm.value.postIds = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.USER_GROUP: + configForm.value.userGroups = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.FORM_USER: + configForm.value.formUser = candidateParam + break + case CandidateStrategy.EXPRESSION: + configForm.value.expression = candidateParam + break + case CandidateStrategy.DEPT_MEMBER: + case CandidateStrategy.DEPT_LEADER: + configForm.value.deptIds = candidateParam.split(',').map((item) => +item) + break + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: + configForm.value.deptLevel = +candidateParam + break + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级 + const paramArray = candidateParam.split('|') + configForm.value.deptIds = paramArray[0].split(',').map((item) => +item) + configForm.value.deptLevel = +paramArray[1] + break + } + // 表单内的部门负责人 + case CandidateStrategy.FORM_DEPT_LEADER: { + // 候选人参数格式: | 分隔 。左边为表单内的部门字段。 右边为部门层级 + const paramArray = candidateParam.split('|') + configForm.value.formDept = paramArray[0] + configForm.value.deptLevel = +paramArray[1] + break + } + default: + break + } + } + return { + configForm, + roleOptions, + postOptions, + userOptions, + userGroupOptions, + deptTreeOptions, + handleCandidateParam, + parseCandidateParam, + getShowText + } +} + +/** + * @description 抽屉配置 + */ +export function useDrawer() { + // 抽屉配置是否可见 + const settingVisible = ref(false) + // 关闭配置抽屉 + const closeDrawer = () => { + settingVisible.value = false + } + // 打开配置抽屉 + const openDrawer = () => { + settingVisible.value = true + } + return { + settingVisible, + closeDrawer, + openDrawer + } +} + +/** + * @description 节点名称配置 + */ +export function useNodeName(nodeType: NodeType) { + // 节点名称 + const nodeName = ref() + // 节点名称输入框 + const showInput = ref(false) + // 点击节点名称编辑图标 + const clickIcon = () => { + showInput.value = true + } + // 节点名称输入框失去焦点 + const blurEvent = () => { + showInput.value = false + nodeName.value = nodeName.value || (NODE_DEFAULT_NAME.get(nodeType) as string) + } + return { + nodeName, + showInput, + clickIcon, + blurEvent + } +} + +export function useNodeName2(node: Ref, nodeType: NodeType) { + // 显示节点名称输入框 + const showInput = ref(false) + // 节点名称输入框失去焦点 + const blurEvent = () => { + showInput.value = false + node.value.name = node.value.name || (NODE_DEFAULT_NAME.get(nodeType) as string) + } + // 点击节点标题进行输入 + const clickTitle = () => { + showInput.value = true + } + return { + showInput, + clickTitle, + blurEvent + } +} + +/** + * @description 根据节点任务状态,获取节点任务状态样式 + */ +export function useTaskStatusClass(taskStatus: TaskStatusEnum | undefined): string { + if (!taskStatus) { + return '' + } + if (taskStatus === TaskStatusEnum.APPROVE) { + return 'status-pass' + } + if (taskStatus === TaskStatusEnum.RUNNING) { + return 'status-running' + } + if (taskStatus === TaskStatusEnum.REJECT) { + return 'status-reject' + } + if (taskStatus === TaskStatusEnum.CANCEL) { + return 'status-cancel' + } + + return '' +} diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue new file mode 100644 index 0000000..ae93172 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue @@ -0,0 +1,429 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue new file mode 100644 index 0000000..f83f185 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -0,0 +1,374 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue new file mode 100644 index 0000000..27a351b --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue @@ -0,0 +1,189 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue new file mode 100644 index 0000000..26c8e13 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue @@ -0,0 +1,163 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue new file mode 100644 index 0000000..fb5e780 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -0,0 +1,913 @@ + + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue new file mode 100644 index 0000000..8b97ee5 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue @@ -0,0 +1,97 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue new file mode 100644 index 0000000..94f9c41 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue @@ -0,0 +1,98 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue new file mode 100644 index 0000000..63aa24e --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue @@ -0,0 +1,102 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue new file mode 100644 index 0000000..adeae77 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue @@ -0,0 +1,229 @@ + + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue new file mode 100644 index 0000000..f1445d8 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue new file mode 100644 index 0000000..7aa6793 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue @@ -0,0 +1,184 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue new file mode 100644 index 0000000..89a57d0 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue new file mode 100644 index 0000000..761a674 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue @@ -0,0 +1,174 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/utils.ts b/src/components/SimpleProcessDesignerV2/src/utils.ts new file mode 100644 index 0000000..8e715b4 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/utils.ts @@ -0,0 +1,41 @@ +import { TimeUnitType, ApproveType, APPROVE_TYPE } from './consts' + +// 获取条件节点默认的名称 +export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean | undefined): string => { + if (defaultFlow) { + return '其它情况' + } + return '条件' + (index + 1) +} + +// 获取包容分支条件节点默认的名称 +export const getDefaultInclusiveConditionNodeName = (index: number, defaultFlow: boolean | undefined): string => { + if (defaultFlow) { + return '其它情况' + } + return '包容条件' + (index + 1) +} + +export const convertTimeUnit = (strTimeUnit: string) => { + if (strTimeUnit === 'M') { + return TimeUnitType.MINUTE + } + if (strTimeUnit === 'H') { + return TimeUnitType.HOUR + } + if (strTimeUnit === 'D') { + return TimeUnitType.DAY + } + return TimeUnitType.HOUR +} + +export const getApproveTypeText = (approveType: ApproveType): string => { + let approveTypeText = '' + APPROVE_TYPE.forEach((item) => { + if (item.value === approveType) { + approveTypeText = item.label + return + } + }) + return approveTypeText +} diff --git a/src/components/SimpleProcessDesignerV2/theme/iconfont.ttf b/src/components/SimpleProcessDesignerV2/theme/iconfont.ttf new file mode 100644 index 0000000..bb85b35 Binary files /dev/null and b/src/components/SimpleProcessDesignerV2/theme/iconfont.ttf differ diff --git a/src/components/SimpleProcessDesignerV2/theme/iconfont.woff b/src/components/SimpleProcessDesignerV2/theme/iconfont.woff new file mode 100644 index 0000000..94befbd Binary files /dev/null and b/src/components/SimpleProcessDesignerV2/theme/iconfont.woff differ diff --git a/src/components/SimpleProcessDesignerV2/theme/iconfont.woff2 b/src/components/SimpleProcessDesignerV2/theme/iconfont.woff2 new file mode 100644 index 0000000..e8f95c8 Binary files /dev/null and b/src/components/SimpleProcessDesignerV2/theme/iconfont.woff2 differ diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss new file mode 100644 index 0000000..8cf2681 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -0,0 +1,755 @@ +// 配置节点头部 +.config-header { + display: flex; + flex-direction: column; + + .node-name { + display: flex; + height: 24px; + line-height: 24px; + font-size: 16px; + cursor: pointer; + align-items: center; + } + + .divide-line { + width: 100%; + height: 1px; + margin-top: 16px; + background: #eee; + } + + .config-editable-input { + height: 24px; + max-width: 510px; + font-size: 16px; + line-height: 24px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + border-color: #40a9ff; + outline: 0; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); + } + } +} + +// 表单字段权限 +.field-setting-pane { + display: flex; + flex-direction: column; + font-size: 14px; + + .field-setting-desc { + padding-right: 8px; + margin-bottom: 16px; + font-size: 16px; + font-weight: 700; + } + + .field-permit-title { + display: flex; + justify-content: space-between; + align-items: center; + height: 45px; + padding-left: 12px; + line-height: 45px; + background-color: #f8fafc0a; + border: 1px solid #1f38581a; + + .first-title { + text-align: left !important; + } + + .other-titles { + display: flex; + justify-content: space-between; + } + + .setting-title-label { + display: inline-block; + width: 110px; + padding: 5px 0; + font-size: 13px; + font-weight: 700; + color: #000; + text-align: center; + } + } + + .field-setting-item { + align-items: center; + display: flex; + justify-content: space-between; + height: 38px; + padding-left: 12px; + border: 1px solid #1f38581a; + border-top: 0; + + .field-setting-item-label { + display: inline-block; + width: 110px; + min-height: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: text; + } + + .field-setting-item-group { + display: flex; + justify-content: space-between; + + .item-radio-wrap { + display: inline-block; + width: 110px; + text-align: center; + } + } + } +} + +// 节点连线气泡卡片样式 +.handler-item-wrapper { + display: flex; + cursor: pointer; + + .handler-item { + display: flex; + flex-direction: column; + align-items: center; + } + + .handler-item-icon { + width: 60px; + height: 60px; + background: #fff; + border: 1px solid #e2e2e2; + border-radius: 50%; + user-select: none; + text-align: center; + + &:hover { + background: #e2e2e2; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); + } + + .icon-size { + font-size: 25px; + line-height: 60px; + } + } + + .approve { + color: #ff943e; + } + .copy { + color: #3296fa; + } + + .condition { + color: #67c23a; + } + + .parallel { + color: #626aef; + } + + .inclusive { + color: #345da2; + } + + .handler-item-text { + margin-top: 4px; + width: 80px; + text-align: center; + font-size: 13px; + } +} +// Simple 流程模型样式 +.simple-process-model-container { + height: 100%; + padding-top: 32px; + background-color: #fafafa; + overflow-x: auto; + width: 100%; + + .simple-process-model { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + transform-origin: 50% 0 0; + min-width: fit-content; + transform: scale(1); + transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + background: url(@/assets/svgs/bpm/simple-process-bg.svg) 0 0 repeat; + // 节点容器 定义节点宽度 + .node-container { + width: 200px; + } + // 节点 + .node-box { + position: relative; + display: flex; + min-height: 70px; + padding: 5px 10px 8px; + cursor: pointer; + background-color: #fff; + flex-direction: column; + border: 2px solid transparent; + border-radius: 8px; + box-shadow: 0 1px 4px 0 rgb(10 30 65 / 16%); + transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); + + &.status-pass { + background-color: #a9da90; + border-color: #67c23a; + } + + &.status-pass:hover { + border-color: #67c23a; + } + + &.status-running { + background-color: #e7f0fe; + border-color: #5a9cf8; + } + + &.status-running:hover { + border-color: #5a9cf8; + } + + &.status-reject { + background-color: #f6e5e5; + border-color: #e47470; + } + + &.status-reject:hover { + border-color: #e47470; + } + + &:hover { + border-color: #0089ff; + + .node-toolbar { + opacity: 1; + } + + .branch-node-move { + display: flex; + } + } + + // 普通节点标题 + .node-title-container { + display: flex; + padding: 4px; + cursor: pointer; + border-radius: 4px 4px 0 0; + align-items: center; + + .node-title-icon { + display: flex; + align-items: center; + + &.user-task { + color: #ff943e; + } + + &.copy-task { + color: #3296fa; + } + + &.start-user { + color: #676565; + } + } + + .node-title { + margin-left: 4px; + overflow: hidden; + font-size: 14px; + font-weight: 600; + line-height: 18px; + color: #1f1f1f; + text-overflow: ellipsis; + white-space: nowrap; + + &:hover { + border-bottom: 1px dashed #f60; + } + } + } + + // 条件节点标题 + .branch-node-title-container { + display: flex; + padding: 4px 0; + cursor: pointer; + border-radius: 4px 4px 0 0; + align-items: center; + justify-content: space-between; + + .input-max-width { + max-width: 115px !important; + } + + .branch-title { + overflow: hidden; + font-size: 13px; + font-weight: 600; + color: #f60; + text-overflow: ellipsis; + white-space: nowrap; + + &:hover { + border-bottom: 1px dashed #000; + } + } + + .branch-priority { + min-width: 50px; + font-size: 12px; + } + } + + .node-content { + display: flex; + min-height: 32px; + padding: 4px 8px; + margin-top: 4px; + line-height: 32px; + justify-content: space-between; + align-items: center; + color: #111f2c; + background: rgb(0 0 0 / 3%); + border-radius: 4px; + + .node-text { + display: -webkit-box; + overflow: hidden; + font-size: 14px; + line-height: 24px; + text-overflow: ellipsis; + word-break: break-all; + -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */ + -webkit-box-orient: vertical; + } + } + + //条件节点内容 + .branch-node-content { + display: flex; + min-height: 32px; + padding: 4px 0; + margin-top: 4px; + line-height: 32px; + align-items: center; + color: #111f2c; + border-radius: 4px; + + .branch-node-text { + overflow: hidden; + font-size: 12px; + line-height: 24px; + text-overflow: ellipsis; + word-break: break-all; + -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */ + -webkit-box-orient: vertical; + } + } + + // 节点操作 :删除 + .node-toolbar { + position: absolute; + top: -20px; + right: 0; + display: flex; + opacity: 0; + + .toolbar-icon { + text-align: center; + vertical-align: middle; + } + } + + // 条件节点左右移动 + .branch-node-move { + position: absolute; + display: none; + width: 10px; + height: 100%; + cursor: pointer; + align-items: center; + justify-content: center; + } + + .move-node-left { + top: 0; + left: -2px; + background: rgb(126 134 142 / 8%); + border-bottom-left-radius: 8px; + border-top-left-radius: 8px; + } + + .move-node-right { + top: 0; + right: -2px; + background: rgb(126 134 142 / 8%); + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + } + } + + .node-config-error { + border-color: #ff5219 !important; + } + // 普通节点包装 + .node-wrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + // 节点连线处理 + .node-handler-wrapper { + position: relative; + display: flex; + height: 70px; + align-items: center; + user-select: none; + justify-content: center; + flex-direction: column; + + &::before { + position: absolute; + top: 0; + z-index: 0; + width: 2px; + height: 100%; + margin: auto; + background-color: #dedede; + content: ''; + } + + .node-handler { + .add-icon { + position: relative; + top: -5px; + display: flex; + width: 25px; + height: 25px; + color: #fff; + cursor: pointer; + background-color: #0089ff; + border-radius: 50%; + align-items: center; + justify-content: center; + + &:hover { + transform: scale(1.1); + } + } + } + + .node-handler-arrow { + position: absolute; + bottom: 0; + left: 50%; + display: flex; + transform: translateX(-50%); + } + } + + // 条件节点包装 + .branch-node-wrapper { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 16px; + + .branch-node-container { + position: relative; + display: flex; + min-width: fit-content; + + &::before { + position: absolute; + left: 50%; + width: 4px; + height: 100%; + background-color: #fafafa; + content: ''; + transform: translate(-50%); + } + + .branch-node-add { + position: absolute; + top: -18px; + left: 50%; + z-index: 1; + height: 36px; + padding: 0 10px; + font-size: 12px; + line-height: 36px; + border: 2px solid #dedede; + border-radius: 18px; + transform: translateX(-50%); + transform-origin: center center; + } + + .branch-node-readonly { + position: absolute; + top: -18px; + left: 50%; + z-index: 1; + display: flex; + width: 36px; + height: 36px; + background-color: #fff; + border: 2px solid #dedede; + border-radius: 50%; + transform: translateX(-50%); + align-items: center; + justify-content: center; + transform-origin: center center; + + &.status-pass { + background-color: #e9f4e2; + border-color: #6bb63c; + } + + &.status-pass:hover { + border-color: #6bb63c; + } + + .icon-size { + font-size: 22px; + &.condition { + color: #67c23a; + } + &.parallel { + color: #626aef; + } + &.inclusive { + color: #345da2; + } + } + } + + .branch-node-item { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + min-width: 280px; + padding: 40px 40px 0; + background: transparent; + border-top: 2px solid #dedede; + border-bottom: 2px solid #dedede; + flex-shrink: 0; + + &::before { + position: absolute; + width: 2px; + height: 100%; + margin: auto; + inset: 0; + background-color: #dedede; + content: ''; + } + } + // 覆盖条件节点第一个节点左上角的线 + .branch-line-first-top { + position: absolute; + top: -5px; + left: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点第一个节点左下角的线 + .branch-line-first-bottom { + position: absolute; + bottom: -5px; + left: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点最后一个节点右上角的线 + .branch-line-last-top { + position: absolute; + top: -5px; + right: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点最后一个节点右下角的线 + .branch-line-last-bottom { + position: absolute; + right: -1px; + bottom: -5px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + } + } + + .node-fixed-name { + display: inline-block; + width: auto; + padding: 0 4px; + overflow: hidden; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + } + // 开始节点包装 + .start-node-wrapper { + position: relative; + margin-top: 16px; + + .start-node-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .start-node-box { + display: flex; + justify-content: center; + align-items: center; + width: 90px; + height: 36px; + padding: 3px 4px; + color: #212121; + cursor: pointer; + background: #fafafa; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgb(10 30 65 / 8%); + box-sizing: border-box; + } + } + } + + // 结束节点包装 + .end-node-wrapper { + margin-bottom: 16px; + + .end-node-box { + display: flex; + width: 80px; + height: 36px; + color: #212121; + border: 2px solid #fafafa; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgb(10 30 65 / 8%); + box-sizing: border-box; + justify-content: center; + align-items: center; + + &.status-pass { + background-color: #a9da90; + border-color: #6bb63c; + } + + &.status-pass:hover { + border-color: #6bb63c; + } + + &.status-reject { + background-color: #f6e5e5; + border-color: #e47470; + } + + &.status-reject:hover { + border-color: #e47470; + } + + &.status-cancel { + background-color: #eaeaeb; + border-color: #919398; + } + + &.status-cancel:hover { + border-color: #919398; + } + } + } + + // 可编辑的 title 输入框 + .editable-title-input { + height: 20px; + max-width: 145px; + margin-left: 4px; + font-size: 12px; + line-height: 20px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + border-color: #40a9ff; + outline: 0; + box-shadow: 0 0 0 2px rgb(24 144 255 / 20%); + } + } + } +} + +// iconfont 样式 +@font-face { + font-family: 'iconfont'; /* Project id 4495938 */ + src: + url('iconfont.woff2?t=1724339470412') format('woff2'), + url('iconfont.woff?t=1724339470412') format('woff'), + url('iconfont.ttf?t=1724339470412') format('truetype'); +} + +.iconfont { + font-family: 'iconfont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-start-user:before { + content: '\e679'; +} + +.icon-inclusive:before { + content: '\e602'; +} + +.icon-copy:before { + content: '\e7eb'; +} + +.icon-handle:before { + content: '\e61c'; +} + +.icon-exclusive:before { + content: '\e717'; +} + +.icon-approve:before { + content: '\e715'; +} + +.icon-parallel:before { + content: '\e688'; +} diff --git a/src/components/Sticky/index.ts b/src/components/Sticky/index.ts new file mode 100644 index 0000000..5e1de45 --- /dev/null +++ b/src/components/Sticky/index.ts @@ -0,0 +1,3 @@ +import Sticky from './src/Sticky.vue' + +export { Sticky } diff --git a/src/components/Sticky/src/Sticky.vue b/src/components/Sticky/src/Sticky.vue new file mode 100644 index 0000000..28ecbcb --- /dev/null +++ b/src/components/Sticky/src/Sticky.vue @@ -0,0 +1,143 @@ + + diff --git a/src/components/SummaryCard/index.vue b/src/components/SummaryCard/index.vue new file mode 100644 index 0000000..52da6da --- /dev/null +++ b/src/components/SummaryCard/index.vue @@ -0,0 +1,52 @@ + + diff --git a/src/components/Table/index.ts b/src/components/Table/index.ts new file mode 100644 index 0000000..9f89317 --- /dev/null +++ b/src/components/Table/index.ts @@ -0,0 +1,13 @@ +import Table from './src/Table.vue' +import { ElTable } from 'element-plus' +import { TableSetPropsType } from '@/types/table' +import TableSelectForm from './src/TableSelectForm.vue' + +export interface TableExpose { + setProps: (props: Recordable) => void + setColumn: (columnProps: TableSetPropsType[]) => void + selections: Recordable[] + elTableRef: ComponentRef +} + +export { Table, TableSelectForm } diff --git a/src/components/Table/src/Table.vue b/src/components/Table/src/Table.vue new file mode 100644 index 0000000..279a9fa --- /dev/null +++ b/src/components/Table/src/Table.vue @@ -0,0 +1,311 @@ + + diff --git a/src/components/Table/src/TableSelectForm.vue b/src/components/Table/src/TableSelectForm.vue new file mode 100644 index 0000000..7fece2d --- /dev/null +++ b/src/components/Table/src/TableSelectForm.vue @@ -0,0 +1,91 @@ + + + + diff --git a/src/components/Table/src/helper.ts b/src/components/Table/src/helper.ts new file mode 100644 index 0000000..d8b34a8 --- /dev/null +++ b/src/components/Table/src/helper.ts @@ -0,0 +1,8 @@ +export const setIndex = (reserveIndex: boolean, index: number, size: number, current: number) => { + const newIndex = index + 1 + if (reserveIndex) { + return size * (current - 1) + newIndex + } else { + return newIndex + } +} diff --git a/src/components/Table/src/types.ts b/src/components/Table/src/types.ts new file mode 100644 index 0000000..1c7ff76 --- /dev/null +++ b/src/components/Table/src/types.ts @@ -0,0 +1,26 @@ +import { Pagination, TableColumn } from '@/types/table' + +export type TableProps = { + pageSize?: number + currentPage?: number + // 是否多选 + selection?: boolean + // 是否所有的超出隐藏,优先级低于schema中的showOverflowTooltip, + showOverflowTooltip?: boolean + // 表头 + columns?: TableColumn[] + // 是否展示分页 + pagination?: Pagination | undefined + // 仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据(需指定 row-key) + reserveSelection?: boolean + // 加载状态 + loading?: boolean + // 是否叠加索引 + reserveIndex?: boolean + // 对齐方式 + align?: 'left' | 'center' | 'right' + // 表头对齐方式 + headerAlign?: 'left' | 'center' | 'right' + data?: Recordable + expand?: boolean +} & Recordable diff --git a/src/components/Tooltip/index.ts b/src/components/Tooltip/index.ts new file mode 100644 index 0000000..ab66ddf --- /dev/null +++ b/src/components/Tooltip/index.ts @@ -0,0 +1,3 @@ +import Tooltip from './src/Tooltip.vue' + +export { Tooltip } diff --git a/src/components/Tooltip/src/Tooltip.vue b/src/components/Tooltip/src/Tooltip.vue new file mode 100644 index 0000000..1a2e09c --- /dev/null +++ b/src/components/Tooltip/src/Tooltip.vue @@ -0,0 +1,17 @@ + + diff --git a/src/components/UploadFile/index.ts b/src/components/UploadFile/index.ts new file mode 100644 index 0000000..97c1d66 --- /dev/null +++ b/src/components/UploadFile/index.ts @@ -0,0 +1,5 @@ +import UploadImg from './src/UploadImg.vue' +import UploadImgs from './src/UploadImgs.vue' +import UploadFile from './src/UploadFile.vue' + +export { UploadImg, UploadImgs, UploadFile } diff --git a/src/components/UploadFile/src/UploadFile.vue b/src/components/UploadFile/src/UploadFile.vue new file mode 100644 index 0000000..9d0a904 --- /dev/null +++ b/src/components/UploadFile/src/UploadFile.vue @@ -0,0 +1,230 @@ + + + diff --git a/src/components/UploadFile/src/UploadImg.vue b/src/components/UploadFile/src/UploadImg.vue new file mode 100644 index 0000000..ac0c162 --- /dev/null +++ b/src/components/UploadFile/src/UploadImg.vue @@ -0,0 +1,271 @@ + + + + diff --git a/src/components/UploadFile/src/UploadImgs.vue b/src/components/UploadFile/src/UploadImgs.vue new file mode 100644 index 0000000..59857a9 --- /dev/null +++ b/src/components/UploadFile/src/UploadImgs.vue @@ -0,0 +1,318 @@ + + + + diff --git a/src/components/UploadFile/src/useUpload.ts b/src/components/UploadFile/src/useUpload.ts new file mode 100644 index 0000000..2981e12 --- /dev/null +++ b/src/components/UploadFile/src/useUpload.ts @@ -0,0 +1,106 @@ +import * as FileApi from '@/api/infra/file' +import CryptoJS from 'crypto-js' +import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload' +import axios from 'axios' + +/** + * 获得上传 URL + */ +export const getUploadUrl = (): string => { + return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload' +} + +export const useUpload = () => { + // 后端上传地址 + const uploadUrl = getUploadUrl() + // 是否使用前端直连上传 + const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE + // 重写ElUpload上传方法 + const httpRequest = async (options: UploadRequestOptions) => { + // 模式一:前端上传 + if (isClientUpload) { + // 1.1 生成文件名称 + const fileName = await generateFileName(options.file) + // 1.2 获取文件预签名地址 + const presignedInfo = await FileApi.getFilePresignedUrl(fileName) + // 1.3 上传文件(不能使用 ElUpload 的 ajaxUpload 方法的原因:其使用的是 FormData 上传,Minio 不支持) + return axios + .put(presignedInfo.uploadUrl, options.file, { + headers: { + 'Content-Type': options.file.type + } + }) + .then(() => { + // 1.4. 记录文件信息到后端(异步) + createFile(presignedInfo, fileName, options.file) + // 通知成功,数据格式保持与后端上传的返回结果一致 + return { data: presignedInfo.url } + }) + } else { + // 模式二:后端上传 + // 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子 + return new Promise((resolve, reject) => { + FileApi.updateFile({ file: options.file }) + .then((res) => { + if (res.code === 0) { + resolve(res) + } else { + reject(res) + } + }) + .catch((res) => { + reject(res) + }) + }) + } + } + + return { + uploadUrl, + httpRequest + } +} + +/** + * 创建文件信息 + * @param vo 文件预签名信息 + * @param name 文件名称 + * @param file 文件 + */ +function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) { + const fileVo = { + configId: vo.configId, + url: vo.url, + path: name, + name: file.name, + type: file.type, + size: file.size + } + FileApi.createFile(fileVo) + return fileVo +} + +/** + * 生成文件名称(使用算法SHA256) + * @param file 要上传的文件 + */ +async function generateFileName(file: UploadRawFile) { + // 读取文件内容 + const data = await file.arrayBuffer() + const wordArray = CryptoJS.lib.WordArray.create(data) + // 计算SHA256 + const sha256 = CryptoJS.SHA256(wordArray).toString() + // 拼接后缀 + const ext = file.name.substring(file.name.lastIndexOf('.')) + return `${sha256}${ext}` +} + +/** + * 上传类型 + */ +enum UPLOAD_TYPE { + // 客户端直接上传(只支持S3服务) + CLIENT = 'client', + // 客户端发送到后端上传 + SERVER = 'server' +} diff --git a/src/components/UserSelectForm/index.vue b/src/components/UserSelectForm/index.vue new file mode 100644 index 0000000..5ed99f8 --- /dev/null +++ b/src/components/UserSelectForm/index.vue @@ -0,0 +1,171 @@ + + + + diff --git a/src/components/Verifition/index.ts b/src/components/Verifition/index.ts new file mode 100644 index 0000000..bcfe6d9 --- /dev/null +++ b/src/components/Verifition/index.ts @@ -0,0 +1,3 @@ +import Verify from './src/Verify.vue' + +export { Verify } diff --git a/src/components/Verifition/src/Verify.vue b/src/components/Verifition/src/Verify.vue new file mode 100644 index 0000000..b7b5048 --- /dev/null +++ b/src/components/Verifition/src/Verify.vue @@ -0,0 +1,441 @@ + + + diff --git a/src/components/Verifition/src/Verify/VerifyPoints.vue b/src/components/Verifition/src/Verify/VerifyPoints.vue new file mode 100644 index 0000000..9d04f29 --- /dev/null +++ b/src/components/Verifition/src/Verify/VerifyPoints.vue @@ -0,0 +1,250 @@ + + diff --git a/src/components/Verifition/src/Verify/VerifySlide.vue b/src/components/Verifition/src/Verify/VerifySlide.vue new file mode 100644 index 0000000..f3c7bfe --- /dev/null +++ b/src/components/Verifition/src/Verify/VerifySlide.vue @@ -0,0 +1,376 @@ + + diff --git a/src/components/Verifition/src/Verify/index.ts b/src/components/Verifition/src/Verify/index.ts new file mode 100644 index 0000000..0daa63a --- /dev/null +++ b/src/components/Verifition/src/Verify/index.ts @@ -0,0 +1,4 @@ +import VerifySlide from './VerifySlide.vue' +import VerifyPoints from './VerifyPoints.vue' + +export { VerifySlide, VerifyPoints } diff --git a/src/components/Verifition/src/utils/ase.ts b/src/components/Verifition/src/utils/ase.ts new file mode 100644 index 0000000..d2e6b98 --- /dev/null +++ b/src/components/Verifition/src/utils/ase.ts @@ -0,0 +1,14 @@ +import CryptoJS from 'crypto-js' +/** + * @word 要加密的内容 + * @keyWord String 服务器随机返回的关键字 + * */ +export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') { + const key = CryptoJS.enc.Utf8.parse(keyWord) + const srcs = CryptoJS.enc.Utf8.parse(word) + const encrypted = CryptoJS.AES.encrypt(srcs, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }) + return encrypted.toString() +} diff --git a/src/components/Verifition/src/utils/util.ts b/src/components/Verifition/src/utils/util.ts new file mode 100644 index 0000000..15c1627 --- /dev/null +++ b/src/components/Verifition/src/utils/util.ts @@ -0,0 +1,97 @@ +export function resetSize(vm) { + let img_width, img_height, bar_width, bar_height //图片的宽度、高度,移动条的宽度、高度 + const EmployeeWindow = window as any + const parentWidth = vm.$el.parentNode.offsetWidth || EmployeeWindow.offsetWidth + const parentHeight = vm.$el.parentNode.offsetHeight || EmployeeWindow.offsetHeight + if (vm.imgSize.width.indexOf('%') != -1) { + img_width = (parseInt(vm.imgSize.width) / 100) * parentWidth + 'px' + } else { + img_width = vm.imgSize.width + } + + if (vm.imgSize.height.indexOf('%') != -1) { + img_height = (parseInt(vm.imgSize.height) / 100) * parentHeight + 'px' + } else { + img_height = vm.imgSize.height + } + + if (vm.barSize.width.indexOf('%') != -1) { + bar_width = (parseInt(vm.barSize.width) / 100) * parentWidth + 'px' + } else { + bar_width = vm.barSize.width + } + + if (vm.barSize.height.indexOf('%') != -1) { + bar_height = (parseInt(vm.barSize.height) / 100) * parentHeight + 'px' + } else { + bar_height = vm.barSize.height + } + + return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height } +} + +export const _code_chars = [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z' +] +export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0'] +export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC'] diff --git a/src/components/VerticalButtonGroup/index.vue b/src/components/VerticalButtonGroup/index.vue new file mode 100644 index 0000000..9c78ea2 --- /dev/null +++ b/src/components/VerticalButtonGroup/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/components/XButton/index.ts b/src/components/XButton/index.ts new file mode 100644 index 0000000..be0f0d4 --- /dev/null +++ b/src/components/XButton/index.ts @@ -0,0 +1,4 @@ +import XButton from './src/XButton.vue' +import XTextButton from './src/XTextButton.vue' + +export { XButton, XTextButton } diff --git a/src/components/XButton/src/XButton.vue b/src/components/XButton/src/XButton.vue new file mode 100644 index 0000000..40cba1a --- /dev/null +++ b/src/components/XButton/src/XButton.vue @@ -0,0 +1,50 @@ + + + + diff --git a/src/components/XButton/src/XTextButton.vue b/src/components/XButton/src/XTextButton.vue new file mode 100644 index 0000000..b1a922b --- /dev/null +++ b/src/components/XButton/src/XTextButton.vue @@ -0,0 +1,49 @@ + + + + diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue new file mode 100644 index 0000000..9d2fa5b --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue @@ -0,0 +1,665 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue new file mode 100644 index 0000000..34a54c8 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue @@ -0,0 +1,379 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/designer/index.ts b/src/components/bpmnProcessDesigner/package/designer/index.ts new file mode 100644 index 0000000..8522846 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/index.ts @@ -0,0 +1,8 @@ +import MyProcessDesigner from './ProcessDesigner.vue' + +MyProcessDesigner.install = function (Vue) { + Vue.component(MyProcessDesigner.name, MyProcessDesigner) +} + +// 流程图的设计器,可编辑 +export default MyProcessDesigner diff --git a/src/components/bpmnProcessDesigner/package/designer/index2.ts b/src/components/bpmnProcessDesigner/package/designer/index2.ts new file mode 100644 index 0000000..ebe8ca7 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/index2.ts @@ -0,0 +1,8 @@ +import MyProcessViewer from './ProcessViewer.vue' + +MyProcessViewer.install = function (Vue) { + Vue.component(MyProcessViewer.name, MyProcessViewer) +} + +// 流程图的查看器,不可编辑 +export default MyProcessViewer diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js b/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js new file mode 100644 index 0000000..8783493 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js @@ -0,0 +1,423 @@ +import { assign, forEach, isArray } from 'min-dash' + +import { is } from 'bpmn-js/lib/util/ModelUtil' + +import { isExpanded, isEventSubProcess } from 'bpmn-js/lib/util/DiUtil' + +import { isAny } from 'bpmn-js/lib/features/modeling/util/ModelingUtil' + +import { getChildLanes } from 'bpmn-js/lib/features/modeling/util/LaneUtil' + +import { hasPrimaryModifier } from 'diagram-js/lib/util/Mouse' + +/** + * A provider for BPMN 2.0 elements context pad + */ +export default function ContextPadProvider( + config, + injector, + eventBus, + contextPad, + modeling, + elementFactory, + connect, + create, + popupMenu, + canvas, + rules, + translate +) { + config = config || {} + + contextPad.registerProvider(this) + + 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._translate = translate + + if (config.autoPlace !== false) { + this._autoPlace = injector.get('autoPlace', false) + } + + eventBus.on('create.end', 250, function (event) { + const context = event.context, + shape = context.shape + + if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) { + return + } + + const entries = contextPad.getEntries(shape) + + if (entries.replace) { + entries.replace.action.click(event, shape) + } + }) +} + +ContextPadProvider.$inject = [ + 'config.contextPad', + 'injector', + 'eventBus', + 'contextPad', + 'modeling', + 'elementFactory', + 'connect', + 'create', + 'popupMenu', + 'canvas', + 'rules', + 'translate', + 'elementRegistry' +] + +ContextPadProvider.prototype.getContextPadEntries = function (element) { + const contextPad = this._contextPad, + modeling = this._modeling, + elementFactory = this._elementFactory, + connect = this._connect, + create = this._create, + popupMenu = this._popupMenu, + canvas = this._canvas, + rules = this._rules, + autoPlace = this._autoPlace, + translate = this._translate + + const actions = {} + + if (element.type === 'label') { + return actions + } + + const businessObject = element.businessObject + + function startConnect(event, element) { + connect.start(event, element) + } + + function removeElement() { + modeling.removeElements([element]) + } + + function getReplaceMenuPosition(element) { + const Y_OFFSET = 5 + + const diagramContainer = canvas.getContainer(), + pad = contextPad.getPad(element).html + + const diagramRect = diagramContainer.getBoundingClientRect(), + padRect = pad.getBoundingClientRect() + + const top = padRect.top - diagramRect.top + const left = padRect.left - diagramRect.left + + const pos = { + x: left, + y: top + padRect.height + Y_OFFSET + } + + return pos + } + + /** + * Create an append action + * + * @param {string} type + * @param {string} className + * @param {string} [title] + * @param {Object} [options] + * + * @return {Object} descriptor + */ + function appendAction(type, className, title, options) { + if (typeof title !== 'string') { + options = title + title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') }) + } + + function appendStart(event, element) { + const shape = elementFactory.createShape(assign({ type: type }, options)) + create.start(event, shape, { + source: element + }) + } + + const append = autoPlace + ? function (event, element) { + const shape = elementFactory.createShape(assign({ type: type }, options)) + + autoPlace.append(element, shape) + } + : appendStart + + return { + group: 'model', + className: className, + title: title, + action: { + dragstart: appendStart, + click: append + } + } + } + + function splitLaneHandler(count) { + return function (event, element) { + // actual split + modeling.splitLane(element, count) + + // refresh context pad after split to + // get rid of split icons + contextPad.open(element, true) + } + } + + if (isAny(businessObject, ['bpmn:Lane', 'bpmn:Participant']) && isExpanded(businessObject)) { + const childLanes = getChildLanes(element) + + assign(actions, { + 'lane-insert-above': { + group: 'lane-insert-above', + className: 'bpmn-icon-lane-insert-above', + title: translate('Add Lane above'), + action: { + click: function (event, element) { + modeling.addLane(element, 'top') + } + } + } + }) + + if (childLanes.length < 2) { + if (element.height >= 120) { + assign(actions, { + 'lane-divide-two': { + group: 'lane-divide', + className: 'bpmn-icon-lane-divide-two', + title: translate('Divide into two Lanes'), + action: { + click: splitLaneHandler(2) + } + } + }) + } + + if (element.height >= 180) { + assign(actions, { + 'lane-divide-three': { + group: 'lane-divide', + className: 'bpmn-icon-lane-divide-three', + title: translate('Divide into three Lanes'), + action: { + click: splitLaneHandler(3) + } + } + }) + } + } + + assign(actions, { + 'lane-insert-below': { + group: 'lane-insert-below', + className: 'bpmn-icon-lane-insert-below', + title: translate('Add Lane below'), + action: { + click: function (event, element) { + modeling.addLane(element, 'bottom') + } + } + } + }) + } + + if (is(businessObject, 'bpmn:FlowNode')) { + if (is(businessObject, 'bpmn:EventBasedGateway')) { + assign(actions, { + 'append.receive-task': appendAction( + 'bpmn:ReceiveTask', + 'bpmn-icon-receive-task', + translate('Append ReceiveTask') + ), + 'append.message-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-message', + translate('Append MessageIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:MessageEventDefinition' } + ), + 'append.timer-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-timer', + translate('Append TimerIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:TimerEventDefinition' } + ), + 'append.condition-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-condition', + translate('Append ConditionIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:ConditionalEventDefinition' } + ), + 'append.signal-intermediate-event': appendAction( + 'bpmn:IntermediateCatchEvent', + 'bpmn-icon-intermediate-event-catch-signal', + translate('Append SignalIntermediateCatchEvent'), + { eventDefinitionType: 'bpmn:SignalEventDefinition' } + ) + }) + } else if ( + isEventType(businessObject, 'bpmn:BoundaryEvent', 'bpmn:CompensateEventDefinition') + ) { + assign(actions, { + 'append.compensation-activity': appendAction( + 'bpmn:Task', + 'bpmn-icon-task', + translate('Append compensation activity'), + { + isForCompensation: true + } + ) + }) + } else if ( + !is(businessObject, 'bpmn:EndEvent') && + !businessObject.isForCompensation && + !isEventType(businessObject, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition') && + !isEventSubProcess(businessObject) + ) { + assign(actions, { + 'append.end-event': appendAction( + 'bpmn:EndEvent', + 'bpmn-icon-end-event-none', + translate('Append EndEvent') + ), + 'append.gateway': appendAction( + 'bpmn:ExclusiveGateway', + 'bpmn-icon-gateway-none', + translate('Append Gateway') + ), + 'append.append-task': appendAction( + 'bpmn:UserTask', + 'bpmn-icon-user-task', + translate('Append Task') + ), + 'append.intermediate-event': appendAction( + 'bpmn:IntermediateThrowEvent', + 'bpmn-icon-intermediate-event-none', + translate('Append Intermediate/Boundary Event') + ) + }) + } + } + + if (!popupMenu.isEmpty(element, 'bpmn-replace')) { + // Replace menu entry + assign(actions, { + replace: { + group: 'edit', + className: 'bpmn-icon-screw-wrench', + title: '修改类型', + action: { + click: function (event, element) { + const position = assign(getReplaceMenuPosition(element), { + cursor: { x: event.x, y: event.y } + }) + + popupMenu.open(element, 'bpmn-replace', position) + } + } + } + }) + } + + if ( + isAny(businessObject, [ + 'bpmn:FlowNode', + 'bpmn:InteractionNode', + 'bpmn:DataObjectReference', + 'bpmn:DataStoreReference' + ]) + ) { + assign(actions, { + 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation'), + + connect: { + group: 'connect', + className: 'bpmn-icon-connection-multi', + title: translate( + 'Connect using ' + + (businessObject.isForCompensation ? '' : 'Sequence/MessageFlow or ') + + 'Association' + ), + action: { + click: startConnect, + dragstart: startConnect + } + } + }) + } + + if (isAny(businessObject, ['bpmn:DataObjectReference', 'bpmn:DataStoreReference'])) { + assign(actions, { + connect: { + group: 'connect', + className: 'bpmn-icon-connection-multi', + title: translate('Connect using DataInputAssociation'), + action: { + click: startConnect, + dragstart: startConnect + } + } + }) + } + + if (is(businessObject, 'bpmn:Group')) { + assign(actions, { + 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation') + }) + } + + // delete element entry, only show if allowed by rules + let deleteAllowed = rules.allowed('elements.delete', { elements: [element] }) + + if (isArray(deleteAllowed)) { + // was the element returned as a deletion candidate? + deleteAllowed = deleteAllowed[0] === element + } + + if (deleteAllowed) { + assign(actions, { + delete: { + group: 'edit', + className: 'bpmn-icon-trash', + title: translate('Remove'), + action: { + click: removeElement + } + } + }) + } + + return actions +} + +// helpers ///////// + +function isEventType(eventBo, type, definition) { + const isType = eventBo.$instanceOf(type) + let isDefinition = false + + const definitions = eventBo.eventDefinitions || [] + forEach(definitions, function (def) { + if (def.$type === definition) { + isDefinition = true + } + }) + + return isType && isDefinition +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js b/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js new file mode 100644 index 0000000..80009ef --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js @@ -0,0 +1,6 @@ +import CustomContextPadProvider from './contentPadProvider' + +export default { + __init__: ['contextPadProvider'], + contextPadProvider: ['type', CustomContextPadProvider] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js b/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js new file mode 100644 index 0000000..f3bc894 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js @@ -0,0 +1,24 @@ +export default (key, name, type) => { + if (!type) type = 'camunda' + const TYPE_TARGET = { + activiti: 'http://activiti.org/bpmn', + camunda: 'http://bpmn.io/schema/bpmn', + flowable: 'http://flowable.org/bpmn' + } + return ` + + + + + + + +` +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json new file mode 100644 index 0000000..94ba8f6 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json @@ -0,0 +1,1004 @@ +{ + "name": "Activiti", + "uri": "http://activiti.org/bpmn", + "prefix": "activiti", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "name": "Definitions", + "isAbstract": true, + "extends": ["bpmn:Definitions"], + "properties": [ + { + "name": "diagramRelationId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "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": "JobPriorized", + "isAbstract": true, + "extends": ["bpmn:Process", "activiti: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": "activiti:errorMessage", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "PotentialStarter", + "superClass": ["Element"], + "properties": [ + { + "name": "resourceAssignmentExpression", + "type": "bpmn:ResourceAssignmentExpression" + } + ] + }, + { + "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": "executionListener", + "isAbstract": true, + "type": "Expression" + } + ] + }, + { + "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": "multiinstance_type", + "superClass": ["Element"] + }, + { + "name": "multiinstance_condition", + "superClass": ["Element"] + }, + { + "name": "Assignable", + "extends": ["bpmn:UserTask"], + "properties": [ + { + "name": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "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": "multiinstance_condition", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "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": "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": ["activiti:ServiceTaskLike"], + "properties": [ + { + "name": "type", + "isAttr": true, + "type": "String" + }, + { + "name": "topic", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TaskPriorized", + "extends": ["bpmn:Process", "activiti: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": ["activiti:ServiceTaskLike"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + } + ] + }, + { + "name": "InputOutput", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:FlowNode", "activiti: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": [ + "activiti:ServiceTaskLike", + "activiti:ExecutionListener", + "activiti:TaskListener" + ] + }, + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "expression", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "InputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "OutputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "Collectable", + "isAbstract": true, + "extends": ["bpmn:MultiInstanceLoopCharacteristics"], + "superClass": ["activiti:AsyncCapable"], + "properties": [ + { + "name": "collection", + "isAttr": true, + "type": "String" + }, + { + "name": "elementVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FailedJobRetryTimeCycle", + "superClass": ["Element"], + "meta": { + "allowedIn": ["activiti: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": "FormProperty", + "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/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json new file mode 100644 index 0000000..8322561 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json @@ -0,0 +1,1020 @@ +{ + "name": "Camunda", + "uri": "http://camunda.org/schema/1.0/bpmn", + "prefix": "camunda", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "name": "Definitions", + "isAbstract": true, + "extends": ["bpmn:Definitions"], + "properties": [ + { + "name": "diagramRelationId", + "isAttr": true, + "type": "String" + } + ] + }, + { + "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", "bpmn:SignalEventDefinition"] + } + }, + { + "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": "JobPriorized", + "isAbstract": true, + "extends": ["bpmn:Process", "camunda: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": "camunda:errorMessage", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "PotentialStarter", + "superClass": ["Element"], + "properties": [ + { + "name": "resourceAssignmentExpression", + "type": "bpmn:ResourceAssignmentExpression" + } + ] + }, + { + "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": "modelerTemplateVersion", + "isAttr": true, + "type": "Integer" + } + ] + }, + { + "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": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "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": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "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": "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": ["camunda:ServiceTaskLike"], + "properties": [ + { + "name": "type", + "isAttr": true, + "type": "String" + }, + { + "name": "topic", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "TaskPriorized", + "extends": ["bpmn:Process", "camunda: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": ["camunda:ServiceTaskLike"] + }, + "properties": [ + { + "name": "inputOutput", + "type": "InputOutput" + }, + { + "name": "connectorId", + "type": "String" + } + ] + }, + { + "name": "InputOutput", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:FlowNode", "camunda: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": [ + "camunda:ServiceTaskLike", + "camunda:ExecutionListener", + "camunda:TaskListener" + ] + }, + "properties": [ + { + "name": "name", + "isAttr": true, + "type": "String" + }, + { + "name": "expression", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "InputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "OutputParameter", + "superClass": ["InputOutputParameter"] + }, + { + "name": "Collectable", + "isAbstract": true, + "extends": ["bpmn:MultiInstanceLoopCharacteristics"], + "superClass": ["camunda:AsyncCapable"], + "properties": [ + { + "name": "collection", + "isAttr": true, + "type": "String" + }, + { + "name": "elementVariable", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "FailedJobRetryTimeCycle", + "superClass": ["Element"], + "meta": { + "allowedIn": ["camunda: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": "id", + "type": "String", + "isAttr": true + }, + { + "name": "eventDefinitions", + "type": "bpmn:TimerEventDefinition", + "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": "variableEvents", + "isAttr": true, + "type": "String" + } + ] + } + ], + "emumerations": [] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json new file mode 100644 index 0000000..7fe1fa7 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json @@ -0,0 +1,1444 @@ +{ + "name": "Flowable", + "uri": "http://flowable.org/bpmn", + "prefix": "flowable", + "xml": { + "tagAlias": "lowerCase" + }, + "associations": [], + "types": [ + { + "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": "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": "FormSupported", + "isAbstract": true, + "extends": ["bpmn:StartEvent", "bpmn:UserTask"], + "properties": [ + { + "name": "formHandlerClass", + "isAttr": true, + "type": "String" + }, + { + "name": "formKey", + "isAttr": true, + "type": "String" + }, + { + "name": "formType", + "isAttr": true, + "type": "String" + }, + { + "name": "formReadOnly", + "isAttr": true, + "type": "Boolean", + "default": false + }, + { + "name": "formInit", + "isAttr": true, + "type": "Boolean", + "default": true + } + ] + }, + { + "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": "assignee", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateUsers", + "isAttr": true, + "type": "String" + }, + { + "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": "candidateStrategy", + "isAttr": true, + "type": "String" + }, + { + "name": "candidateParam", + "isAttr": true, + "type": "String" + } + ] + }, + { + "name": "Assignee", + "supperClass": "Element", + "meta": { + "allowedIn": ["*"] + }, + "properties": [ + { + "name": "label", + "type": "String", + "isAttr": true + }, + { + "name": "viewId", + "type": "Number", + "isAttr": true + } + ] + }, + { + "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": "calledElementType", + "isAttr": true, + "type": "String" + }, + { + "name": "processInstanceName", + "isAttr": true, + "type": "String" + }, + { + "name": "inheritBusinessKey", + "isAttr": true, + "type": "Boolean" + }, + { + "name": "businessKey", + "isAttr": true, + "type": "String" + }, + { + "name": "inheritVariables", + "isAttr": true, + "type": "Boolean" + } + ] + }, + { + "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": "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": "Button", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "name", + "type": "String", + "isAttr": true + }, + { + "name": "code", + "type": "String", + "isAttr": true + }, + { + "name": "isHide", + "type": "String", + "isAttr": true + }, + { + "name": "next", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "isAttr": true + } + ] + }, + { + "name": "Assignee", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "type", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + }, + { + "name": "condition", + "type": "String", + "isAttr": true + }, + { + "name": "operationType", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "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", + "type": "String" + }, + { + "name": "stringValue", + "isAttr": true, + "type": "String" + }, + { + "name": "string", + "type": "String" + } + ] + }, + { + "name": "ChildField", + "superClass": ["Element"], + "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": "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": "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": "children", + "type": "ChildField", + "isMany": true + }, + { + "name": "extensionElements", + "type": "bpmn:ExtensionElements", + "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" + } + ] + }, + { + "name": "Condition", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:SequenceFlow"] + }, + "properties": [ + { + "name": "id", + "type": "String", + "isAttr": true + }, + { + "name": "field", + "type": "String", + "isAttr": true + }, + { + "name": "compare", + "type": "String", + "isAttr": true + }, + { + "name": "value", + "type": "String", + "isAttr": true + }, + { + "name": "logic", + "type": "String", + "isAttr": true + }, + { + "name": "sort", + "type": "Integer", + "isAttr": true + } + ] + }, + { + "name": "AssignStartUserHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "RejectHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "RejectReturnTaskId", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + }, + { + "name": "AssignEmptyHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "AssignEmptyUserIds", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + }, + { + "name": "ButtonsSetting", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "flowable:id", + "type": "Integer", + "isAttr": true + }, + { + "name": "flowable:enable", + "type": "Boolean", + "isAttr": true + }, + { + "name": "flowable:displayName", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "FieldsPermission", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "flowable:field", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:title", + "type": "String", + "isAttr": true + }, + { + "name": "flowable:permission", + "type": "String", + "isAttr": true + } + ] + }, + { + "name": "BoundaryEventType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:BoundaryEvent"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "TimeoutHandlerType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:BoundaryEvent"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "ApproveType", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "ApproveMethod", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "CandidateStrategy", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Integer", + "isBody": true + } + ] + }, + { + "name": "CandidateParam", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "String", + "isBody": true + } + ] + } + ], + "emumerations": [] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js new file mode 100644 index 0000000..56ef38a --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js @@ -0,0 +1,83 @@ +'use strict' + +import { some } from 'min-dash' + +// const some = require('min-dash').some +// const some = some + +const ALLOWED_TYPES = { + FailedJobRetryTimeCycle: [ + 'bpmn:StartEvent', + 'bpmn:BoundaryEvent', + 'bpmn:IntermediateCatchEvent', + 'bpmn:Activity' + ], + Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], + Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'] +} + +function is(element, type) { + return element && typeof element.$instanceOf === 'function' && element.$instanceOf(type) +} + +function exists(element) { + return element && element.length +} + +function includesType(collection, type) { + return ( + exists(collection) && + some(collection, function (element) { + return is(element, type) + }) + ) +} + +function anyType(element, types) { + return some(types, function (type) { + return is(element, type) + }) +} + +function isAllowed(propName, propDescriptor, newElement) { + const name = propDescriptor.name, + types = ALLOWED_TYPES[name.replace(/activiti:/, '')] + + return name === propName && anyType(newElement, types) +} + +function ActivitiModdleExtension(eventBus) { + eventBus.on( + 'property.clone', + function (context) { + const newElement = context.newElement, + propDescriptor = context.propertyDescriptor + + this.canCloneProperty(newElement, propDescriptor) + }, + this + ) +} + +ActivitiModdleExtension.$inject = ['eventBus'] + +ActivitiModdleExtension.prototype.canCloneProperty = function (newElement, propDescriptor) { + if (isAllowed('activiti:FailedJobRetryTimeCycle', propDescriptor, newElement)) { + return ( + includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') || + includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') || + is(newElement.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics') + ) + } + + if (isAllowed('activiti:Connector', propDescriptor, newElement)) { + return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition') + } + + if (isAllowed('activiti:Field', propDescriptor, newElement)) { + return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition') + } +} + +// module.exports = ActivitiModdleExtension; +export default ActivitiModdleExtension diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js new file mode 100644 index 0000000..c22ca34 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js @@ -0,0 +1,11 @@ +/* + * @author igdianov + * address https://github.com/igdianov/activiti-bpmn-moddle + * */ + +import activitiExtension from './activitiExtension' + +export default { + __init__: ['ActivitiModdleExtension'], + ActivitiModdleExtension: ['type', activitiExtension] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js new file mode 100644 index 0000000..b8c37a5 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js @@ -0,0 +1,151 @@ +'use strict' + +import { isFunction, isObject, some } from 'min-dash' + +// const isFunction = isFunction, +// isObject = isObject, +// some = some +// const isFunction = require('min-dash').isFunction, +// isObject = require('min-dash').isObject, +// some = require('min-dash').some + +const WILDCARD = '*' + +function CamundaModdleExtension(eventBus) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this + + eventBus.on('moddleCopy.canCopyProperty', function (context) { + const property = context.property, + parent = context.parent + + return self.canCopyProperty(property, parent) + }) +} + +CamundaModdleExtension.$inject = ['eventBus'] + +/** + * Check wether to disallow copying property. + */ +CamundaModdleExtension.prototype.canCopyProperty = function (property, parent) { + // (1) check wether property is allowed in parent + if (isObject(property) && !isAllowedInParent(property, parent)) { + return false + } + + // (2) check more complex scenarios + + if (is(property, 'camunda:InputOutput') && !this.canHostInputOutput(parent)) { + return false + } + + if (isAny(property, ['camunda:Connector', 'camunda:Field']) && !this.canHostConnector(parent)) { + return false + } + + if (is(property, 'camunda:In') && !this.canHostIn(parent)) { + return false + } +} + +CamundaModdleExtension.prototype.canHostInputOutput = function (parent) { + // allowed in camunda:Connector + const connector = getParent(parent, 'camunda:Connector') + + if (connector) { + return true + } + + // special rules inside bpmn:FlowNode + const flowNode = getParent(parent, 'bpmn:FlowNode') + + if (!flowNode) { + return false + } + + if (isAny(flowNode, ['bpmn:StartEvent', 'bpmn:Gateway', 'bpmn:BoundaryEvent'])) { + return false + } + + return !(is(flowNode, 'bpmn:SubProcess') && flowNode.get('triggeredByEvent')) +} + +CamundaModdleExtension.prototype.canHostConnector = function (parent) { + const serviceTaskLike = getParent(parent, 'camunda:ServiceTaskLike') + + if (is(serviceTaskLike, 'bpmn:MessageEventDefinition')) { + // only allow on throw and end events + return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent') + } + + return true +} + +CamundaModdleExtension.prototype.canHostIn = function (parent) { + const callActivity = getParent(parent, 'bpmn:CallActivity') + + if (callActivity) { + return true + } + + const signalEventDefinition = getParent(parent, 'bpmn:SignalEventDefinition') + + if (signalEventDefinition) { + // only allow on throw and end events + return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent') + } + + return true +} + +// module.exports = CamundaModdleExtension; +export default CamundaModdleExtension + +// helpers ////////// + +function is(element, type) { + return element && isFunction(element.$instanceOf) && element.$instanceOf(type) +} + +function isAny(element, types) { + return some(types, function (t) { + return is(element, t) + }) +} + +function getParent(element, type) { + if (!type) { + return element.$parent + } + + if (is(element, type)) { + return element + } + + if (!element.$parent) { + return + } + + return getParent(element.$parent, type) +} + +function isAllowedInParent(property, parent) { + // (1) find property descriptor + const descriptor = property.$type && property.$model.getTypeDescriptor(property.$type) + + const allowedIn = descriptor && descriptor.meta && descriptor.meta.allowedIn + + if (!allowedIn || isWildcard(allowedIn)) { + return true + } + + // (2) check wether property has parent of allowed type + return some(allowedIn, function (type) { + return getParent(parent, type) + }) +} + +function isWildcard(allowedIn) { + return allowedIn.indexOf(WILDCARD) !== -1 +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js new file mode 100644 index 0000000..1da1bc7 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js @@ -0,0 +1,8 @@ +'use strict' + +import extension from './extension' + +export default { + __init__: ['camundaModdleExtension'], + camundaModdleExtension: ['type', extension] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js new file mode 100644 index 0000000..3dcea67 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js @@ -0,0 +1,83 @@ +'use strict' + +import { some } from 'min-dash' + +// const some = some +// const some = require('min-dash').some + +const ALLOWED_TYPES = { + FailedJobRetryTimeCycle: [ + 'bpmn:StartEvent', + 'bpmn:BoundaryEvent', + 'bpmn:IntermediateCatchEvent', + 'bpmn:Activity' + ], + Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'], + Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'] +} + +function is(element, type) { + return element && typeof element.$instanceOf === 'function' && element.$instanceOf(type) +} + +function exists(element) { + return element && element.length +} + +function includesType(collection, type) { + return ( + exists(collection) && + some(collection, function (element) { + return is(element, type) + }) + ) +} + +function anyType(element, types) { + return some(types, function (type) { + return is(element, type) + }) +} + +function isAllowed(propName, propDescriptor, newElement) { + const name = propDescriptor.name, + types = ALLOWED_TYPES[name.replace(/flowable:/, '')] + + return name === propName && anyType(newElement, types) +} + +function FlowableModdleExtension(eventBus) { + eventBus.on( + 'property.clone', + function (context) { + const newElement = context.newElement, + propDescriptor = context.propertyDescriptor + + this.canCloneProperty(newElement, propDescriptor) + }, + this + ) +} + +FlowableModdleExtension.$inject = ['eventBus'] + +FlowableModdleExtension.prototype.canCloneProperty = function (newElement, propDescriptor) { + if (isAllowed('flowable:FailedJobRetryTimeCycle', propDescriptor, newElement)) { + return ( + includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') || + includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') || + is(newElement.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics') + ) + } + + if (isAllowed('flowable:Connector', propDescriptor, newElement)) { + return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition') + } + + if (isAllowed('flowable:Field', propDescriptor, newElement)) { + return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition') + } +} + +// module.exports = FlowableModdleExtension; +export default FlowableModdleExtension diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js new file mode 100644 index 0000000..6d59b67 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js @@ -0,0 +1,10 @@ +/* + * @author igdianov + * address https://github.com/igdianov/activiti-bpmn-moddle + * */ +import flowableExtension from './flowableExtension' + +export default { + __init__: ['FlowableModdleExtension'], + FlowableModdleExtension: ['type', flowableExtension] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js new file mode 100644 index 0000000..788e4d1 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js @@ -0,0 +1,233 @@ +import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider' +import { assign } from 'min-dash' + +export default function CustomPalette( + palette, + create, + elementFactory, + spaceTool, + lassoTool, + handTool, + globalConnect, + translate +) { + PaletteProvider.call( + this, + palette, + create, + elementFactory, + spaceTool, + lassoTool, + handTool, + globalConnect, + translate, + 2000 + ) +} + +const F = function () {} // 核心,利用空对象作为中介; +F.prototype = PaletteProvider.prototype // 核心,将父类的原型赋值给空对象F; + +// 利用中介函数重写原型链方法 +F.prototype.getPaletteEntries = function () { + const actions = {}, + create = this._create, + elementFactory = this._elementFactory, + spaceTool = this._spaceTool, + lassoTool = this._lassoTool, + handTool = this._handTool, + globalConnect = this._globalConnect, + translate = this._translate + + function createAction(type, group, className, title, options) { + function createListener(event) { + const shape = elementFactory.createShape(assign({ type: type }, options)) + + if (options) { + shape.businessObject.di.isExpanded = options.isExpanded + } + + create.start(event, shape) + } + + const shortType = type.replace(/^bpmn:/, '') + + return { + group: group, + className: className, + title: title || translate('Create {type}', { type: shortType }), + action: { + dragstart: createListener, + click: createListener + } + } + } + + function createSubprocess(event) { + const subProcess = elementFactory.createShape({ + type: 'bpmn:SubProcess', + x: 0, + y: 0, + isExpanded: true + }) + + const startEvent = elementFactory.createShape({ + type: 'bpmn:StartEvent', + x: 40, + y: 82, + parent: subProcess + }) + + create.start(event, [subProcess, startEvent], { + hints: { + autoSelect: [startEvent] + } + }) + } + + function createParticipant(event) { + create.start(event, elementFactory.createParticipantShape()) + } + + assign(actions, { + 'hand-tool': { + group: 'tools', + className: 'bpmn-icon-hand-tool', + title: '激活抓手工具', + // title: translate("Activate the hand tool"), + action: { + click: function (event) { + handTool.activateHand(event) + } + } + }, + 'lasso-tool': { + group: 'tools', + className: 'bpmn-icon-lasso-tool', + title: translate('Activate the lasso tool'), + action: { + click: function (event) { + lassoTool.activateSelection(event) + } + } + }, + 'space-tool': { + group: 'tools', + className: 'bpmn-icon-space-tool', + title: translate('Activate the create/remove space tool'), + action: { + click: function (event) { + spaceTool.activateSelection(event) + } + } + }, + 'global-connect-tool': { + group: 'tools', + className: 'bpmn-icon-connection-multi', + title: translate('Activate the global connect tool'), + action: { + click: function (event) { + globalConnect.toggle(event) + } + } + }, + 'tool-separator': { + group: 'tools', + separator: true + }, + 'create.start-event': createAction( + 'bpmn:StartEvent', + 'event', + 'bpmn-icon-start-event-none', + translate('Create StartEvent') + ), + 'create.intermediate-event': createAction( + 'bpmn:IntermediateThrowEvent', + 'event', + 'bpmn-icon-intermediate-event-none', + translate('Create Intermediate/Boundary Event') + ), + 'create.end-event': createAction( + 'bpmn:EndEvent', + 'event', + 'bpmn-icon-end-event-none', + translate('Create EndEvent') + ), + 'create.exclusive-gateway': createAction( + 'bpmn:ExclusiveGateway', + 'gateway', + 'bpmn-icon-gateway-none', + translate('Create Gateway') + ), + 'create.user-task': createAction( + 'bpmn:UserTask', + 'activity', + 'bpmn-icon-user-task', + translate('Create User Task') + ), + 'create.call-activity': createAction( + 'bpmn:CallActivity', + 'activity', + 'bpmn-icon-call-activity', + translate('Create Call Activity') + ), + 'create.service-task': createAction( + 'bpmn:ServiceTask', + 'activity', + 'bpmn-icon-service', + translate('Create Service Task') + ), + 'create.data-object': createAction( + 'bpmn:DataObjectReference', + 'data-object', + 'bpmn-icon-data-object', + translate('Create DataObjectReference') + ), + 'create.data-store': createAction( + 'bpmn:DataStoreReference', + 'data-store', + 'bpmn-icon-data-store', + translate('Create DataStoreReference') + ), + 'create.subprocess-expanded': { + group: 'activity', + className: 'bpmn-icon-subprocess-expanded', + title: translate('Create expanded SubProcess'), + action: { + dragstart: createSubprocess, + click: createSubprocess + } + }, + 'create.participant-expanded': { + group: 'collaboration', + className: 'bpmn-icon-participant', + title: translate('Create Pool/Participant'), + action: { + dragstart: createParticipant, + click: createParticipant + } + }, + 'create.group': createAction( + 'bpmn:Group', + 'artifact', + 'bpmn-icon-group', + translate('Create Group') + ) + }) + + return actions +} + +CustomPalette.$inject = [ + 'palette', + 'create', + 'elementFactory', + 'spaceTool', + 'lassoTool', + 'handTool', + 'globalConnect', + 'translate' +] + +CustomPalette.prototype = new F() // 核心,将 F的实例赋值给子类; +CustomPalette.prototype.constructor = CustomPalette // 修复子类CustomPalette的构造器指向,防止原型链的混乱; diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js new file mode 100644 index 0000000..8e4f3ac --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js @@ -0,0 +1,22 @@ +// import PaletteModule from "diagram-js/lib/features/palette"; +// import CreateModule from "diagram-js/lib/features/create"; +// import SpaceToolModule from "diagram-js/lib/features/space-tool"; +// import LassoToolModule from "diagram-js/lib/features/lasso-tool"; +// import HandToolModule from "diagram-js/lib/features/hand-tool"; +// import GlobalConnectModule from "diagram-js/lib/features/global-connect"; +// import translate from "diagram-js/lib/i18n/translate"; +// +// import PaletteProvider from "./paletteProvider"; +// +// export default { +// __depends__: [PaletteModule, CreateModule, SpaceToolModule, LassoToolModule, HandToolModule, GlobalConnectModule, translate], +// __init__: ["paletteProvider"], +// paletteProvider: ["type", PaletteProvider] +// }; + +import CustomPalette from './CustomPalette' + +export default { + __init__: ['paletteProvider'], + paletteProvider: ['type', CustomPalette] +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js new file mode 100644 index 0000000..304875c --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js @@ -0,0 +1,219 @@ +import { assign } from 'min-dash' + +/** + * A palette provider for BPMN 2.0 elements. + */ +export default function PaletteProvider( + 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 + + palette.registerProvider(this) +} + +PaletteProvider.$inject = [ + 'palette', + 'create', + 'elementFactory', + 'spaceTool', + 'lassoTool', + 'handTool', + 'globalConnect', + 'translate' +] + +PaletteProvider.prototype.getPaletteEntries = function () { + const actions = {}, + create = this._create, + elementFactory = this._elementFactory, + spaceTool = this._spaceTool, + lassoTool = this._lassoTool, + handTool = this._handTool, + globalConnect = this._globalConnect, + translate = this._translate + + function createAction(type, group, className, title, options) { + function createListener(event) { + const shape = elementFactory.createShape(assign({ type: type }, options)) + + if (options) { + shape.businessObject.di.isExpanded = options.isExpanded + } + + create.start(event, shape) + } + + const shortType = type.replace(/^bpmn:/, '') + + return { + group: group, + className: className, + title: title || translate('Create {type}', { type: shortType }), + action: { + dragstart: createListener, + click: createListener + } + } + } + + function createSubprocess(event) { + const subProcess = elementFactory.createShape({ + type: 'bpmn:SubProcess', + x: 0, + y: 0, + isExpanded: true + }) + + const startEvent = elementFactory.createShape({ + type: 'bpmn:StartEvent', + x: 40, + y: 82, + parent: subProcess + }) + + create.start(event, [subProcess, startEvent], { + hints: { + autoSelect: [startEvent] + } + }) + } + + function createParticipant(event) { + create.start(event, elementFactory.createParticipantShape()) + } + + assign(actions, { + 'hand-tool': { + group: 'tools', + className: 'bpmn-icon-hand-tool', + title: translate('Activate the hand tool'), + action: { + click: function (event) { + handTool.activateHand(event) + } + } + }, + 'lasso-tool': { + group: 'tools', + className: 'bpmn-icon-lasso-tool', + title: translate('Activate the lasso tool'), + action: { + click: function (event) { + lassoTool.activateSelection(event) + } + } + }, + 'space-tool': { + group: 'tools', + className: 'bpmn-icon-space-tool', + title: translate('Activate the create/remove space tool'), + action: { + click: function (event) { + spaceTool.activateSelection(event) + } + } + }, + 'global-connect-tool': { + group: 'tools', + className: 'bpmn-icon-connection-multi', + title: translate('Activate the global connect tool'), + action: { + click: function (event) { + globalConnect.toggle(event) + } + } + }, + 'tool-separator': { + group: 'tools', + separator: true + }, + 'create.start-event': createAction( + 'bpmn:StartEvent', + 'event', + 'bpmn-icon-start-event-none', + translate('Create StartEvent') + ), + 'create.intermediate-event': createAction( + 'bpmn:IntermediateThrowEvent', + 'event', + 'bpmn-icon-intermediate-event-none', + translate('Create Intermediate/Boundary Event') + ), + 'create.end-event': createAction( + 'bpmn:EndEvent', + 'event', + 'bpmn-icon-end-event-none', + translate('Create EndEvent') + ), + 'create.exclusive-gateway': createAction( + 'bpmn:ExclusiveGateway', + 'gateway', + 'bpmn-icon-gateway-none', + translate('Create Gateway') + ), + 'create.user-task': createAction( + 'bpmn:UserTask', + 'activity', + 'bpmn-icon-user-task', + translate('Create User Task') + ), + 'create.service-task': createAction( + 'bpmn:ServiceTask', + 'activity', + 'bpmn-icon-service', + translate('Create Service Task') + ), + 'create.data-object': createAction( + 'bpmn:DataObjectReference', + 'data-object', + 'bpmn-icon-data-object', + translate('Create DataObjectReference') + ), + 'create.data-store': createAction( + 'bpmn:DataStoreReference', + 'data-store', + 'bpmn-icon-data-store', + translate('Create DataStoreReference') + ), + 'create.subprocess-expanded': { + group: 'activity', + className: 'bpmn-icon-subprocess-expanded', + title: translate('Create expanded SubProcess'), + action: { + dragstart: createSubprocess, + click: createSubprocess + } + }, + 'create.participant-expanded': { + group: 'collaboration', + className: 'bpmn-icon-participant', + title: translate('Create Pool/Participant'), + action: { + dragstart: createParticipant, + click: createParticipant + } + }, + 'create.group': createAction( + 'bpmn:Group', + 'artifact', + 'bpmn-icon-group', + translate('Create Group') + ) + }) + + return actions +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js b/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js new file mode 100644 index 0000000..c1b99e1 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js @@ -0,0 +1,44 @@ +// import translations from "./zh"; +// +// export default function customTranslate(template, replacements) { +// replacements = replacements || {}; +// +// // Translate +// template = translations[template] || template; +// +// // Replace +// return template.replace(/{([^}]+)}/g, function(_, key) { +// let str = replacements[key]; +// if ( +// translations[replacements[key]] !== null && +// translations[replacements[key]] !== "undefined" +// ) { +// // eslint-disable-next-line no-mixed-spaces-and-tabs +// str = translations[replacements[key]]; +// // eslint-disable-next-line no-mixed-spaces-and-tabs +// } +// return str || "{" + key + "}"; +// }); +// } + +export default function customTranslate(translations) { + return function (template, replacements) { + replacements = replacements || {} + // Translate + template = translations[template] || template + + // Replace + return template.replace(/{([^}]+)}/g, function (_, key) { + let str = replacements[key] + if ( + translations[replacements[key]] !== null && + translations[replacements[key]] !== undefined + ) { + // eslint-disable-next-line no-mixed-spaces-and-tabs + str = translations[replacements[key]] + // eslint-disable-next-line no-mixed-spaces-and-tabs + } + return str || '{' + key + '}' + }) + } +} diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js b/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js new file mode 100644 index 0000000..cb92041 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js @@ -0,0 +1,242 @@ +/** + * This is a sample file that should be replaced with the actual translation. + * + * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available + * translations and labels to translate. + */ +export default { + // 添加部分 + 'Append EndEvent': '追加结束事件', + 'Append Gateway': '追加网关', + 'Append Task': '追加任务', + 'Append Intermediate/Boundary Event': '追加中间抛出事件/边界事件', + + 'Activate the global connect tool': '激活全局连接工具', + 'Append {type}': '添加 {type}', + 'Add Lane above': '在上面添加道', + 'Divide into two Lanes': '分割成两个道', + 'Divide into three Lanes': '分割成三个道', + 'Add Lane below': '在下面添加道', + 'Append compensation activity': '追加补偿活动', + 'Change type': '修改类型', + 'Connect using Association': '使用关联连接', + 'Connect using Sequence/MessageFlow or Association': '使用顺序/消息流或者关联连接', + 'Connect using DataInputAssociation': '使用数据输入关联连接', + Remove: '移除', + 'Activate the hand tool': '激活抓手工具', + 'Activate the lasso tool': '激活套索工具', + 'Activate the create/remove space tool': '激活创建/删除空间工具', + 'Create expanded SubProcess': '创建扩展子过程', + 'Create IntermediateThrowEvent/BoundaryEvent': '创建中间抛出事件/边界事件', + 'Create Pool/Participant': '创建池/参与者', + 'Parallel Multi Instance': '并行多重事件', + 'Sequential Multi Instance': '时序多重事件', + DataObjectReference: '数据对象参考', + DataStoreReference: '数据存储参考', + Loop: '循环', + 'Ad-hoc': '即席', + 'Create {type}': '创建 {type}', + Task: '任务', + 'Send Task': '发送任务', + 'Receive Task': '接收任务', + 'User Task': '用户任务', + 'Manual Task': '手工任务', + 'Business Rule Task': '业务规则任务', + 'Service Task': '服务任务', + 'Script Task': '脚本任务', + 'Call Activity': '调用活动', + 'Sub Process (collapsed)': '子流程(折叠的)', + 'Sub Process (expanded)': '子流程(展开的)', + 'Start Event': '开始事件', + StartEvent: '开始事件', + 'Intermediate Throw Event': '中间事件', + 'End Event': '结束事件', + EndEvent: '结束事件', + 'Create StartEvent': '创建开始事件', + 'Create EndEvent': '创建结束事件', + 'Create Task': '创建任务', + 'Create User Task': '创建用户任务', + 'Create Call Activity': '创建调用活动', + 'Create Service Task': '创建服务任务', + 'Create Gateway': '创建网关', + 'Create DataObjectReference': '创建数据对象', + 'Create DataStoreReference': '创建数据存储', + 'Create Group': '创建分组', + 'Create Intermediate/Boundary Event': '创建中间/边界事件', + 'Message Start Event': '消息开始事件', + 'Timer Start Event': '定时开始事件', + 'Conditional Start Event': '条件开始事件', + 'Signal Start Event': '信号开始事件', + 'Error Start Event': '错误开始事件', + 'Escalation Start Event': '升级开始事件', + 'Compensation Start Event': '补偿开始事件', + 'Message Start Event (non-interrupting)': '消息开始事件(非中断)', + 'Timer Start Event (non-interrupting)': '定时开始事件(非中断)', + 'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)', + 'Signal Start Event (non-interrupting)': '信号开始事件(非中断)', + 'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)', + 'Message Intermediate Catch Event': '消息中间捕获事件', + 'Message Intermediate Throw Event': '消息中间抛出事件', + 'Timer Intermediate Catch Event': '定时中间捕获事件', + 'Escalation Intermediate Throw Event': '升级中间抛出事件', + 'Conditional Intermediate Catch Event': '条件中间捕获事件', + 'Link Intermediate Catch Event': '链接中间捕获事件', + 'Link Intermediate Throw Event': '链接中间抛出事件', + 'Compensation Intermediate Throw Event': '补偿中间抛出事件', + 'Signal Intermediate Catch Event': '信号中间捕获事件', + 'Signal Intermediate Throw Event': '信号中间抛出事件', + 'Message End Event': '消息结束事件', + 'Escalation End Event': '定时结束事件', + 'Error End Event': '错误结束事件', + 'Cancel End Event': '取消结束事件', + 'Compensation End Event': '补偿结束事件', + 'Signal End Event': '信号结束事件', + 'Terminate End Event': '终止结束事件', + 'Message Boundary Event': '消息边界事件', + 'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)', + 'Timer Boundary Event': '定时边界事件', + 'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)', + 'Escalation Boundary Event': '升级边界事件', + 'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)', + 'Conditional Boundary Event': '条件边界事件', + 'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)', + 'Error Boundary Event': '错误边界事件', + 'Cancel Boundary Event': '取消边界事件', + 'Signal Boundary Event': '信号边界事件', + 'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)', + 'Compensation Boundary Event': '补偿边界事件', + 'Exclusive Gateway': '互斥网关', + 'Parallel Gateway': '并行网关', + 'Inclusive Gateway': '相容网关', + 'Complex Gateway': '复杂网关', + 'Event based Gateway': '事件网关', + Transaction: '转运', + 'Sub Process': '子流程', + 'Event Sub Process': '事件子流程', + 'Collapsed Pool': '折叠池', + 'Expanded Pool': '展开池', + + // Errors + 'no parent for {element} in {parent}': '在{parent}里,{element}没有父类', + 'no shape type specified': '没有指定的形状类型', + 'flow elements must be children of pools/participants': '流元素必须是池/参与者的子类', + 'out of bounds release': 'out of bounds release', + 'more than {count} child lanes': '子道大于{count} ', + 'element required': '元素不能为空', + 'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范', + 'no diagram to display': '没有可展示的流程图', + 'no process or collaboration to display': '没有可展示的流程/协作', + 'element {element} referenced by {referenced}#{property} not yet drawn': + '由{referenced}#{property}引用的{element}元素仍未绘制', + 'already rendered {element}': '{element} 已被渲染', + 'failed to import {element}': '导入{element}失败', + //属性面板的参数 + Id: '编号', + Name: '名称', + General: '常规', + Details: '详情', + 'Message Name': '消息名称', + Message: '消息', + Initiator: '创建者', + 'Asynchronous Continuations': '持续异步', + 'Asynchronous Before': '异步前', + 'Asynchronous After': '异步后', + 'Job Configuration': '工作配置', + Exclusive: '排除', + 'Job Priority': '工作优先级', + 'Retry Time Cycle': '重试时间周期', + Documentation: '文档', + 'Element Documentation': '元素文档', + 'History Configuration': '历史配置', + 'History Time To Live': '历史的生存时间', + Forms: '表单', + 'Form Key': '表单key', + 'Form Fields': '表单字段', + 'Business Key': '业务key', + 'Form Field': '表单字段', + ID: '编号', + Type: '类型', + Label: '名称', + 'Default Value': '默认值', + 'Default Flow': '默认流转路径', + 'Conditional Flow': '条件流转路径', + 'Sequence Flow': '普通流转路径', + Validation: '校验', + 'Add Constraint': '添加约束', + Config: '配置', + Properties: '属性', + 'Add Property': '添加属性', + Value: '值', + Listeners: '监听器', + 'Execution Listener': '执行监听', + 'Event Type': '事件类型', + 'Listener Type': '监听器类型', + 'Java Class': 'Java类', + Expression: '表达式', + 'Must provide a value': '必须提供一个值', + 'Delegate Expression': '代理表达式', + Script: '脚本', + 'Script Format': '脚本格式', + 'Script Type': '脚本类型', + 'Inline Script': '内联脚本', + 'External Script': '外部脚本', + Resource: '资源', + 'Field Injection': '字段注入', + Extensions: '扩展', + 'Input/Output': '输入/输出', + 'Input Parameters': '输入参数', + 'Output Parameters': '输出参数', + Parameters: '参数', + 'Output Parameter': '输出参数', + 'Timer Definition Type': '定时器定义类型', + 'Timer Definition': '定时器定义', + Date: '日期', + Duration: '持续', + Cycle: '循环', + Signal: '信号', + 'Signal Name': '信号名称', + Escalation: '升级', + Error: '错误', + 'Link Name': '链接名称', + Condition: '条件名称', + 'Variable Name': '变量名称', + 'Variable Event': '变量事件', + 'Specify more than one variable change event as a comma separated list.': + '多个变量事件以逗号隔开', + 'Wait for Completion': '等待完成', + 'Activity Ref': '活动参考', + 'Version Tag': '版本标签', + Executable: '可执行文件', + 'External Task Configuration': '扩展任务配置', + 'Task Priority': '任务优先级', + External: '外部', + Connector: '连接器', + 'Must configure Connector': '必须配置连接器', + 'Connector Id': '连接器编号', + Implementation: '实现方式', + 'Field Injections': '字段注入', + Fields: '字段', + 'Result Variable': '结果变量', + Topic: '主题', + 'Configure Connector': '配置连接器', + 'Input Parameter': '输入参数', + Assignee: '代理人', + 'Candidate Users': '候选用户', + 'Candidate Groups': '候选组', + 'Due Date': '到期时间', + 'Follow Up Date': '跟踪日期', + Priority: '优先级', + 'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': + '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00', + 'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': + '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00', + Variables: '变量', + 'Candidate Starter Configuration': '候选人起动器配置', + 'Candidate Starter Groups': '候选人起动器组', + 'This maps to the process definition key.': '这映射到流程定义键。', + 'Candidate Starter Users': '候选人起动器的用户', + 'Specify more than one user as a comma separated list.': '指定多个用户作为逗号分隔的列表。', + 'Tasklist Configuration': 'Tasklist配置', + Startable: '启动', + 'Specify more than one group as a comma separated list.': '指定多个组作为逗号分隔的列表。' +} diff --git a/src/components/bpmnProcessDesigner/package/index.ts b/src/components/bpmnProcessDesigner/package/index.ts new file mode 100644 index 0000000..ce44a3c --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/index.ts @@ -0,0 +1,11 @@ +import MyProcessDesigner from './designer' +import MyProcessPenal from './penal' +import MyProcessViewer from './designer/index2' + +import './theme/index.scss' +import 'bpmn-js/dist/assets/diagram-js.css' +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css' +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css' +import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css' + +export { MyProcessDesigner, MyProcessPenal, MyProcessViewer } diff --git a/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue b/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue new file mode 100644 index 0000000..ba97d96 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue new file mode 100644 index 0000000..e53ad99 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue @@ -0,0 +1,258 @@ + + diff --git a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue new file mode 100644 index 0000000..70ad4f8 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue @@ -0,0 +1,180 @@ + + diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue b/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue new file mode 100644 index 0000000..f9cb9ac --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue new file mode 100644 index 0000000..ca46b27 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue @@ -0,0 +1,252 @@ + + + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue new file mode 100644 index 0000000..ba38514 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue @@ -0,0 +1,623 @@ + + + + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts b/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts new file mode 100644 index 0000000..a45355e --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts @@ -0,0 +1,13 @@ +import UserTaskCustomConfig from './components/UserTaskCustomConfig.vue' +import BoundaryEventTimer from './components/BoundaryEventTimer.vue' + +export const CustomConfigMap = { + UserTask: { + name: '用户任务', + componet: UserTaskCustomConfig + }, + BoundaryEventTimerEventDefinition: { + name: '定时边界事件(非中断)', + componet: BoundaryEventTimer + } +} diff --git a/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue b/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue new file mode 100644 index 0000000..304630d --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue @@ -0,0 +1,191 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue b/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue new file mode 100644 index 0000000..3bb7d66 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue @@ -0,0 +1,478 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/index.js b/src/components/bpmnProcessDesigner/package/penal/index.js new file mode 100644 index 0000000..7fa5617 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/index.js @@ -0,0 +1,7 @@ +import MyPropertiesPanel from './PropertiesPanel.vue' + +MyPropertiesPanel.install = function (Vue) { + Vue.component(MyPropertiesPanel.name, MyPropertiesPanel) +} + +export default MyPropertiesPanel diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue b/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue new file mode 100644 index 0000000..de5445c --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue @@ -0,0 +1,448 @@ + + diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue b/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue new file mode 100644 index 0000000..21088ab --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue @@ -0,0 +1,85 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue b/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue new file mode 100644 index 0000000..76e0c80 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue @@ -0,0 +1,491 @@ + + diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/template.js b/src/components/bpmnProcessDesigner/package/penal/listeners/template.js new file mode 100644 index 0000000..430dc64 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/listeners/template.js @@ -0,0 +1,178 @@ +export const template = (isTaskListener) => { + return ` +
+ + + + + + + + +
+ 添加监听器 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + ${ + isTaskListener + ? "" + + "" + + "" + + "" + + "" + + "" + + '' + + '' + + "" + + "" + + '' + : '' + } + + +

+ 注入字段: + 添加字段 +

+ + + + + + + + + + +
+ 取 消 + 保 存 +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ ` +} diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts b/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts new file mode 100644 index 0000000..b4eb1d2 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts @@ -0,0 +1,89 @@ +// 初始化表单数据 +export function initListenerForm(listener) { + let self = { + ...listener + } + if (listener.script) { + self = { + ...listener, + ...listener.script, + scriptType: listener.script.resource ? 'externalScript' : 'inlineScript' + } + } + if (listener.event === 'timeout' && listener.eventDefinitions) { + if (listener.eventDefinitions.length) { + let k = '' + for (const key in listener.eventDefinitions[0]) { + console.log(listener.eventDefinitions, key) + if (key.indexOf('time') !== -1) { + k = key + self.eventDefinitionType = key.replace('time', '').toLowerCase() + } + } + console.log(k) + self.eventTimeDefinitions = listener.eventDefinitions[0][k].body + } + } + return self +} + +export function initListenerType(listener) { + let listenerType + if (listener.class) listenerType = 'classListener' + if (listener.expression) listenerType = 'expressionListener' + if (listener.delegateExpression) listenerType = 'delegateExpressionListener' + if (listener.script) listenerType = 'scriptListener' + return { + ...JSON.parse(JSON.stringify(listener)), + ...(listener.script ?? {}), + listenerType: listenerType + } +} + +/** 将 ProcessListenerDO 转换成 initListenerForm 想同的 Form 对象 */ +export function initListenerForm2(processListener) { + if (processListener.valueType === 'class') { + return { + listenerType: 'classListener', + class: processListener.value, + event: processListener.event, + fields: [] + } + } else if (processListener.valueType === 'expression') { + return { + listenerType: 'expressionListener', + expression: processListener.value, + event: processListener.event, + fields: [] + } + } else if (processListener.valueType === 'delegateExpression') { + return { + listenerType: 'delegateExpressionListener', + delegateExpression: processListener.value, + event: processListener.event, + fields: [] + } + } + throw new Error('未知的监听器类型') +} + +export const listenerType = { + classListener: 'Java 类', + expressionListener: '表达式', + delegateExpressionListener: '代理表达式', + scriptListener: '脚本' +} + +export const eventType = { + create: '创建', + assignment: '指派', + complete: '完成', + delete: '删除', + update: '更新', + timeout: '超时' +} + +export const fieldType = { + string: '字符串', + expression: '表达式' +} diff --git a/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue b/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue new file mode 100644 index 0000000..de2fb0d --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue @@ -0,0 +1,412 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue b/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue new file mode 100644 index 0000000..05532c6 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue b/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue new file mode 100644 index 0000000..7bf4f0e --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue @@ -0,0 +1,168 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue b/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue new file mode 100644 index 0000000..f38f31c --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue @@ -0,0 +1,113 @@ + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue new file mode 100644 index 0000000..3a71b4c --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/data.ts b/src/components/bpmnProcessDesigner/package/penal/task/data.ts new file mode 100644 index 0000000..805c9ac --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/data.ts @@ -0,0 +1,36 @@ +import UserTask from './task-components/UserTask.vue' +import ServiceTask from './task-components/ServiceTask.vue' +import ScriptTask from './task-components/ScriptTask.vue' +import ReceiveTask from './task-components/ReceiveTask.vue' +import CallActivity from './task-components/CallActivity.vue' + +export const installedComponent = { + UserTask: { + name: '用户任务', + component: UserTask + }, + ServiceTask: { + name: '服务任务', + component: ServiceTask + }, + ScriptTask: { + name: '脚本任务', + component: ScriptTask + }, + ReceiveTask: { + name: '接收任务', + component: ReceiveTask + }, + CallActivity: { + name: '调用活动', + component: CallActivity + } +} + +export const getTaskCollapseItemName = (elementType) => { + return installedComponent[elementType].name +} + +export const isTaskCollapseItemShow = (elementType) => { + return installedComponent[elementType] +} diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue new file mode 100644 index 0000000..6d8268b --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue @@ -0,0 +1,280 @@ + + + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue new file mode 100644 index 0000000..a038e69 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue new file mode 100644 index 0000000..83ed24e --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue @@ -0,0 +1,125 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue new file mode 100644 index 0000000..683fef3 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue @@ -0,0 +1,99 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue new file mode 100644 index 0000000..2f9c535 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue new file mode 100644 index 0000000..e563bfd --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue @@ -0,0 +1,439 @@ + + + diff --git a/src/components/bpmnProcessDesigner/package/theme/element-variables.scss b/src/components/bpmnProcessDesigner/package/theme/element-variables.scss new file mode 100644 index 0000000..0646f8e --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/theme/element-variables.scss @@ -0,0 +1,70 @@ +/* 改变主题色变量 */ +$--color-primary: #1890ff; +$--color-danger: #ff4d4f; + +/* 改变 icon 字体路径变量,必需 */ +$--font-path: '~element-ui/lib/theme-chalk/fonts'; + +@use '~element-ui/packages/theme-chalk/src/index'; + +.el-table td, +.el-table th { + color: #333; +} +.el-drawer__header { + padding: 16px 16px 8px 16px; + margin: 0; + line-height: 24px; + font-size: 18px; + color: #303133; + box-sizing: border-box; + border-bottom: 1px solid #e8e8e8; +} +div[class^='el-drawer']:focus, +span:focus { + outline: none; +} +.el-drawer__body { + box-sizing: border-box; + padding: 16px; + width: 100%; + overflow-y: auto; +} + +.el-dialog { + margin-top: 50vh !important; + transform: translateY(-50%); + overflow: hidden; +} +.el-dialog__wrapper { + overflow: hidden; + max-height: 100vh; +} +.el-dialog__header { + padding: 16px 16px 8px 16px; + box-sizing: border-box; + border-bottom: 1px solid #e8e8e8; +} +.el-dialog__body { + padding: 16px; + max-height: 80vh; + box-sizing: border-box; + overflow-y: auto; +} +.el-dialog__footer { + padding: 16px; + box-sizing: border-box; + border-top: 1px solid #e8e8e8; +} +.el-dialog__close { + font-weight: 600; +} +.el-select { + width: 100%; +} +.el-divider:not(.el-divider--horizontal) { + margin: 0 8px; +} +.el-divider.el-divider--horizontal { + margin: 16px 0; +} diff --git a/src/components/bpmnProcessDesigner/package/theme/index.scss b/src/components/bpmnProcessDesigner/package/theme/index.scss new file mode 100644 index 0000000..2404760 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/theme/index.scss @@ -0,0 +1,117 @@ +@use './process-designer.scss'; +@use './process-panel.scss'; + +$success-color: #4eb819; +$primary-color: #409EFF; +$danger-color: #F56C6C; +$cancel-color: #909399; + +.process-viewer { + position: relative; + border: 1px solid #EFEFEF; + background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') repeat!important; + + .success-arrow { + fill: $success-color; + stroke: $success-color; + } + + .success-conditional { + fill: white; + stroke: $success-color; + } + + .success.djs-connection { + .djs-visual path { + stroke: $success-color!important; + //marker-end: url(#sequenceflow-end-white-success)!important; + } + } + + .success.djs-connection.condition-expression { + .djs-visual path { + //marker-start: url(#conditional-flow-marker-white-success)!important; + } + } + + .success.djs-shape { + .djs-visual rect { + stroke: $success-color!important; + fill: $success-color!important; + fill-opacity: 0.15!important; + } + + .djs-visual polygon { + stroke: $success-color!important; + } + + .djs-visual path:nth-child(2) { + stroke: $success-color!important; + fill: $success-color!important; + } + + .djs-visual circle { + stroke: $success-color!important; + fill: $success-color!important; + fill-opacity: 0.15!important; + } + } + + .primary.djs-shape { + .djs-visual rect { + stroke: $primary-color!important; + fill: $primary-color!important; + fill-opacity: 0.15!important; + } + + .djs-visual polygon { + stroke: $primary-color!important; + } + + .djs-visual circle { + stroke: $primary-color!important; + fill: $primary-color!important; + fill-opacity: 0.15!important; + } + } + + .danger.djs-shape { + .djs-visual rect { + stroke: $danger-color!important; + fill: $danger-color!important; + fill-opacity: 0.15!important; + } + + .djs-visual polygon { + stroke: $danger-color!important; + } + + .djs-visual circle { + stroke: $danger-color!important; + fill: $danger-color!important; + fill-opacity: 0.15!important; + } + } + + .cancel.djs-shape { + .djs-visual rect { + stroke: $cancel-color!important; + fill: $cancel-color!important; + fill-opacity: 0.15!important; + } + + .djs-visual polygon { + stroke: $cancel-color!important; + } + + .djs-visual circle { + stroke: $cancel-color!important; + fill: $cancel-color!important; + fill-opacity: 0.15!important; + } + } +} + +.process-viewer .djs-tooltip-container, .process-viewer .djs-overlay-container, .process-viewer .djs-palette { + display: none; +} diff --git a/src/components/bpmnProcessDesigner/package/theme/process-designer.scss b/src/components/bpmnProcessDesigner/package/theme/process-designer.scss new file mode 100644 index 0000000..bca0258 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/theme/process-designer.scss @@ -0,0 +1,159 @@ +@use 'bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css'; + +// 边框被 token-simulation 样式覆盖了 +.djs-palette { + background: var(--palette-background-color); + border: solid 1px var(--palette-border-color) !important; + border-radius: 2px; +} + +.my-process-designer { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + box-sizing: border-box; + .my-process-designer__header { + width: 100%; + min-height: 36px; + .el-button { + text-align: center; + } + .el-button-group { + margin: 4px; + } + .el-tooltip__popper { + .el-button { + width: 100%; + text-align: left; + padding-left: 8px; + padding-right: 8px; + } + .el-button:hover { + background: rgba(64, 158, 255, 0.8); + color: #ffffff; + } + } + .align { + position: relative; + i { + &:after { + content: '|'; + position: absolute; + // transform: rotate(90deg) translate(200%, 60%); + transform: rotate(180deg) translate(271%, -10%); + } + } + } + .align.align-left i { + transform: rotate(90deg); + } + .align.align-right i { + transform: rotate(-90deg); + } + .align.align-top i { + transform: rotate(180deg); + } + .align.align-bottom i { + transform: rotate(0deg); + } + .align.align-center i { + transform: rotate(0deg); + &:after { + // transform: rotate(90deg) translate(0, 60%); + transform: rotate(0deg) translate(-0%, -5%); + } + } + .align.align-middle i { + transform: rotate(-90deg); + &:after { + // transform: rotate(90deg) translate(0, 60%); + transform: rotate(0deg) translate(0, -10%); + } + } + } + .my-process-designer__container { + display: inline-flex; + width: 100%; + flex: 1; + .my-process-designer__canvas { + flex: 1; + height: 100%; + position: relative; + background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') + repeat !important; + div.toggle-mode { + display: none; + } + } + .my-process-designer__property-panel { + height: 100%; + overflow: scroll; + overflow-y: auto; + z-index: 10; + * { + box-sizing: border-box; + } + } + // svg { + // width: 100%; + // height: 100%; + // min-height: 100%; + // overflow: hidden; + // } + } +} + +//侧边栏配置 +// .djs-palette .two-column .open { +.open { + // .djs-palette.open { + .djs-palette-entries { + div[class^='bpmn-icon-']:before, + div[class*='bpmn-icon-']:before { + line-height: unset; + } + div.entry { + position: relative; + } + div.entry:hover { + &::after { + width: max-content; + content: attr(title); + vertical-align: text-bottom; + position: absolute; + right: -10px; + top: 0; + bottom: 0; + overflow: hidden; + transform: translateX(100%); + font-size: 0.5em; + display: inline-block; + text-decoration: inherit; + font-variant: normal; + text-transform: none; + background: #fafafa; + box-shadow: 0 0 6px #eeeeee; + border: 1px solid #cccccc; + box-sizing: border-box; + padding: 0 16px; + border-radius: 4px; + z-index: 100; + } + } + } +} +pre { + margin: 0; + height: 100%; + overflow: hidden; + max-height: calc(80vh - 32px); + overflow-y: auto; +} +.hljs { + word-break: break-word; + white-space: pre-wrap; +} +.hljs * { + font-family: Consolas, Monaco, monospace; +} diff --git a/src/components/bpmnProcessDesigner/package/theme/process-panel.scss b/src/components/bpmnProcessDesigner/package/theme/process-panel.scss new file mode 100644 index 0000000..f840cdd --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/theme/process-panel.scss @@ -0,0 +1,107 @@ +.process-panel__container { + box-sizing: border-box; + padding: 0 8px; + border-left: 1px solid #eeeeee; + box-shadow: 0 0 8px #cccccc; + max-height: 100%; + overflow-y: scroll; +} +.panel-tab__title { + font-weight: 600; + padding: 0 8px; + font-size: 1.1em; + line-height: 1.2em; + i { + margin-right: 8px; + font-size: 1.2em; + } +} +.panel-tab__content { + width: 100%; + box-sizing: border-box; + border-top: 1px solid #eeeeee; + padding: 8px 16px; + .panel-tab__content--title { + display: flex; + justify-content: space-between; + padding-bottom: 8px; + span { + flex: 1; + text-align: left; + } + } +} +.element-property { + width: 100%; + display: flex; + align-items: flex-start; + margin: 8px 0; + .element-property__label { + display: block; + width: 90px; + text-align: right; + overflow: hidden; + padding-right: 12px; + line-height: 32px; + font-size: 14px; + box-sizing: border-box; + } + .element-property__value { + flex: 1; + line-height: 32px; + } + .el-form-item { + width: 100%; + margin-bottom: 0; + padding-bottom: 18px; + } +} +.list-property { + flex-direction: column; + .element-listener-item { + width: 100%; + display: inline-grid; + grid-template-columns: 16px auto 32px 32px; + grid-column-gap: 8px; + } + .element-listener-item + .element-listener-item { + margin-top: 8px; + } +} +.listener-filed__title { + display: inline-flex; + width: 100%; + justify-content: space-between; + align-items: center; + margin-top: 0; + span { + width: 200px; + text-align: left; + font-size: 14px; + } + i { + margin-right: 8px; + } +} +.element-drawer__button { + margin-top: 8px; + width: 100%; + display: inline-flex; + justify-content: space-around; +} +.element-drawer__button > .el-button { + width: 100%; +} + +.el-collapse-item__content { + padding-bottom: 0; +} +.el-input.is-disabled .el-input__inner { + color: #999999; +} +.el-form-item.el-form-item--mini { + margin-bottom: 0; + & + .el-form-item { + margin-top: 16px; + } +} diff --git a/src/components/bpmnProcessDesigner/package/utils.ts b/src/components/bpmnProcessDesigner/package/utils.ts new file mode 100644 index 0000000..8996788 --- /dev/null +++ b/src/components/bpmnProcessDesigner/package/utils.ts @@ -0,0 +1,78 @@ +import { toRaw } from 'vue' +const bpmnInstances = () => (window as any)?.bpmnInstances +// 创建监听器实例 +export function createListenerObject(options, isTask, prefix) { + debugger + const listenerObj = Object.create(null) + listenerObj.event = options.event + isTask && (listenerObj.id = options.id) // 任务监听器特有的 id 字段 + switch (options.listenerType) { + case 'scriptListener': + listenerObj.script = createScriptObject(options, prefix) + break + case 'expressionListener': + listenerObj.expression = options.expression + break + case 'delegateExpressionListener': + listenerObj.delegateExpression = options.delegateExpression + break + default: + listenerObj.class = options.class + } + // 注入字段 + if (options.fields) { + listenerObj.fields = options.fields.map((field) => { + return createFieldObject(field, prefix) + }) + } + // 任务监听器的 定时器 设置 + if (isTask && options.event === 'timeout' && !!options.eventDefinitionType) { + const timeDefinition = bpmnInstances().moddle.create('bpmn:FormalExpression', { + body: options.eventTimeDefinitions + }) + const TimerEventDefinition = bpmnInstances().moddle.create('bpmn:TimerEventDefinition', { + id: `TimerEventDefinition_${uuid(8)}`, + [`time${options.eventDefinitionType.replace(/^\S/, (s) => s.toUpperCase())}`]: timeDefinition + }) + listenerObj.eventDefinitions = [TimerEventDefinition] + } + return bpmnInstances().moddle.create( + `${prefix}:${isTask ? 'TaskListener' : 'ExecutionListener'}`, + listenerObj + ) +} + +// 创建 监听器的注入字段 实例 +export function createFieldObject(option, prefix) { + const { name, fieldType, string, expression } = option + const fieldConfig = fieldType === 'string' ? { name, string } : { name, expression } + return bpmnInstances().moddle.create(`${prefix}:Field`, fieldConfig) +} + +// 创建脚本实例 +export function createScriptObject(options, prefix) { + const { scriptType, scriptFormat, value, resource } = options + const scriptConfig = + scriptType === 'inlineScript' ? { scriptFormat, value } : { scriptFormat, resource } + return bpmnInstances().moddle.create(`${prefix}:Script`, scriptConfig) +} + +// 更新元素扩展属性 +export function updateElementExtensions(element, extensionList) { + const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', { + values: extensionList + }) + bpmnInstances().modeling.updateProperties(toRaw(element), { + extensionElements: extensions + }) +} + +// 创建一个id +export function uuid(length = 8, chars?) { + let result = '' + const charsString = chars || '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + for (let i = length; i > 0; --i) { + result += charsString[Math.floor(Math.random() * charsString.length)] + } + return result +} diff --git a/src/components/bpmnProcessDesigner/src/highlight/index.js b/src/components/bpmnProcessDesigner/src/highlight/index.js new file mode 100644 index 0000000..5df38c9 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/highlight/index.js @@ -0,0 +1,5 @@ +const hljs = require('highlight.js/lib/core') +hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml')) +hljs.registerLanguage('json', require('highlight.js/lib/languages/json')) + +module.exports = hljs diff --git a/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js b/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js new file mode 100644 index 0000000..e876031 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js @@ -0,0 +1,14 @@ +import BpmnRenderer from 'bpmn-js/lib/draw/BpmnRenderer' + +export default function CustomRenderer(config, eventBus, styles, pathMap, canvas, textRenderer) { + BpmnRenderer.call(this, config, eventBus, styles, pathMap, canvas, textRenderer, 2000) + + this.handlers['label'] = function () { + return null + } +} + +const F = function () {} // 核心,利用空对象作为中介; +F.prototype = BpmnRenderer.prototype // 核心,将父类的原型赋值给空对象F; +CustomRenderer.prototype = new F() // 核心,将 F的实例赋值给子类; +CustomRenderer.prototype.constructor = CustomRenderer // 修复子类CustomRenderer的构造器指向,防止原型链的混乱; diff --git a/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js b/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js new file mode 100644 index 0000000..79d8bd0 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js @@ -0,0 +1,6 @@ +import CustomRenderer from './CustomRenderer' + +export default { + __init__: ['customRenderer'], + customRenderer: ['type', CustomRenderer] +} diff --git a/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js b/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js new file mode 100644 index 0000000..9fa1d14 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js @@ -0,0 +1,16 @@ +import BpmnRules from 'bpmn-js/lib/features/rules/BpmnRules' +import inherits from 'inherits' + +export default function CustomRules(eventBus) { + BpmnRules.call(this, eventBus) +} + +inherits(CustomRules, BpmnRules) + +CustomRules.prototype.canDrop = function () { + return false +} + +CustomRules.prototype.canMove = function () { + return false +} diff --git a/src/components/bpmnProcessDesigner/src/modules/rules/index.js b/src/components/bpmnProcessDesigner/src/modules/rules/index.js new file mode 100644 index 0000000..12cf05a --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/modules/rules/index.js @@ -0,0 +1,6 @@ +import CustomRules from './CustomRules' + +export default { + __init__: ['customRules'], + customRules: ['type', CustomRules] +} diff --git a/src/components/bpmnProcessDesigner/src/translations.ts b/src/components/bpmnProcessDesigner/src/translations.ts new file mode 100644 index 0000000..5f9b9a5 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/translations.ts @@ -0,0 +1,25 @@ +/** + * This is a sample file that should be replaced with the actual translation. + * + * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available + * translations and labels to translate. + */ +export default { + 'Exclusive Gateway': 'Exklusives Gateway', + 'Parallel Gateway': 'Paralleles Gateway', + 'Inclusive Gateway': 'Inklusives Gateway', + 'Complex Gateway': 'Komplexes Gateway', + 'Event based Gateway': 'Ereignis-basiertes Gateway', + 'Message Start Event': '消息启动事件', + 'Timer Start Event': '定时启动事件', + 'Conditional Start Event': '条件启动事件', + 'Signal Start Event': '信号启动事件', + 'Error Start Event': '错误启动事件', + 'Escalation Start Event': '升级启动事件', + 'Compensation Start Event': '补偿启动事件', + 'Message Start Event (non-interrupting)': '消息启动事件 (非中断)', + 'Timer Start Event (non-interrupting)': '定时启动事件 (非中断)', + 'Conditional Start Event (non-interrupting)': '条件启动事件 (非中断)', + 'Signal Start Event (non-interrupting)': '信号启动事件 (非中断)', + 'Escalation Start Event (non-interrupting)': '升级启动事件 (非中断)' +} diff --git a/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js b/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js new file mode 100644 index 0000000..bb71d44 --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js @@ -0,0 +1,39 @@ +//outside.js + +const ctx = '@@clickoutsideContext' + +export default { + bind(el, binding, vnode) { + const ele = el + const documentHandler = (e) => { + if (!vnode.context || ele.contains(e.target)) { + return false + } + // 调用指令回调 + if (binding.expression) { + vnode.context[el[ctx].methodName](e) + } else { + el[ctx].bindingFn(e) + } + } + // 将方法添加到ele + ele[ctx] = { + documentHandler, + methodName: binding.expression, + bindingFn: binding.value + } + + setTimeout(() => { + document.addEventListener('touchstart', documentHandler) // 为document绑定事件 + }) + }, + update(el, binding) { + const ele = el + ele[ctx].methodName = binding.expression + ele[ctx].bindingFn = binding.value + }, + unbind(el) { + document.removeEventListener('touchstart', el[ctx].documentHandler) // 解绑 + delete el[ctx] + } +} diff --git a/src/components/bpmnProcessDesigner/src/utils/index.js b/src/components/bpmnProcessDesigner/src/utils/index.js new file mode 100644 index 0000000..7d970ec --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/utils/index.js @@ -0,0 +1,10 @@ +export function debounce(fn, delay = 500) { + let timer + return function (...args) { + if (timer) { + clearTimeout(timer) + timer = null + } + timer = setTimeout(fn.bind(this, ...args), delay) + } +} diff --git a/src/components/bpmnProcessDesigner/src/utils/xml2json.js b/src/components/bpmnProcessDesigner/src/utils/xml2json.js new file mode 100644 index 0000000..fe1a52f --- /dev/null +++ b/src/components/bpmnProcessDesigner/src/utils/xml2json.js @@ -0,0 +1,50 @@ +function xmlStr2XmlObj(xmlStr) { + let xmlObj = {} + if (document.all) { + const xmlDom = new window.ActiveXObject('Microsoft.XMLDOM') + xmlDom.loadXML(xmlStr) + xmlObj = xmlDom + } else { + xmlObj = new DOMParser().parseFromString(xmlStr, 'text/xml') + } + return xmlObj +} + +function xml2json(xml) { + try { + let obj = {} + if (xml.children.length > 0) { + for (let i = 0; i < xml.children.length; i++) { + const item = xml.children.item(i) + const nodeName = item.nodeName + if (typeof obj[nodeName] == 'undefined') { + obj[nodeName] = xml2json(item) + } else { + if (typeof obj[nodeName].push == 'undefined') { + const old = obj[nodeName] + obj[nodeName] = [] + obj[nodeName].push(old) + } + obj[nodeName].push(xml2json(item)) + } + } + } else { + obj = xml.textContent + } + return obj + } catch (e) { + console.log(e.message) + } +} + +function xmlObj2json(xml) { + const xmlObj = xmlStr2XmlObj(xml) + console.log(xmlObj) + let jsonObj = {} + if (xmlObj.childNodes.length > 0) { + jsonObj = xml2json(xmlObj) + } + return jsonObj +} + +export default xmlObj2json diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..4d030c3 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,6 @@ +import type { App } from 'vue' +import { Icon } from './Icon' + +export const setupGlobCom = (app: App): void => { + app.component('Icon', Icon) +} diff --git a/src/config/axios/config.ts b/src/config/axios/config.ts new file mode 100644 index 0000000..8116508 --- /dev/null +++ b/src/config/axios/config.ts @@ -0,0 +1,28 @@ +const config: { + base_url: string + result_code: number | string + default_headers: AxiosHeaders + request_timeout: number +} = { + /** + * api请求基础路径 + */ + base_url: import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL, + /** + * 接口成功返回状态码 + */ + result_code: 200, + + /** + * 接口请求超时时间 + */ + request_timeout: 30000, + + /** + * 默认接口请求类型 + * 可选值:application/x-www-form-urlencoded multipart/form-data + */ + default_headers: 'application/json' +} + +export { config } diff --git a/src/config/axios/errorCode.ts b/src/config/axios/errorCode.ts new file mode 100644 index 0000000..94d719f --- /dev/null +++ b/src/config/axios/errorCode.ts @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + default: '系统未知错误,请反馈给管理员' +} diff --git a/src/config/axios/index.ts b/src/config/axios/index.ts new file mode 100644 index 0000000..07719a2 --- /dev/null +++ b/src/config/axios/index.ts @@ -0,0 +1,47 @@ +import { service } from './service' + +import { config } from './config' + +const { default_headers } = config + +const request = (option: any) => { + const { headersType, headers, ...otherOption } = option + return service({ + ...otherOption, + headers: { + 'Content-Type': headersType || default_headers, + ...headers + } + }) +} +export default { + get: async (option: any) => { + const res = await request({ method: 'GET', ...option }) + return res.data as unknown as T + }, + post: async (option: any) => { + const res = await request({ method: 'POST', ...option }) + return res.data as unknown as T + }, + postOriginal: async (option: any) => { + const res = await request({ method: 'POST', ...option }) + return res + }, + delete: async (option: any) => { + const res = await request({ method: 'DELETE', ...option }) + return res.data as unknown as T + }, + put: async (option: any) => { + const res = await request({ method: 'PUT', ...option }) + return res.data as unknown as T + }, + download: async (option: any) => { + const res = await request({ method: 'GET', responseType: 'blob', ...option }) + return res as unknown as Promise + }, + upload: async (option: any) => { + option.headersType = 'multipart/form-data' + const res = await request({ method: 'POST', ...option }) + return res as unknown as Promise + } +} diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts new file mode 100644 index 0000000..618f14a --- /dev/null +++ b/src/config/axios/service.ts @@ -0,0 +1,223 @@ +import axios, { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios' + +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' +import qs from 'qs' +import { config } from '@/config/axios/config' +import { getAccessToken, getRefreshToken, getTenantId, removeToken, setToken } from '@/utils/auth' +import errorCode from './errorCode' + +import { resetRouter } from '@/router' +import { deleteUserCache } from '@/hooks/web/useCache' + +const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE +const { result_code, base_url, request_timeout } = config + +// 需要忽略的提示。忽略后,自动 Promise.reject('error') +const ignoreMsgs = [ + '无效的刷新令牌', // 刷新令牌被删除时,不用提示 + '刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面 +] +// 是否显示重新登录 +export const isRelogin = { show: false } +// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现 +// 请求队列 +let requestList: any[] = [] +// 是否正在刷新中 +let isRefreshToken = false +// 请求白名单,无须token的接口 +const whiteList: string[] = ['/login', '/refresh-token'] + +// 创建axios实例 +const service: AxiosInstance = axios.create({ + baseURL: base_url, // api 的 base_url + timeout: request_timeout, // 请求超时时间 + withCredentials: false, // 禁用 Cookie 等信息 + // 自定义参数序列化函数 + paramsSerializer: (params) => { + return qs.stringify(params, { allowDots: true }) + } +}) + +// request拦截器 +service.interceptors.request.use( + (config: InternalAxiosRequestConfig) => { + // 是否需要设置 token + let isToken = (config!.headers || {}).isToken === false + whiteList.some((v) => { + if (config.url && config.url.indexOf(v) > -1) { + return (isToken = false) + } + }) + if (getAccessToken() && !isToken) { + config.headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token + } + // 设置租户 + if (tenantEnable && tenantEnable === 'true') { + const tenantId = getTenantId() + if (tenantId) config.headers['tenant-id'] = tenantId + } + const method = config.method?.toUpperCase() + // 防止 GET 请求缓存 + if (method === 'GET') { + config.headers['Cache-Control'] = 'no-cache' + config.headers['Pragma'] = 'no-cache' + } + // 自定义参数序列化函数 + else if (method === 'POST') { + const contentType = config.headers['Content-Type'] || config.headers['content-type'] + if (contentType === 'application/x-www-form-urlencoded') { + if (config.data && typeof config.data !== 'string') { + config.data = qs.stringify(config.data) + } + } + } + return config + }, + (error: AxiosError) => { + // Do something with request error + console.log(error) // for debug + return Promise.reject(error) + } +) + +// response 拦截器 +service.interceptors.response.use( + async (response: AxiosResponse) => { + let { data } = response + const config = response.config + if (!data) { + // 返回“[HTTP]请求没有返回值”; + throw new Error() + } + const { t } = useI18n() + // 未设置状态码则默认成功状态 + // 二进制数据则直接返回,例如说 Excel 导出 + if ( + response.request.responseType === 'blob' || + response.request.responseType === 'arraybuffer' + ) { + // 注意:如果导出的响应为 json,说明可能失败了,不直接返回进行下载 + if (response.data.type !== 'application/json') { + return response.data + } + data = await new Response(response.data).json() + } + const code = data.code || result_code + // 获取错误信息 + const msg = data.msg || errorCode[code] || errorCode['default'] + if (ignoreMsgs.indexOf(msg) !== -1) { + // 如果是忽略的错误码,直接返回 msg 异常 + return Promise.reject(msg) + } else if (code === 401) { + // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 + if (!isRefreshToken) { + isRefreshToken = true + // 1. 如果获取不到刷新令牌,则只能执行登出操作 + if (!getRefreshToken()) { + return handleAuthorized() + } + // 2. 进行刷新访问令牌 + try { + const refreshTokenRes = await refreshToken() + // 2.1 刷新成功,则回放队列的请求 + 当前请求 + setToken((await refreshTokenRes).data.data) + config.headers!.Authorization = 'Bearer ' + getAccessToken() + requestList.forEach((cb: any) => { + cb() + }) + requestList = [] + return service(config) + } catch (e) { + // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 + // 2.2 刷新失败,只回放队列的请求 + requestList.forEach((cb: any) => { + cb() + }) + // 提示是否要登出。即不回放当前请求!不然会形成递归 + return handleAuthorized() + } finally { + requestList = [] + isRefreshToken = false + } + } else { + // 添加到队列,等待刷新获取到新的令牌 + return new Promise((resolve) => { + requestList.push(() => { + config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + resolve(service(config)) + }) + }) + } + } else if (code === 500) { + ElMessage.error(t('sys.api.errMsg500')) + return Promise.reject(new Error(msg)) + } else if (code === 901) { + ElMessage.error({ + offset: 300, + dangerouslyUseHTMLString: true, + message: + '
' + + t('sys.api.errMsg901') + + '
' + + '
 
' + + '
参考 https://doc.iocoder.cn/ 教程
' + + '
 
' + + '
5 分钟搭建本地环境
' + }) + return Promise.reject(new Error(msg)) + } else if (code !== 200) { + if (msg === '无效的刷新令牌') { + // hard coding:忽略这个提示,直接登出 + console.log(msg) + return handleAuthorized() + } else { + ElNotification.error({ title: msg }) + } + return Promise.reject('error') + } else { + return data + } + }, + (error: AxiosError) => { + console.log('err' + error) // for debug + let { message } = error + const { t } = useI18n() + if (message === 'Network Error') { + message = t('sys.api.errorMessage') + } else if (message.includes('timeout')) { + message = t('sys.api.apiTimeoutMessage') + } else if (message.includes('Request failed with status code')) { + message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3) + } + ElMessage.error(message) + return Promise.reject(error) + } +) + +const refreshToken = async () => { + axios.defaults.headers.common['tenant-id'] = getTenantId() + return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken()) +} +const handleAuthorized = () => { + const { t } = useI18n() + if (!isRelogin.show) { + isRelogin.show = true + ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), { + showCancelButton: false, + closeOnClickModal: false, + showClose: false, + closeOnPressEscape: false, + confirmButtonText: t('login.relogin'), + type: 'warning' + }).then(() => { + resetRouter() // 重置静态路由表 + deleteUserCache() // 删除用户缓存 + removeToken() + isRelogin.show = false + // 干掉token后再走一次路由让它过router.beforeEach的校验 + window.location.href = window.location.href + }) + } + return Promise.reject(t('sys.api.timeoutMessage')) +} +export { service } diff --git a/src/directives/index.ts b/src/directives/index.ts new file mode 100644 index 0000000..1b99988 --- /dev/null +++ b/src/directives/index.ts @@ -0,0 +1,24 @@ +import type { App } from 'vue' +import { hasRole } from './permission/hasRole' +import { hasPermi } from './permission/hasPermi' + +/** + * 导出指令:v-xxx + * @methods hasRole 用户权限,用法: v-hasRole + * @methods hasPermi 按钮权限,用法: v-hasPermi + */ +export const setupAuth = (app: App) => { + hasRole(app) + hasPermi(app) +} + +/** + * 导出指令:v-mountedFocus + */ +export const setupMountedFocus = (app: App) => { + app.directive('mountedFocus', { + mounted(el) { + el.focus() + } + }) +} diff --git a/src/directives/permission/hasPermi.ts b/src/directives/permission/hasPermi.ts new file mode 100644 index 0000000..02e2fbc --- /dev/null +++ b/src/directives/permission/hasPermi.ts @@ -0,0 +1,31 @@ +import type { App } from 'vue' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' + +const { t } = useI18n() // 国际化 + +export function hasPermi(app: App) { + app.directive('hasPermi', (el, binding) => { + const { value } = binding + + if (value && value instanceof Array && value.length > 0) { + const hasPermissions = hasPermission(value) + + if (!hasPermissions) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + throw new Error(t('permission.hasPermission')) + } + }) +} + +export const hasPermission = (permission: string[]) => { + const { wsCache } = useCache() + const all_permission = '*:*:*' + const userInfo = wsCache.get(CACHE_KEY.USER) + const permissions = userInfo?.permissions || [] + + return permissions.some((p: string) => { + return all_permission === p || permission.includes(p) + }) +} \ No newline at end of file diff --git a/src/directives/permission/hasRole.ts b/src/directives/permission/hasRole.ts new file mode 100644 index 0000000..a512811 --- /dev/null +++ b/src/directives/permission/hasRole.ts @@ -0,0 +1,28 @@ +import type { App } from 'vue' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' + +const { t } = useI18n() // 国际化 + +export function hasRole(app: App) { + app.directive('hasRole', (el, binding) => { + const { wsCache } = useCache() + const { value } = binding + const super_admin = 'super_admin' + const userInfo = wsCache.get(CACHE_KEY.USER) + const roles = userInfo?.roles || [] + + if (value && value instanceof Array && value.length > 0) { + const roleFlag = value + + const hasRole = roles.some((role: string) => { + return super_admin === role || roleFlag.includes(role) + }) + + if (!hasRole) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + throw new Error(t('permission.hasRole')) + } + }) +} diff --git a/src/hooks/event/useScrollTo.ts b/src/hooks/event/useScrollTo.ts new file mode 100644 index 0000000..92aec87 --- /dev/null +++ b/src/hooks/event/useScrollTo.ts @@ -0,0 +1,60 @@ +export interface ScrollToParams { + el: HTMLElement + to: number + position: string + duration?: number + callback?: () => void +} + +const easeInOutQuad = (t: number, b: number, c: number, d: number) => { + t /= d / 2 + if (t < 1) { + return (c / 2) * t * t + b + } + t-- + return (-c / 2) * (t * (t - 2) - 1) + b +} +const move = (el: HTMLElement, position: string, amount: number) => { + el[position] = amount +} + +export function useScrollTo({ + el, + position = 'scrollLeft', + to, + duration = 500, + callback +}: ScrollToParams) { + const isActiveRef = ref(false) + const start = el[position] + const change = to - start + const increment = 20 + let currentTime = 0 + + function animateScroll() { + if (!unref(isActiveRef)) { + return + } + currentTime += increment + const val = easeInOutQuad(currentTime, start, change, duration) + move(el, position, val) + if (currentTime < duration && unref(isActiveRef)) { + requestAnimationFrame(animateScroll) + } else { + if (callback) { + callback() + } + } + } + + function run() { + isActiveRef.value = true + animateScroll() + } + + function stop() { + isActiveRef.value = false + } + + return { start: run, stop } +} diff --git a/src/hooks/web/useCache.ts b/src/hooks/web/useCache.ts new file mode 100644 index 0000000..4f39f30 --- /dev/null +++ b/src/hooks/web/useCache.ts @@ -0,0 +1,39 @@ +/** + * 配置浏览器本地存储的方式,可直接存储对象数组。 + */ + +import WebStorageCache from 'web-storage-cache' + +type CacheType = 'localStorage' | 'sessionStorage' + +export const CACHE_KEY = { + // 用户相关 + ROLE_ROUTERS: 'roleRouters', + USER: 'user', + // 系统设置 + IS_DARK: 'isDark', + LANG: 'lang', + THEME: 'theme', + LAYOUT: 'layout', + DICT_CACHE: 'dictCache', + // 登录表单 + LoginForm: 'loginForm', + TenantId: 'tenantId' +} + +export const useCache = (type: CacheType = 'localStorage') => { + const wsCache: WebStorageCache = new WebStorageCache({ + storage: type + }) + + return { + wsCache + } +} + +export const deleteUserCache = () => { + const { wsCache } = useCache() + wsCache.delete(CACHE_KEY.USER) + wsCache.delete(CACHE_KEY.ROLE_ROUTERS) + // 注意,不要清理 LoginForm 登录表单 +} diff --git a/src/hooks/web/useConfigGlobal.ts b/src/hooks/web/useConfigGlobal.ts new file mode 100644 index 0000000..afb3db3 --- /dev/null +++ b/src/hooks/web/useConfigGlobal.ts @@ -0,0 +1,9 @@ +import { ConfigGlobalTypes } from '@/types/configGlobal' + +export const useConfigGlobal = () => { + const configGlobal = inject('configGlobal', {}) as ConfigGlobalTypes + + return { + configGlobal + } +} diff --git a/src/hooks/web/useCrudSchemas.ts b/src/hooks/web/useCrudSchemas.ts new file mode 100644 index 0000000..458b57e --- /dev/null +++ b/src/hooks/web/useCrudSchemas.ts @@ -0,0 +1,326 @@ +import { reactive } from 'vue' +import { AxiosPromise } from 'axios' +import { findIndex } from '@/utils' +import { eachTree, filter, treeMap } from '@/utils/tree' +import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict' + +import { FormSchema } from '@/types/form' +import { TableColumn } from '@/types/table' +import { DescriptionsSchema } from '@/types/descriptions' +import { ComponentOptions, ComponentProps } from '@/types/components' +import { DictTag } from '@/components/DictTag' +import { cloneDeep, merge } from 'lodash-es' + +export type CrudSchema = Omit & { + isSearch?: boolean // 是否在查询显示 + search?: CrudSearchParams // 查询的详细配置 + isTable?: boolean // 是否在列表显示 + table?: CrudTableParams // 列表的详细配置 + isForm?: boolean // 是否在表单显示 + form?: CrudFormParams // 表单的详细配置 + isDetail?: boolean // 是否在详情显示 + detail?: CrudDescriptionsParams // 详情的详细配置 + children?: CrudSchema[] + dictType?: string // 字典类型 + dictClass?: 'string' | 'number' | 'boolean' // 字典数据类型 string | number | boolean +} + +type CrudSearchParams = { + // 是否显示在查询项 + show?: boolean + // 接口 + api?: () => Promise + // 搜索字段 + field?: string +} & Omit + +type CrudTableParams = { + // 是否显示表头 + show?: boolean + // 列宽配置 + width?: number | string + // 列是否固定在左侧或者右侧 + fixed?: 'left' | 'right' +} & Omit +type CrudFormParams = { + // 是否显示表单项 + show?: boolean + // 接口 + api?: () => Promise +} & Omit + +type CrudDescriptionsParams = { + // 是否显示表单项 + show?: boolean +} & Omit + +interface AllSchemas { + searchSchema: FormSchema[] + tableColumns: TableColumn[] + formSchema: FormSchema[] + detailSchema: DescriptionsSchema[] +} + +const { t } = useI18n() + +// 过滤所有结构 +export const useCrudSchemas = ( + crudSchema: CrudSchema[] +): { + allSchemas: AllSchemas +} => { + // 所有结构数据 + const allSchemas = reactive({ + searchSchema: [], + tableColumns: [], + formSchema: [], + detailSchema: [] + }) + + const searchSchema = filterSearchSchema(crudSchema, allSchemas) + allSchemas.searchSchema = searchSchema || [] + + const tableColumns = filterTableSchema(crudSchema) + allSchemas.tableColumns = tableColumns || [] + + const formSchema = filterFormSchema(crudSchema, allSchemas) + allSchemas.formSchema = formSchema + + const detailSchema = filterDescriptionsSchema(crudSchema) + allSchemas.detailSchema = detailSchema + + return { + allSchemas + } +} + +// 过滤 Search 结构 +const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { + const searchSchema: FormSchema[] = [] + + // 获取字典列表队列 + const searchRequestTask: Array<() => Promise> = [] + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.isSearch || schemaItem.search?.show) { + let component = schemaItem?.search?.component || 'Input' + const options: ComponentOptions[] = [] + let comonentProps: ComponentProps = {} + if (schemaItem.dictType) { + const allOptions: ComponentOptions = { label: '全部', value: '' } + options.push(allOptions) + getDictOptions(schemaItem.dictType).forEach((dict) => { + options.push(dict) + }) + comonentProps = { + options: options + } + if (!schemaItem.search?.component) component = 'Select' + } + + // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题 + const searchSchemaItem = merge( + { + // 默认为 input + component, + ...schemaItem.search, + field: schemaItem.field, + label: schemaItem.search?.label || schemaItem.label + }, + { componentProps: comonentProps } + ) + if (searchSchemaItem.api) { + searchRequestTask.push(async () => { + const res = await (searchSchemaItem.api as () => AxiosPromise)() + if (res) { + const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => { + return v.field === searchSchemaItem.field + }) + if (index !== -1) { + allSchemas.searchSchema[index]!.componentProps!.options = filterOptions( + res, + searchSchemaItem.componentProps.optionsAlias?.labelField + ) + } + } + }) + } + // 删除不必要的字段 + delete searchSchemaItem.show + + searchSchema.push(searchSchemaItem) + } + }) + for (const task of searchRequestTask) { + task() + } + return searchSchema +} + +// 过滤 table 结构 +const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => { + const tableColumns = treeMap(crudSchema, { + conversion: (schema: CrudSchema) => { + if (schema?.isTable !== false && schema?.table?.show !== false) { + // add by 芋艿:增加对 dict 字典数据的支持 + if (!schema.formatter && schema.dictType) { + schema.formatter = (_: Recordable, __: TableColumn, cellValue: any) => { + return h(DictTag, { + type: schema.dictType!, // ! 表示一定不为空 + value: cellValue + }) + } + } + return { + ...schema.table, + ...schema + } + } + } + }) + + // 第一次过滤会有 undefined 所以需要二次过滤 + return filter(tableColumns as TableColumn[], (data) => { + if (data.children === void 0) { + delete data.children + } + return !!data.field + }) +} + +// 过滤 form 结构 +const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { + const formSchema: FormSchema[] = [] + + // 获取字典列表队列 + const formRequestTask: Array<() => Promise> = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) { + let component = schemaItem?.form?.component || 'Input' + let defaultValue: any = '' + if (schemaItem.form?.value) { + defaultValue = schemaItem.form?.value + } else { + if (component === 'InputNumber') { + defaultValue = 0 + } + } + let comonentProps: ComponentProps = {} + if (schemaItem.dictType) { + const options: ComponentOptions[] = [] + if (schemaItem.dictClass && schemaItem.dictClass === 'number') { + getIntDictOptions(schemaItem.dictType).forEach((dict) => { + options.push(dict) + }) + } else if (schemaItem.dictClass && schemaItem.dictClass === 'boolean') { + getBoolDictOptions(schemaItem.dictType).forEach((dict) => { + options.push(dict) + }) + } else { + getDictOptions(schemaItem.dictType).forEach((dict) => { + options.push(dict) + }) + } + comonentProps = { + options: options + } + if (!(schemaItem.form && schemaItem.form.component)) component = 'Select' + } + + // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题 + const formSchemaItem = merge( + { + // 默认为 input + component, + value: defaultValue, + ...schemaItem.form, + field: schemaItem.field, + label: schemaItem.form?.label || schemaItem.label + }, + { componentProps: comonentProps } + ) + + if (formSchemaItem.api) { + formRequestTask.push(async () => { + const res = await (formSchemaItem.api as () => AxiosPromise)() + if (res) { + const index = findIndex(allSchemas.formSchema, (v: FormSchema) => { + return v.field === formSchemaItem.field + }) + if (index !== -1) { + allSchemas.formSchema[index]!.componentProps!.options = filterOptions( + res, + formSchemaItem.componentProps.optionsAlias?.labelField + ) + } + } + }) + } + + // 删除不必要的字段 + delete formSchemaItem.show + + formSchema.push(formSchemaItem) + } + }) + + for (const task of formRequestTask) { + task() + } + return formSchema +} + +// 过滤 descriptions 结构 +const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => { + const descriptionsSchema: FormSchema[] = [] + + eachTree(crudSchema, (schemaItem: CrudSchema) => { + // 判断是否显示 + if (schemaItem?.isDetail !== false && schemaItem.detail?.show !== false) { + const descriptionsSchemaItem = { + ...schemaItem.detail, + field: schemaItem.field, + label: schemaItem.detail?.label || schemaItem.label + } + if (schemaItem.dictType) { + descriptionsSchemaItem.dictType = schemaItem.dictType + } + if (schemaItem.detail?.dateFormat || schemaItem.formatter == 'formatDate') { + // 优先使用 detail 下的配置,如果没有默认为 YYYY-MM-DD HH:mm:ss + descriptionsSchemaItem.dateFormat = schemaItem?.detail?.dateFormat + ? schemaItem?.detail?.dateFormat + : 'YYYY-MM-DD HH:mm:ss' + } + + // 删除不必要的字段 + delete descriptionsSchemaItem.show + + descriptionsSchema.push(descriptionsSchemaItem) + } + }) + + return descriptionsSchema +} + +// 给options添加国际化 +const filterOptions = (options: Recordable, labelField?: string) => { + return options?.map((v: Recordable) => { + if (labelField) { + v['labelField'] = t(v.labelField) + } else { + v['label'] = t(v.label) + } + return v + }) +} + +// 将 tableColumns 指定 fields 放到最前面 +export const sortTableColumns = (tableColumns: TableColumn[], field: string) => { + const fieldIndex = tableColumns.findIndex((item) => item.field === field) + const fieldColumn = cloneDeep(tableColumns[fieldIndex]) + tableColumns.splice(fieldIndex, 1) + // 添加到开头 + tableColumns.unshift(fieldColumn) +} diff --git a/src/hooks/web/useDesign.ts b/src/hooks/web/useDesign.ts new file mode 100644 index 0000000..8ee3b38 --- /dev/null +++ b/src/hooks/web/useDesign.ts @@ -0,0 +1,18 @@ +import variables from '@/styles/global.module.scss' + +export const useDesign = () => { + const scssVariables = variables + + /** + * @param scope 类名 + * @returns 返回空间名-类名 + */ + const getPrefixCls = (scope: string) => { + return `${scssVariables.namespace}-${scope}` + } + + return { + variables: scssVariables, + getPrefixCls + } +} diff --git a/src/hooks/web/useEmitt.ts b/src/hooks/web/useEmitt.ts new file mode 100644 index 0000000..d4efea7 --- /dev/null +++ b/src/hooks/web/useEmitt.ts @@ -0,0 +1,22 @@ +import mitt from 'mitt' + +interface Option { + name: string // 事件名称 + callback: Fn // 回调 +} + +const emitter = mitt() + +export const useEmitt = (option?: Option) => { + if (option) { + emitter.on(option.name, option.callback) + + onBeforeUnmount(() => { + emitter.off(option.name) + }) + } + + return { + emitter + } +} diff --git a/src/hooks/web/useForm.ts b/src/hooks/web/useForm.ts new file mode 100644 index 0000000..53a8a94 --- /dev/null +++ b/src/hooks/web/useForm.ts @@ -0,0 +1,94 @@ +import type { Form, FormExpose } from '@/components/Form' +import type { ElForm } from 'element-plus' +import type { FormProps } from '@/components/Form/src/types' +import { FormSchema, FormSetPropsType } from '@/types/form' + +export const useForm = (props?: FormProps) => { + // From实例 + const formRef = ref() + + // ElForm实例 + const elFormRef = ref>() + + /** + * @param ref Form实例 + * @param elRef ElForm实例 + */ + const register = (ref: typeof Form & FormExpose, elRef: ComponentRef) => { + formRef.value = ref + elFormRef.value = elRef + } + + const getForm = async () => { + await nextTick() + const form = unref(formRef) + if (!form) { + console.error('The form is not registered. Please use the register method to register') + } + return form + } + + // 一些内置的方法 + const methods: { + setProps: (props: Recordable) => void + setValues: (data: Recordable) => void + getFormData: () => Promise + setSchema: (schemaProps: FormSetPropsType[]) => void + addSchema: (formSchema: FormSchema, index?: number) => void + delSchema: (field: string) => void + } = { + setProps: async (props: FormProps = {}) => { + const form = await getForm() + form?.setProps(props) + if (props.model) { + form?.setValues(props.model) + } + }, + + setValues: async (data: Recordable) => { + const form = await getForm() + form?.setValues(data) + }, + + /** + * @param schemaProps 需要设置的schemaProps + */ + setSchema: async (schemaProps: FormSetPropsType[]) => { + const form = await getForm() + form?.setSchema(schemaProps) + }, + + /** + * @param formSchema 需要新增数据 + * @param index 在哪里新增 + */ + addSchema: async (formSchema: FormSchema, index?: number) => { + const form = await getForm() + form?.addSchema(formSchema, index) + }, + + /** + * @param field 删除哪个数据 + */ + delSchema: async (field: string) => { + const form = await getForm() + form?.delSchema(field) + }, + + /** + * @returns form data + */ + getFormData: async (): Promise => { + const form = await getForm() + return form?.formModel as T + } + } + + props && methods.setProps(props) + + return { + register, + elFormRef, + methods + } +} diff --git a/src/hooks/web/useGuide.ts b/src/hooks/web/useGuide.ts new file mode 100644 index 0000000..7fd2fb0 --- /dev/null +++ b/src/hooks/web/useGuide.ts @@ -0,0 +1,49 @@ +import { Config, driver } from 'driver.js' +import 'driver.js/dist/driver.css' +import { useDesign } from '@/hooks/web/useDesign' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +const { variables } = useDesign() + +export const useGuide = (options?: Config) => { + const driverObj = driver( + options || { + showProgress: true, + nextBtnText: t('common.nextLabel'), + prevBtnText: t('common.prevLabel'), + doneBtnText: t('common.doneLabel'), + steps: [ + { + element: `#${variables.namespace}-menu`, + popover: { + title: t('common.menu'), + description: t('common.menuDes'), + side: 'right' + } + }, + { + element: `#${variables.namespace}-tool-header`, + popover: { + title: t('common.tool'), + description: t('common.toolDes'), + side: 'left' + } + }, + { + element: `#${variables.namespace}-tags-view`, + popover: { + title: t('common.tagsView'), + description: t('common.tagsViewDes'), + side: 'bottom' + } + } + ] + } + ) + + return { + ...driverObj + } +} diff --git a/src/hooks/web/useI18n.ts b/src/hooks/web/useI18n.ts new file mode 100644 index 0000000..d1ab70f --- /dev/null +++ b/src/hooks/web/useI18n.ts @@ -0,0 +1,53 @@ +import { i18n } from '@/plugins/vueI18n' + +type I18nGlobalTranslation = { + (key: string): string + (key: string, locale: string): string + (key: string, locale: string, list: unknown[]): string + (key: string, locale: string, named: Record): string + (key: string, list: unknown[]): string + (key: string, named: Record): string +} + +type I18nTranslationRestParameters = [string, any] + +const getKey = (namespace: string | undefined, key: string) => { + if (!namespace) { + return key + } + if (key.startsWith(namespace)) { + return key + } + return `${namespace}.${key}` +} + +export const useI18n = ( + namespace?: string +): { + t: I18nGlobalTranslation +} => { + const normalFn = { + t: (key: string) => { + return getKey(namespace, key) + } + } + + if (!i18n) { + return normalFn + } + + const { t, ...methods } = i18n.global + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) return '' + if (!key.includes('.') && !namespace) return key + //@ts-ignore + return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) + } + return { + ...methods, + t: tFn + } +} + +export const t = (key: string) => key diff --git a/src/hooks/web/useIcon.ts b/src/hooks/web/useIcon.ts new file mode 100644 index 0000000..3500204 --- /dev/null +++ b/src/hooks/web/useIcon.ts @@ -0,0 +1,8 @@ +import { h } from 'vue' +import type { VNode } from 'vue' +import { Icon } from '@/components/Icon' +import { IconTypes } from '@/types/icon' + +export const useIcon = (props: IconTypes): VNode => { + return h(Icon, props) +} diff --git a/src/hooks/web/useLocale.ts b/src/hooks/web/useLocale.ts new file mode 100644 index 0000000..c65070e --- /dev/null +++ b/src/hooks/web/useLocale.ts @@ -0,0 +1,35 @@ +import { i18n } from '@/plugins/vueI18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import { setHtmlPageLang } from '@/plugins/vueI18n/helper' + +const setI18nLanguage = (locale: LocaleType) => { + const localeStore = useLocaleStoreWithOut() + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale + } else { + ;(i18n.global.locale as any).value = locale + } + localeStore.setCurrentLocale({ + lang: locale + }) + setHtmlPageLang(locale) +} + +export const useLocale = () => { + // Switching the language will change the locale of useI18n + // And submit to configuration modification + const changeLocale = async (locale: LocaleType) => { + const globalI18n = i18n.global + + const langModule = await import(`../../locales/${locale}.ts`) + + globalI18n.setLocaleMessage(locale, langModule.default) + + setI18nLanguage(locale) + } + + return { + changeLocale + } +} diff --git a/src/hooks/web/useMessage.ts b/src/hooks/web/useMessage.ts new file mode 100644 index 0000000..ac2b552 --- /dev/null +++ b/src/hooks/web/useMessage.ts @@ -0,0 +1,95 @@ +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' +import { useI18n } from './useI18n' +export const useMessage = () => { + const { t } = useI18n() + return { + // 消息提示 + info(content: string) { + ElMessage.info(content) + }, + // 错误消息 + error(content: string) { + ElMessage.error(content) + }, + // 成功消息 + success(content: string) { + ElMessage.success(content) + }, + // 警告消息 + warning(content: string) { + ElMessage.warning(content) + }, + // 弹出提示 + alert(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle')) + }, + // 错误提示 + alertError(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'error' }) + }, + // 成功提示 + alertSuccess(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'success' }) + }, + // 警告提示 + alertWarning(content: string) { + ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'warning' }) + }, + // 通知提示 + notify(content: string) { + ElNotification.info(content) + }, + // 错误通知 + notifyError(content: string) { + ElNotification.error(content) + }, + // 成功通知 + notifySuccess(content: string) { + ElNotification.success(content) + }, + // 警告通知 + notifyWarning(content: string) { + ElNotification.warning(content) + }, + // 确认窗体 + confirm(content: string, tip?: string) { + return ElMessageBox.confirm(content, tip ? tip : t('common.confirmTitle'), { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + }, + // 删除窗体 + delConfirm(content?: string, tip?: string) { + return ElMessageBox.confirm( + content ? content : t('common.delMessage'), + tip ? tip : t('common.confirmTitle'), + { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + } + ) + }, + // 导出窗体 + exportConfirm(content?: string, tip?: string) { + return ElMessageBox.confirm( + content ? content : t('common.exportMessage'), + tip ? tip : t('common.confirmTitle'), + { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + } + ) + }, + // 提交内容 + prompt(content: string, tip: string) { + return ElMessageBox.prompt(content, tip, { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + } + } +} diff --git a/src/hooks/web/useNProgress.ts b/src/hooks/web/useNProgress.ts new file mode 100644 index 0000000..6d8c0b9 --- /dev/null +++ b/src/hooks/web/useNProgress.ts @@ -0,0 +1,33 @@ +import { useCssVar } from '@vueuse/core' +import type { NProgressOptions } from 'nprogress' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' + +const primaryColor = useCssVar('--el-color-primary', document.documentElement) + +export const useNProgress = () => { + NProgress.configure({ showSpinner: false } as NProgressOptions) + + const initColor = async () => { + await nextTick() + const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef + if (bar) { + bar.style.background = unref(primaryColor.value) + } + } + + initColor() + + const start = () => { + NProgress.start() + } + + const done = () => { + NProgress.done() + } + + return { + start, + done + } +} diff --git a/src/hooks/web/useNetwork.ts b/src/hooks/web/useNetwork.ts new file mode 100644 index 0000000..66fa446 --- /dev/null +++ b/src/hooks/web/useNetwork.ts @@ -0,0 +1,21 @@ +import { ref, onBeforeUnmount } from 'vue' + +const useNetwork = () => { + const online = ref(true) + + const updateNetwork = () => { + online.value = navigator.onLine + } + + window.addEventListener('online', updateNetwork) + window.addEventListener('offline', updateNetwork) + + onBeforeUnmount(() => { + window.removeEventListener('online', updateNetwork) + window.removeEventListener('offline', updateNetwork) + }) + + return { online } +} + +export { useNetwork } diff --git a/src/hooks/web/useNow.ts b/src/hooks/web/useNow.ts new file mode 100644 index 0000000..09d3176 --- /dev/null +++ b/src/hooks/web/useNow.ts @@ -0,0 +1,60 @@ +import { dateUtil } from '@/utils/dateUtil' +import { reactive, toRefs } from 'vue' +import { tryOnMounted, tryOnUnmounted } from '@vueuse/core' + +export const useNow = (immediate = true) => { + let timer: IntervalHandle + + const state = reactive({ + year: 0, + month: 0, + week: '', + day: 0, + hour: '', + minute: '', + second: 0, + meridiem: '' + }) + + const update = () => { + const now = dateUtil() + + const h = now.format('HH') + const m = now.format('mm') + const s = now.get('s') + + state.year = now.get('y') + state.month = now.get('M') + 1 + state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()] + state.day = now.get('date') + state.hour = h + state.minute = m + state.second = s + + state.meridiem = now.format('A') + } + + function start() { + update() + clearInterval(timer) + timer = setInterval(() => update(), 1000) + } + + function stop() { + clearInterval(timer) + } + + tryOnMounted(() => { + immediate && start() + }) + + tryOnUnmounted(() => { + stop() + }) + + return { + ...toRefs(state), + start, + stop + } +} diff --git a/src/hooks/web/usePageLoading.ts b/src/hooks/web/usePageLoading.ts new file mode 100644 index 0000000..bb89457 --- /dev/null +++ b/src/hooks/web/usePageLoading.ts @@ -0,0 +1,18 @@ +import { useAppStoreWithOut } from '@/store/modules/app' + +const appStore = useAppStoreWithOut() + +export const usePageLoading = () => { + const loadStart = () => { + appStore.setPageLoading(true) + } + + const loadDone = () => { + appStore.setPageLoading(false) + } + + return { + loadStart, + loadDone + } +} diff --git a/src/hooks/web/useTable.ts b/src/hooks/web/useTable.ts new file mode 100644 index 0000000..361dd67 --- /dev/null +++ b/src/hooks/web/useTable.ts @@ -0,0 +1,223 @@ +import download from '@/utils/download' +import { Table, TableExpose } from '@/components/Table' +import { ElMessage, ElMessageBox, ElTable } from 'element-plus' +import { computed, nextTick, reactive, ref, unref, watch } from 'vue' +import type { TableProps } from '@/components/Table/src/types' + +import { TableSetPropsType } from '@/types/table' + +const { t } = useI18n() +interface ResponseType { + list: T[] + total?: number +} + +interface UseTableConfig { + getListApi: (option: any) => Promise + delListApi?: (option: any) => Promise + exportListApi?: (option: any) => Promise + // 返回数据格式配置 + response?: ResponseType + // 默认传递的参数 + defaultParams?: Recordable + props?: TableProps +} + +interface TableObject { + pageSize: number + currentPage: number + total: number + tableList: T[] + params: any + loading: boolean + exportLoading: boolean + currentRow: Nullable +} + +export const useTable = (config?: UseTableConfig) => { + const tableObject = reactive>({ + // 页数 + pageSize: 10, + // 当前页 + currentPage: 1, + // 总条数 + total: 10, + // 表格数据 + tableList: [], + // AxiosConfig 配置 + params: { + ...(config?.defaultParams || {}) + }, + // 加载中 + loading: true, + // 导出加载中 + exportLoading: false, + // 当前行的数据 + currentRow: null + }) + + const paramsObj = computed(() => { + return { + ...tableObject.params, + pageSize: tableObject.pageSize, + pageNo: tableObject.currentPage + } + }) + + watch( + () => tableObject.currentPage, + () => { + methods.getList() + } + ) + + watch( + () => tableObject.pageSize, + () => { + // 当前页不为1时,修改页数后会导致多次调用getList方法 + if (tableObject.currentPage === 1) { + methods.getList() + } else { + tableObject.currentPage = 1 + methods.getList() + } + } + ) + + // Table实例 + const tableRef = ref() + + // ElTable实例 + const elTableRef = ref>() + + const register = (ref: typeof Table & TableExpose, elRef: ComponentRef) => { + tableRef.value = ref + elTableRef.value = elRef + } + + const getTable = async () => { + await nextTick() + const table = unref(tableRef) + if (!table) { + console.error('The table is not registered. Please use the register method to register') + } + return table + } + + const delData = async (ids: string | number | string[] | number[]) => { + let idsLength = 1 + if (ids instanceof Array) { + idsLength = ids.length + await Promise.all( + ids.map(async (id: string | number) => { + await (config?.delListApi && config?.delListApi(id)) + }) + ) + } else { + await (config?.delListApi && config?.delListApi(ids)) + } + ElMessage.success(t('common.delSuccess')) + + // 计算出临界点 + tableObject.currentPage = + tableObject.total % tableObject.pageSize === idsLength || tableObject.pageSize === 1 + ? tableObject.currentPage > 1 + ? tableObject.currentPage - 1 + : tableObject.currentPage + : tableObject.currentPage + await methods.getList() + } + + const methods = { + getList: async () => { + tableObject.loading = true + const res = await config?.getListApi(unref(paramsObj)).finally(() => { + tableObject.loading = false + }) + if (res) { + tableObject.tableList = (res as unknown as ResponseType).list + tableObject.total = (res as unknown as ResponseType).total ?? 0 + } + }, + setProps: async (props: TableProps = {}) => { + const table = await getTable() + table?.setProps(props) + }, + setColumn: async (columnProps: TableSetPropsType[]) => { + const table = await getTable() + table?.setColumn(columnProps) + }, + getSelections: async () => { + const table = await getTable() + return (table?.selections || []) as T[] + }, + // 与Search组件结合 + setSearchParams: (data: Recordable) => { + tableObject.params = Object.assign(tableObject.params, { + pageSize: tableObject.pageSize, + pageNo: 1, + ...data + }) + // 页码不等于1时更新页码重新获取数据,页码等于1时重新获取数据 + if (tableObject.currentPage !== 1) { + tableObject.currentPage = 1 + } else { + methods.getList() + } + }, + // 删除数据 + delList: async ( + ids: string | number | string[] | number[], + multiple: boolean, + message = true + ) => { + const tableRef = await getTable() + if (multiple) { + if (!tableRef?.selections.length) { + ElMessage.warning(t('common.delNoData')) + return + } + } + if (message) { + ElMessageBox.confirm(t('common.delMessage'), t('common.confirmTitle'), { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }).then(async () => { + await delData(ids) + }) + } else { + await delData(ids) + } + }, + // 导出列表 + exportList: async (fileName: string) => { + tableObject.exportLoading = true + ElMessageBox.confirm(t('common.exportMessage'), t('common.confirmTitle'), { + confirmButtonText: t('common.ok'), + cancelButtonText: t('common.cancel'), + type: 'warning' + }) + .then(async () => { + const res = await config?.exportListApi?.(unref(paramsObj) as unknown as T) + if (res) { + download.excel(res as unknown as Blob, fileName) + } + }) + .finally(() => { + tableObject.exportLoading = false + }) + } + } + + config?.props && methods.setProps(config.props) + + return { + register, + elTableRef, + tableObject, + methods, + // add by 芋艿:返回 tableMethods 属性,和 tableObject 更统一 + tableMethods: methods + } +} diff --git a/src/hooks/web/useTagsView.ts b/src/hooks/web/useTagsView.ts new file mode 100644 index 0000000..31eadb0 --- /dev/null +++ b/src/hooks/web/useTagsView.ts @@ -0,0 +1,63 @@ +import { useTagsViewStoreWithOut } from '@/store/modules/tagsView' +import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router' +import { computed, nextTick, unref } from 'vue' + +export const useTagsView = () => { + const tagsViewStore = useTagsViewStoreWithOut() + + const { replace, currentRoute } = useRouter() + + const selectedTag = computed(() => tagsViewStore.getSelectedTag) + + const closeAll = (callback?: Fn) => { + tagsViewStore.delAllViews() + callback?.() + } + + const closeLeft = (callback?: Fn) => { + tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeRight = (callback?: Fn) => { + tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeOther = (callback?: Fn) => { + tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded) + callback?.() + } + + const closeCurrent = (view?: RouteLocationNormalizedLoaded, callback?: Fn) => { + if (view?.meta?.affix) return + tagsViewStore.delView(view || unref(currentRoute)) + + callback?.() + } + + const refreshPage = async (view?: RouteLocationNormalizedLoaded, callback?: Fn) => { + tagsViewStore.delCachedView() + const { path, query } = view || unref(currentRoute) + await nextTick() + replace({ + path: '/redirect' + path, + query: query + }) + callback?.() + } + + const setTitle = (title: string, path?: string) => { + tagsViewStore.setTitle(title, path) + } + + return { + closeAll, + closeLeft, + closeRight, + closeOther, + closeCurrent, + refreshPage, + setTitle + } +} diff --git a/src/hooks/web/useTimeAgo.ts b/src/hooks/web/useTimeAgo.ts new file mode 100644 index 0000000..a6da281 --- /dev/null +++ b/src/hooks/web/useTimeAgo.ts @@ -0,0 +1,49 @@ +import { useTimeAgo as useTimeAgoCore, UseTimeAgoMessages } from '@vueuse/core' +import { useLocaleStoreWithOut } from '@/store/modules/locale' + +const TIME_AGO_MESSAGE_MAP: { + 'zh-CN': UseTimeAgoMessages + en: UseTimeAgoMessages +} = { + // @ts-ignore + 'zh-CN': { + justNow: '刚刚', + past: (n) => (n.match(/\d/) ? `${n}前` : n), + future: (n) => (n.match(/\d/) ? `${n}后` : n), + month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`), + year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`), + day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`), + week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`), + hour: (n) => `${n} 小时`, + minute: (n) => `${n} 分钟`, + second: (n) => `${n} 秒` + }, + // @ts-ignore + en: { + justNow: 'just now', + past: (n) => (n.match(/\d/) ? `${n} ago` : n), + future: (n) => (n.match(/\d/) ? `in ${n}` : n), + month: (n, past) => + n === 1 ? (past ? 'last month' : 'next month') : `${n} month${n > 1 ? 's' : ''}`, + year: (n, past) => + n === 1 ? (past ? 'last year' : 'next year') : `${n} year${n > 1 ? 's' : ''}`, + day: (n, past) => (n === 1 ? (past ? 'yesterday' : 'tomorrow') : `${n} day${n > 1 ? 's' : ''}`), + week: (n, past) => + n === 1 ? (past ? 'last week' : 'next week') : `${n} week${n > 1 ? 's' : ''}`, + hour: (n) => `${n} hour${n > 1 ? 's' : ''}`, + minute: (n) => `${n} minute${n > 1 ? 's' : ''}`, + second: (n) => `${n} second${n > 1 ? 's' : ''}` + } +} + +export const useTimeAgo = (time: Date | number | string) => { + const localeStore = useLocaleStoreWithOut() + + const currentLocale = computed(() => localeStore.getCurrentLocale) + + const timeAgo = useTimeAgoCore(time, { + messages: TIME_AGO_MESSAGE_MAP[unref(currentLocale).lang] + }) + + return timeAgo +} diff --git a/src/hooks/web/useTitle.ts b/src/hooks/web/useTitle.ts new file mode 100644 index 0000000..020a9b7 --- /dev/null +++ b/src/hooks/web/useTitle.ts @@ -0,0 +1,24 @@ +import { watch, ref } from 'vue' +import { isString } from '@/utils/is' +import { useAppStoreWithOut } from '@/store/modules/app' + +const appStore = useAppStoreWithOut() + +export const useTitle = (newTitle?: string) => { + const { t } = useI18n() + const title = ref( + newTitle ? `${appStore.getTitle} - ${t(newTitle as string)}` : appStore.getTitle + ) + + watch( + title, + (n, o) => { + if (isString(n) && n !== o && document) { + document.title = n + } + }, + { immediate: true } + ) + + return title +} diff --git a/src/hooks/web/useValidator.ts b/src/hooks/web/useValidator.ts new file mode 100644 index 0000000..151e35b --- /dev/null +++ b/src/hooks/web/useValidator.ts @@ -0,0 +1,60 @@ +import { useI18n } from '@/hooks/web/useI18n' +import { FormItemRule } from 'element-plus' + +const { t } = useI18n() + +interface LengthRange { + min: number + max: number + message?: string +} + +export const useValidator = () => { + const required = (message?: string): FormItemRule => { + return { + required: true, + message: message || t('common.required') + } + } + + const lengthRange = (options: LengthRange): FormItemRule => { + const { min, max, message } = options + + return { + min, + max, + message: message || t('common.lengthRange', { min, max }) + } + } + + const notSpace = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (val?.indexOf(' ') !== -1) { + callback(new Error(message || t('common.notSpace'))) + } else { + callback() + } + } + } + } + + const notSpecialCharacters = (message?: string): FormItemRule => { + return { + validator: (_, val, callback) => { + if (/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(val)) { + callback(new Error(message || t('common.notSpecialCharacters'))) + } else { + callback() + } + } + } + } + + return { + required, + lengthRange, + notSpace, + notSpecialCharacters + } +} diff --git a/src/hooks/web/useWatermark.ts b/src/hooks/web/useWatermark.ts new file mode 100644 index 0000000..4a31359 --- /dev/null +++ b/src/hooks/web/useWatermark.ts @@ -0,0 +1,55 @@ +const domSymbol = Symbol('watermark-dom') + +export function useWatermark(appendEl: HTMLElement | null = document.body) { + let func: Fn = () => {} + const id = domSymbol.toString() + const clear = () => { + const domId = document.getElementById(id) + if (domId) { + const el = appendEl + el && el.removeChild(domId) + } + window.removeEventListener('resize', func) + } + const createWatermark = (str: string) => { + clear() + + const can = document.createElement('canvas') + can.width = 300 + can.height = 240 + + const cans = can.getContext('2d') + if (cans) { + cans.rotate((-20 * Math.PI) / 120) + cans.font = '15px Vedana' + cans.fillStyle = 'rgba(0, 0, 0, 0.15)' + cans.textAlign = 'left' + cans.textBaseline = 'middle' + cans.fillText(str, can.width / 20, can.height) + } + + const div = document.createElement('div') + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '0px' + div.style.left = '0px' + div.style.position = 'absolute' + div.style.zIndex = '100000000' + div.style.width = document.documentElement.clientWidth + 'px' + div.style.height = document.documentElement.clientHeight + 'px' + div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat' + const el = appendEl + el && el.appendChild(div) + return id + } + + function setWatermark(str: string) { + createWatermark(str) + func = () => { + createWatermark(str) + } + window.addEventListener('resize', func) + } + + return { setWatermark, clear } +} diff --git a/src/layout/Layout.vue b/src/layout/Layout.vue new file mode 100644 index 0000000..d15025c --- /dev/null +++ b/src/layout/Layout.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/layout/components/AppView.vue b/src/layout/components/AppView.vue new file mode 100644 index 0000000..df720a1 --- /dev/null +++ b/src/layout/components/AppView.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/layout/components/Breadcrumb/index.ts b/src/layout/components/Breadcrumb/index.ts new file mode 100644 index 0000000..93ffe70 --- /dev/null +++ b/src/layout/components/Breadcrumb/index.ts @@ -0,0 +1,3 @@ +import Breadcrumb from './src/Breadcrumb.vue' + +export { Breadcrumb } diff --git a/src/layout/components/Breadcrumb/src/Breadcrumb.vue b/src/layout/components/Breadcrumb/src/Breadcrumb.vue new file mode 100644 index 0000000..80770a8 --- /dev/null +++ b/src/layout/components/Breadcrumb/src/Breadcrumb.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/layout/components/Breadcrumb/src/helper.ts b/src/layout/components/Breadcrumb/src/helper.ts new file mode 100644 index 0000000..fb3ec19 --- /dev/null +++ b/src/layout/components/Breadcrumb/src/helper.ts @@ -0,0 +1,31 @@ +import { pathResolve } from '@/utils/routerHelper' +import type { RouteMeta } from 'vue-router' + +export const filterBreadcrumb = ( + routes: AppRouteRecordRaw[], + parentPath = '' +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + + for (const route of routes) { + const meta = route?.meta as RouteMeta + if (meta.hidden && !meta.canTo) { + continue + } + + const data: AppRouteRecordRaw = + !meta.alwaysShow && route.children?.length === 1 + ? { ...route.children[0], path: pathResolve(route.path, route.children[0].path) } + : { ...route } + + data.path = pathResolve(parentPath, data.path) + + if (data.children) { + data.children = filterBreadcrumb(data.children, data.path) + } + if (data) { + res.push(data) + } + } + return res +} diff --git a/src/layout/components/Collapse/index.ts b/src/layout/components/Collapse/index.ts new file mode 100644 index 0000000..73f65a3 --- /dev/null +++ b/src/layout/components/Collapse/index.ts @@ -0,0 +1,3 @@ +import Collapse from './src/Collapse.vue' + +export { Collapse } diff --git a/src/layout/components/Collapse/src/Collapse.vue b/src/layout/components/Collapse/src/Collapse.vue new file mode 100644 index 0000000..a8fc7ee --- /dev/null +++ b/src/layout/components/Collapse/src/Collapse.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/layout/components/ContextMenu/index.ts b/src/layout/components/ContextMenu/index.ts new file mode 100644 index 0000000..2a7c1f0 --- /dev/null +++ b/src/layout/components/ContextMenu/index.ts @@ -0,0 +1,10 @@ +import ContextMenu from './src/ContextMenu.vue' +import { ElDropdown } from 'element-plus' +import type { RouteLocationNormalizedLoaded } from 'vue-router' + +export interface ContextMenuExpose { + elDropdownMenuRef: ComponentRef + tagItem: RouteLocationNormalizedLoaded +} + +export { ContextMenu } diff --git a/src/layout/components/ContextMenu/src/ContextMenu.vue b/src/layout/components/ContextMenu/src/ContextMenu.vue new file mode 100644 index 0000000..90eea4c --- /dev/null +++ b/src/layout/components/ContextMenu/src/ContextMenu.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/layout/components/Footer/index.ts b/src/layout/components/Footer/index.ts new file mode 100644 index 0000000..bd052e0 --- /dev/null +++ b/src/layout/components/Footer/index.ts @@ -0,0 +1,3 @@ +import Footer from './src/Footer.vue' + +export { Footer } diff --git a/src/layout/components/Footer/src/Footer.vue b/src/layout/components/Footer/src/Footer.vue new file mode 100644 index 0000000..98ce7e5 --- /dev/null +++ b/src/layout/components/Footer/src/Footer.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/layout/components/LocaleDropdown/index.ts b/src/layout/components/LocaleDropdown/index.ts new file mode 100644 index 0000000..d02e640 --- /dev/null +++ b/src/layout/components/LocaleDropdown/index.ts @@ -0,0 +1,3 @@ +import LocaleDropdown from './src/LocaleDropdown.vue' + +export { LocaleDropdown } diff --git a/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue b/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue new file mode 100644 index 0000000..95132db --- /dev/null +++ b/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/layout/components/Logo/index.ts b/src/layout/components/Logo/index.ts new file mode 100644 index 0000000..1c4224c --- /dev/null +++ b/src/layout/components/Logo/index.ts @@ -0,0 +1,3 @@ +import Logo from './src/Logo.vue' + +export { Logo } diff --git a/src/layout/components/Logo/src/Logo.vue b/src/layout/components/Logo/src/Logo.vue new file mode 100644 index 0000000..d241130 --- /dev/null +++ b/src/layout/components/Logo/src/Logo.vue @@ -0,0 +1,88 @@ + + + diff --git a/src/layout/components/Menu/index.ts b/src/layout/components/Menu/index.ts new file mode 100644 index 0000000..a6ec696 --- /dev/null +++ b/src/layout/components/Menu/index.ts @@ -0,0 +1,3 @@ +import Menu from './src/Menu.vue' + +export { Menu } diff --git a/src/layout/components/Menu/src/Menu.vue b/src/layout/components/Menu/src/Menu.vue new file mode 100644 index 0000000..94a1da4 --- /dev/null +++ b/src/layout/components/Menu/src/Menu.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/src/layout/components/Menu/src/components/useRenderMenuItem.tsx b/src/layout/components/Menu/src/components/useRenderMenuItem.tsx new file mode 100644 index 0000000..301313f --- /dev/null +++ b/src/layout/components/Menu/src/components/useRenderMenuItem.tsx @@ -0,0 +1,50 @@ +import { ElSubMenu, ElMenuItem } from 'element-plus' +import { hasOneShowingChild } from '../helper' +import { isUrl } from '@/utils/is' +import { useRenderMenuTitle } from './useRenderMenuTitle' +import { pathResolve } from '@/utils/routerHelper' + +const { renderMenuTitle } = useRenderMenuTitle() + +export const useRenderMenuItem = () => + // allRouters: AppRouteRecordRaw[] = [], + { + const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => { + return routers + .filter((v) => !v.meta?.hidden) + .map((v) => { + const meta = v.meta ?? {} + const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v) + const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath(allRouters, v.path).join('/') + + if ( + oneShowingChild && + (!onlyOneChild?.children || onlyOneChild?.noShowingChildren) && + !meta?.alwaysShow + ) { + return ( + + {{ + default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta) + }} + + ) + } else { + return ( + + {{ + title: () => renderMenuTitle(meta), + default: () => renderMenuItem(v.children!, fullPath) + }} + + ) + } + }) + } + + return { + renderMenuItem + } + } diff --git a/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx b/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx new file mode 100644 index 0000000..8941d9d --- /dev/null +++ b/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx @@ -0,0 +1,27 @@ +import type { RouteMeta } from 'vue-router' +import { Icon } from '@/components/Icon' +import { useI18n } from '@/hooks/web/useI18n' + +export const useRenderMenuTitle = () => { + const renderMenuTitle = (meta: RouteMeta) => { + const { t } = useI18n() + const { title = 'Please set title', icon } = meta + + return icon ? ( + <> + + + {t(title as string)} + + + ) : ( + + {t(title as string)} + + ) + } + + return { + renderMenuTitle + } +} diff --git a/src/layout/components/Menu/src/helper.ts b/src/layout/components/Menu/src/helper.ts new file mode 100644 index 0000000..c26f5f4 --- /dev/null +++ b/src/layout/components/Menu/src/helper.ts @@ -0,0 +1,54 @@ +import type { RouteMeta } from 'vue-router' +import { findPath } from '@/utils/tree' + +type OnlyOneChildType = AppRouteRecordRaw & { noShowingChildren?: boolean } + +interface HasOneShowingChild { + oneShowingChild?: boolean + onlyOneChild?: OnlyOneChildType +} + +export const getAllParentPath = (treeData: T[], path: string) => { + const menuList = findPath(treeData, (n) => n.path === path) as AppRouteRecordRaw[] + return (menuList || []).map((item) => item.path) +} + +export const hasOneShowingChild = ( + children: AppRouteRecordRaw[] = [], + parent: AppRouteRecordRaw +): HasOneShowingChild => { + const onlyOneChild = ref() + + const showingChildren = children.filter((v) => { + const meta = (v.meta ?? {}) as RouteMeta + if (meta.hidden) { + return false + } else { + // Temp set(will be used if only has one showing child) + onlyOneChild.value = v + return true + } + }) + + // When there is only one child router, the child router is displayed by default + if (showingChildren.length === 1) { + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + // Show parent if there are no child router to display + if (!showingChildren.length) { + onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } + return { + oneShowingChild: true, + onlyOneChild: unref(onlyOneChild) + } + } + + return { + oneShowingChild: false, + onlyOneChild: unref(onlyOneChild) + } +} diff --git a/src/layout/components/Message/index.ts b/src/layout/components/Message/index.ts new file mode 100644 index 0000000..dfe0207 --- /dev/null +++ b/src/layout/components/Message/index.ts @@ -0,0 +1,3 @@ +import Message from './src/Message.vue' + +export { Message } diff --git a/src/layout/components/Message/src/Message.vue b/src/layout/components/Message/src/Message.vue new file mode 100644 index 0000000..d769d88 --- /dev/null +++ b/src/layout/components/Message/src/Message.vue @@ -0,0 +1,132 @@ + + + diff --git a/src/layout/components/Screenfull/index.ts b/src/layout/components/Screenfull/index.ts new file mode 100644 index 0000000..faec2d8 --- /dev/null +++ b/src/layout/components/Screenfull/index.ts @@ -0,0 +1,3 @@ +import Screenfull from './src/Screenfull.vue' + +export { Screenfull } diff --git a/src/layout/components/Screenfull/src/Screenfull.vue b/src/layout/components/Screenfull/src/Screenfull.vue new file mode 100644 index 0000000..4c045f2 --- /dev/null +++ b/src/layout/components/Screenfull/src/Screenfull.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/layout/components/Setting/index.ts b/src/layout/components/Setting/index.ts new file mode 100644 index 0000000..b64c9ad --- /dev/null +++ b/src/layout/components/Setting/index.ts @@ -0,0 +1,3 @@ +import Setting from './src/Setting.vue' + +export { Setting } diff --git a/src/layout/components/Setting/src/Setting.vue b/src/layout/components/Setting/src/Setting.vue new file mode 100644 index 0000000..2973674 --- /dev/null +++ b/src/layout/components/Setting/src/Setting.vue @@ -0,0 +1,302 @@ + + + + + diff --git a/src/layout/components/Setting/src/components/ColorRadioPicker.vue b/src/layout/components/Setting/src/components/ColorRadioPicker.vue new file mode 100644 index 0000000..fcc5e75 --- /dev/null +++ b/src/layout/components/Setting/src/components/ColorRadioPicker.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/layout/components/Setting/src/components/InterfaceDisplay.vue b/src/layout/components/Setting/src/components/InterfaceDisplay.vue new file mode 100644 index 0000000..3ba5c6b --- /dev/null +++ b/src/layout/components/Setting/src/components/InterfaceDisplay.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/layout/components/Setting/src/components/LayoutRadioPicker.vue b/src/layout/components/Setting/src/components/LayoutRadioPicker.vue new file mode 100644 index 0000000..801686c --- /dev/null +++ b/src/layout/components/Setting/src/components/LayoutRadioPicker.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/src/layout/components/SizeDropdown/index.ts b/src/layout/components/SizeDropdown/index.ts new file mode 100644 index 0000000..516488d --- /dev/null +++ b/src/layout/components/SizeDropdown/index.ts @@ -0,0 +1,3 @@ +import SizeDropdown from './src/SizeDropdown.vue' + +export { SizeDropdown } diff --git a/src/layout/components/SizeDropdown/src/SizeDropdown.vue b/src/layout/components/SizeDropdown/src/SizeDropdown.vue new file mode 100644 index 0000000..3e15224 --- /dev/null +++ b/src/layout/components/SizeDropdown/src/SizeDropdown.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/layout/components/TabMenu/index.ts b/src/layout/components/TabMenu/index.ts new file mode 100644 index 0000000..b5fd71c --- /dev/null +++ b/src/layout/components/TabMenu/index.ts @@ -0,0 +1,3 @@ +import TabMenu from './src/TabMenu.vue' + +export { TabMenu } diff --git a/src/layout/components/TabMenu/src/TabMenu.vue b/src/layout/components/TabMenu/src/TabMenu.vue new file mode 100644 index 0000000..efad6a6 --- /dev/null +++ b/src/layout/components/TabMenu/src/TabMenu.vue @@ -0,0 +1,240 @@ + + + diff --git a/src/layout/components/TabMenu/src/helper.ts b/src/layout/components/TabMenu/src/helper.ts new file mode 100644 index 0000000..cce3932 --- /dev/null +++ b/src/layout/components/TabMenu/src/helper.ts @@ -0,0 +1,51 @@ +import { getAllParentPath } from '@/layout/components/Menu/src/helper' +import type { RouteMeta } from 'vue-router' +import { isUrl } from '@/utils/is' +import { cloneDeep } from 'lodash-es' + +export type TabMapTypes = { + [key: string]: string[] +} + +export const tabPathMap = reactive({}) + +export const initTabMap = (routes: AppRouteRecordRaw[]) => { + for (const v of routes) { + const meta = (v.meta ?? {}) as RouteMeta + if (!meta?.hidden) { + tabPathMap[v.path] = [] + } + } +} + +export const filterMenusPath = ( + routes: AppRouteRecordRaw[], + allRoutes: AppRouteRecordRaw[] +): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + for (const v of routes) { + let data: Nullable = null + const meta = (v.meta ?? {}) as RouteMeta + if (!meta.hidden || meta.canTo) { + const allParentPath = getAllParentPath(allRoutes, v.path) + + const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/') + + data = cloneDeep(v) + data.path = fullPath + if (v.children && data) { + data.children = filterMenusPath(v.children, allRoutes) + } + + if (data) { + res.push(data) + } + + if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) { + tabPathMap[allParentPath[0]].push(fullPath) + } + } + } + + return res +} diff --git a/src/layout/components/TagsView/index.ts b/src/layout/components/TagsView/index.ts new file mode 100644 index 0000000..30e604a --- /dev/null +++ b/src/layout/components/TagsView/index.ts @@ -0,0 +1,3 @@ +import TagsView from './src/TagsView.vue' + +export { TagsView } diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue new file mode 100644 index 0000000..dcbb90f --- /dev/null +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -0,0 +1,639 @@ + + + + + diff --git a/src/layout/components/TagsView/src/helper.ts b/src/layout/components/TagsView/src/helper.ts new file mode 100644 index 0000000..22f6a50 --- /dev/null +++ b/src/layout/components/TagsView/src/helper.ts @@ -0,0 +1,21 @@ +import type { RouteMeta, RouteLocationNormalizedLoaded } from 'vue-router' +import { pathResolve } from '@/utils/routerHelper' + +export const filterAffixTags = (routes: AppRouteRecordRaw[], parentPath = '') => { + let tags: RouteLocationNormalizedLoaded[] = [] + routes.forEach((route) => { + const meta = route.meta as RouteMeta + const tagPath = pathResolve(parentPath, route.path) + if (meta?.affix) { + tags.push({ ...route, path: tagPath, fullPath: tagPath } as RouteLocationNormalizedLoaded) + } + if (route.children) { + const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath) + if (tempTags.length >= 1) { + tags = [...tags, ...tempTags] + } + } + }) + + return tags +} diff --git a/src/layout/components/ThemeSwitch/index.ts b/src/layout/components/ThemeSwitch/index.ts new file mode 100644 index 0000000..823a276 --- /dev/null +++ b/src/layout/components/ThemeSwitch/index.ts @@ -0,0 +1,3 @@ +import ThemeSwitch from './src/ThemeSwitch.vue' + +export { ThemeSwitch } diff --git a/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue b/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue new file mode 100644 index 0000000..39a8cfd --- /dev/null +++ b/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue @@ -0,0 +1,46 @@ + + + + diff --git a/src/layout/components/ToolHeader.vue b/src/layout/components/ToolHeader.vue new file mode 100644 index 0000000..0b8d00d --- /dev/null +++ b/src/layout/components/ToolHeader.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/layout/components/UserInfo/index.ts b/src/layout/components/UserInfo/index.ts new file mode 100644 index 0000000..c3a34ab --- /dev/null +++ b/src/layout/components/UserInfo/index.ts @@ -0,0 +1,3 @@ +import UserInfo from './src/UserInfo.vue' + +export { UserInfo } diff --git a/src/layout/components/UserInfo/src/UserInfo.vue b/src/layout/components/UserInfo/src/UserInfo.vue new file mode 100644 index 0000000..355aabc --- /dev/null +++ b/src/layout/components/UserInfo/src/UserInfo.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/src/layout/components/UserInfo/src/components/LockDialog.vue b/src/layout/components/UserInfo/src/components/LockDialog.vue new file mode 100644 index 0000000..7257be1 --- /dev/null +++ b/src/layout/components/UserInfo/src/components/LockDialog.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/layout/components/UserInfo/src/components/LockPage.vue b/src/layout/components/UserInfo/src/components/LockPage.vue new file mode 100644 index 0000000..27d0a43 --- /dev/null +++ b/src/layout/components/UserInfo/src/components/LockPage.vue @@ -0,0 +1,270 @@ + + + + + diff --git a/src/layout/components/useRenderLayout.tsx b/src/layout/components/useRenderLayout.tsx new file mode 100644 index 0000000..a631aa0 --- /dev/null +++ b/src/layout/components/useRenderLayout.tsx @@ -0,0 +1,294 @@ +import { computed } from 'vue' +import { useAppStore } from '@/store/modules/app' +import { Menu } from '@/layout/components/Menu' +import { TabMenu } from '@/layout/components/TabMenu' +import { TagsView } from '@/layout/components/TagsView' +import { Logo } from '@/layout/components/Logo' +import AppView from './AppView.vue' +import ToolHeader from './ToolHeader.vue' +import { ElScrollbar } from 'element-plus' +import { useDesign } from '@/hooks/web/useDesign' + +const { getPrefixCls } = useDesign() + +const prefixCls = getPrefixCls('layout') + +const appStore = useAppStore() + +const pageLoading = computed(() => appStore.getPageLoading) + +// 标签页 +const tagsView = computed(() => appStore.getTagsView) + +// 菜单折叠 +const collapse = computed(() => appStore.getCollapse) + +// logo +const logo = computed(() => appStore.logo) + +// 固定头部 +const fixedHeader = computed(() => appStore.getFixedHeader) + +// 是否是移动端 +const mobile = computed(() => appStore.getMobile) + +// 固定菜单 +const fixedMenu = computed(() => appStore.getFixedMenu) + +export const useRenderLayout = () => { + const renderClassic = () => { + return ( + <> +
+ {logo.value ? ( + + ) : undefined} + +
+
+ +
+ + + {tagsView.value ? ( + + ) : undefined} +
+ + +
+
+ + ) + } + + const renderTopLeft = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ +
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+
+ + ) + } + + const renderTop = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+ + ) + } + + const renderCutMenu = () => { + return ( + <> +
+ {logo.value ? : undefined} + + +
+
+ +
+ + {tagsView.value ? ( + + ) : undefined} + + + +
+
+ + ) + } + + return { + renderClassic, + renderTopLeft, + renderTop, + renderCutMenu + } +} diff --git a/src/locales/en.ts b/src/locales/en.ts new file mode 100644 index 0000000..505cfd8 --- /dev/null +++ b/src/locales/en.ts @@ -0,0 +1,460 @@ +export default { + common: { + inputText: 'Please input', + selectText: 'Please select', + startTimeText: 'Start time', + endTimeText: 'End time', + login: 'Login', + required: 'This is required', + loginOut: 'Login out', + document: 'Document', + profile: 'User Center', + reminder: 'Reminder', + loginOutMessage: 'Exit the system?', + back: 'Back', + ok: 'OK', + save: 'Save', + cancel: 'Cancel', + close: 'Close', + reload: 'Reload current', + success: 'Success', + closeTab: 'Close current', + closeTheLeftTab: 'Close left', + closeTheRightTab: 'Close right', + closeOther: 'Close other', + closeAll: 'Close all', + prevLabel: 'Prev', + nextLabel: 'Next', + skipLabel: 'Jump', + doneLabel: 'End', + menu: 'Menu', + menuDes: 'Menu bar rendered in routed structure', + collapse: 'Collapse', + collapseDes: 'Expand and zoom the menu bar', + tagsView: 'Tags view', + tagsViewDes: 'Used to record routing history', + tool: 'Tool', + toolDes: 'Used to set up custom systems', + query: 'Query', + reset: 'Reset', + shrink: 'Put away', + expand: 'Expand', + confirmTitle: 'System Hint', + exportMessage: 'Whether to confirm export data item?', + importMessage: 'Whether to confirm import data item?', + createSuccess: 'Create Success', + updateSuccess: 'Update Success', + delMessage: 'Delete the selected data?', + delDataMessage: 'Delete the data?', + delNoData: 'Please select the data to delete', + delSuccess: 'Deleted successfully', + index: 'Index', + status: 'Status', + createTime: 'Create Time', + updateTime: 'Update Time', + copy: 'Copy', + copySuccess: 'Copy Success', + copyError: 'Copy Error' + }, + lock: { + lockScreen: 'Lock screen', + lock: 'Lock', + lockPassword: 'Lock screen password', + unlock: 'Click to unlock', + backToLogin: 'Back to login', + entrySystem: 'Entry the system', + placeholder: 'Please enter the lock screen password', + message: 'Lock screen password error' + }, + error: { + noPermission: `Sorry, you don't have permission to access this page.`, + pageError: 'Sorry, the page you visited does not exist.', + networkError: 'Sorry, the server reported an error.', + returnToHome: 'Return to home' + }, + permission: { + hasPermission: `Please set the operation permission label value`, + hasRole: `Please set the role permission tag value` + }, + setting: { + projectSetting: 'Project setting', + theme: 'Theme', + layout: 'Layout', + systemTheme: 'System theme', + menuTheme: 'Menu theme', + interfaceDisplay: 'Interface display', + breadcrumb: 'Breadcrumb', + breadcrumbIcon: 'Breadcrumb icon', + collapseMenu: 'Collapse menu', + hamburgerIcon: 'Hamburger icon', + screenfullIcon: 'Screenfull icon', + sizeIcon: 'Size icon', + localeIcon: 'Locale icon', + messageIcon: 'Message icon', + tagsView: 'Tags view', + logo: 'Logo', + greyMode: 'Grey mode', + fixedHeader: 'Fixed header', + headerTheme: 'Header theme', + cutMenu: 'Cut Menu', + copy: 'Copy', + clearAndReset: 'Clear cache and reset', + copySuccess: 'Copy success', + copyFailed: 'Copy failed', + footer: 'Footer', + uniqueOpened: 'Unique opened', + tagsViewIcon: 'Tags view icon', + reExperienced: 'Please exit the login experience again', + fixedMenu: 'Fixed menu' + }, + size: { + default: 'Default', + large: 'Large', + small: 'Small' + }, + login: { + welcome: 'Welcome to the system', + message: 'Backstage management system', + tenantname: 'TenantName', + username: 'Username', + password: 'Password', + code: 'verification code', + login: 'Sign in', + relogin: 'Sign in again', + otherLogin: 'Sign in with', + register: 'Register', + checkPassword: 'Confirm password', + remember: 'Remember me', + hasUser: 'Existing account? Go to login', + forgetPassword: 'Forget password?', + tenantNamePlaceholder: 'Please Enter Tenant Name', + usernamePlaceholder: 'Please Enter Username', + passwordPlaceholder: 'Please Enter Password', + codePlaceholder: 'Please Enter Verification Code', + mobileTitle: 'Mobile sign in', + mobileNumber: 'Mobile Number', + mobileNumberPlaceholder: 'Plaease Enter Mobile Number', + backLogin: 'back', + getSmsCode: 'Get SMS Code', + btnMobile: 'Mobile sign in', + btnQRCode: 'QR code sign in', + qrcode: 'Scan the QR code to log in', + btnRegister: 'Sign up', + SmsSendMsg: 'code has been sent', + resetPassword: "Reset Password", + resetPasswordSuccess: "Reset Password Success", + invalidTenantName:"Invalid Tenant Name" + }, + captcha: { + verification: 'Please complete security verification', + slide: 'Swipe right to complete verification', + point: 'Please click', + success: 'Verification succeeded', + fail: 'verification failed' + }, + router: { + login: 'Login', + home: 'Home', + analysis: 'Analysis', + workplace: 'Workplace' + }, + analysis: { + newUser: 'New user', + unreadInformation: 'Unread information', + transactionAmount: 'Transaction amount', + totalShopping: 'Total Shopping', + monthlySales: 'Monthly sales', + userAccessSource: 'User access source', + january: 'January', + february: 'February', + march: 'March', + april: 'April', + may: 'May', + june: 'June', + july: 'July', + august: 'August', + september: 'September', + october: 'October', + november: 'November', + december: 'December', + estimate: 'Estimate', + actual: 'Actual', + directAccess: 'Airect access', + mailMarketing: 'Mail marketing', + allianceAdvertising: 'Alliance advertising', + videoAdvertising: 'Video advertising', + searchEngines: 'Search engines', + weeklyUserActivity: 'Weekly user activity', + activeQuantity: 'Active quantity', + monday: 'Monday', + tuesday: 'Tuesday', + wednesday: 'Wednesday', + thursday: 'Thursday', + friday: 'Friday', + saturday: 'Saturday', + sunday: 'Sunday' + }, + workplace: { + welcome: 'Hello', + happyDay: 'Wish you happy every day!', + toady: `It's sunny today`, + notice: 'Announcement', + project: 'Project', + access: 'Project access', + toDo: 'To do', + introduction: 'A serious introduction', + shortcutOperation: 'Quick entry', + operation: 'Operation', + index: 'Index', + personal: 'Personal', + team: 'Team', + quote: 'Quote', + contribution: 'Contribution', + hot: 'Hot', + yield: 'Yield', + dynamic: 'Dynamic', + push: 'push', + follow: 'Follow' + }, + form: { + input: 'Input', + inputNumber: 'InputNumber', + default: 'Default', + icon: 'Icon', + mixed: 'Mixed', + textarea: 'Textarea', + slot: 'Slot', + position: 'Position', + autocomplete: 'Autocomplete', + select: 'Select', + selectGroup: 'Select Group', + selectV2: 'SelectV2', + cascader: 'Cascader', + switch: 'Switch', + rate: 'Rate', + colorPicker: 'Color Picker', + transfer: 'Transfer', + render: 'Render', + radio: 'Radio', + button: 'Button', + checkbox: 'Checkbox', + slider: 'Slider', + datePicker: 'Date Picker', + shortcuts: 'Shortcuts', + today: 'Today', + yesterday: 'Yesterday', + aWeekAgo: 'A week ago', + week: 'Week', + year: 'Year', + month: 'Month', + dates: 'Dates', + daterange: 'Date Range', + monthrange: 'Month Range', + dateTimePicker: 'DateTimePicker', + dateTimerange: 'Datetime Range', + timePicker: 'Time Picker', + timeSelect: 'Time Select', + inputPassword: 'input Password', + passwordStrength: 'Password Strength', + operate: 'operate', + change: 'Change', + restore: 'Restore', + disabled: 'Disabled', + disablement: 'Disablement', + delete: 'Delete', + add: 'Add', + setValue: 'Set value', + resetValue: 'Reset value', + set: 'Set', + subitem: 'Subitem', + formValidation: 'Form validation', + verifyReset: 'Verify reset', + remark: 'Remark' + }, + watermark: { + watermark: 'Watermark' + }, + table: { + table: 'Table', + index: 'Index', + title: 'Title', + author: 'Author', + createTime: 'Create time', + action: 'Action', + pagination: 'pagination', + reserveIndex: 'Reserve index', + restoreIndex: 'Restore index', + showSelections: 'Show selections', + hiddenSelections: 'Restore selections', + showExpandedRows: 'Show expanded rows', + hiddenExpandedRows: 'Hidden expanded rows', + header: 'Header' + }, + action: { + create: 'Create', + add: 'Add', + del: 'Delete', + delete: 'Delete', + edit: 'Edit', + update: 'Update', + preview: 'Preview', + more: 'More', + sync: 'Sync', + save: 'Save', + detail: 'Detail', + export: 'Export', + import: 'Import', + generate: 'Generate', + logout: 'Login Out', + test: 'Test', + typeCreate: 'Dict Type Create', + typeUpdate: 'Dict Type Eidt', + dataCreate: 'Dict Data Create', + dataUpdate: 'Dict Data Eidt', + fileUpload: 'File Upload' + }, + dialog: { + dialog: 'Dialog', + open: 'Open', + close: 'Close' + }, + sys: { + api: { + operationFailed: 'Operation failed', + errorTip: 'Error Tip', + errorMessage: 'The operation failed, the system is abnormal!', + timeoutMessage: 'Login timed out, please log in again!', + apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!', + apiRequestFailed: 'The interface request failed, please try again later!', + networkException: 'network anomaly', + networkExceptionMsg: + 'Please check if your network connection is normal! The network is abnormal', + + errMsg401: 'The user does not have permission (token, user name, password error)!', + errMsg403: 'The user is authorized, but access is forbidden!', + errMsg404: 'Network request error, the resource was not found!', + errMsg405: 'Network request error, request method not allowed!', + errMsg408: 'Network request timed out!', + errMsg500: 'Server error, please contact the administrator!', + errMsg501: 'The network is not implemented!', + errMsg502: 'Network Error!', + errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!', + errMsg504: 'Network timeout!', + errMsg505: 'The http version does not support the request!', + errMsg901: 'Demo mode, no write operations are possible!' + }, + app: { + logoutTip: 'Reminder', + logoutMessage: 'Confirm to exit the system?', + menuLoading: 'Menu loading...' + }, + exception: { + backLogin: 'Back Login', + backHome: 'Back Home', + subTitle403: "Sorry, you don't have access to this page.", + subTitle404: 'Sorry, the page you visited does not exist.', + subTitle500: 'Sorry, the server is reporting an error.', + noDataTitle: 'No data on the current page.', + networkErrorTitle: 'Network Error', + networkErrorSubTitle: + 'Sorry, Your network connection has been disconnected, please check your network!' + }, + lock: { + unlock: 'Click to unlock', + alert: 'Lock screen password error', + backToLogin: 'Back to login', + entry: 'Enter the system', + placeholder: 'Please enter the lock screen password or user password' + }, + login: { + backSignIn: 'Back sign in', + mobileSignInFormTitle: 'Mobile sign in', + qrSignInFormTitle: 'Qr code sign in', + signInFormTitle: 'Sign in', + signUpFormTitle: 'Sign up', + forgetFormTitle: 'Reset password', + + signInTitle: 'Backstage management system', + signInDesc: 'Enter your personal details and get started!', + policy: 'I agree to the xxx Privacy Policy', + scanSign: `scanning the code to complete the login`, + + loginButton: 'Sign in', + registerButton: 'Sign up', + rememberMe: 'Remember me', + forgetPassword: 'Forget Password?', + otherSignIn: 'Sign in with', + + // notify + loginSuccessTitle: 'Login successful', + loginSuccessDesc: 'Welcome back', + + // placeholder + accountPlaceholder: 'Please input username', + passwordPlaceholder: 'Please input password', + smsPlaceholder: 'Please input sms code', + mobilePlaceholder: 'Please input mobile', + policyPlaceholder: 'Register after checking', + diffPwd: 'The two passwords are inconsistent', + + userName: 'Username', + password: 'Password', + confirmPassword: 'Confirm Password', + email: 'Email', + smsCode: 'SMS code', + mobile: 'Mobile' + } + }, + profile: { + user: { + title: 'Personal Information', + username: 'User Name', + nickname: 'Nick Name', + mobile: 'Phone Number', + email: 'User Mail', + dept: 'Department', + posts: 'Position', + roles: 'Own Role', + sex: 'Sex', + man: 'Man', + woman: 'Woman', + createTime: 'Created Date' + }, + info: { + title: 'Basic Information', + basicInfo: 'Basic Information', + resetPwd: 'Reset Password', + userSocial: 'Social Information' + }, + rules: { + nickname: 'Please Enter User Nickname', + mail: 'Please Input The Email Address', + truemail: 'Please Input The Correct Email Address', + phone: 'Please Enter The Phone Number', + truephone: 'Please Enter The Correct Phone Number' + }, + password: { + oldPassword: 'Old PassWord', + newPassword: 'New Password', + confirmPassword: 'Confirm Password', + oldPwdMsg: 'Please Enter Old Password', + newPwdMsg: 'Please Enter New Password', + cfPwdMsg: 'Please Enter Confirm Password', + diffPwd: 'The Passwords Entered Twice No Match' + } + }, + cropper: { + selectImage: 'Select Image', + uploadSuccess: 'Uploaded success!', + modalTitle: 'Avatar upload', + okText: 'Confirm and upload', + btn_reset: 'Reset', + btn_rotate_left: 'Counterclockwise rotation', + btn_rotate_right: 'Clockwise rotation', + btn_scale_x: 'Flip horizontal', + btn_scale_y: 'Flip vertical', + btn_zoom_in: 'Zoom in', + btn_zoom_out: 'Zoom out', + preview: 'Preivew' + } +} diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts new file mode 100644 index 0000000..130d565 --- /dev/null +++ b/src/locales/zh-CN.ts @@ -0,0 +1,456 @@ +export default { + common: { + inputText: '请输入', + selectText: '请选择', + startTimeText: '开始时间', + endTimeText: '结束时间', + login: '登录', + required: '该项为必填项', + loginOut: '退出系统', + document: '项目文档', + profile: '个人中心', + reminder: '温馨提示', + loginOutMessage: '是否退出本系统?', + back: '返回', + ok: '确定', + save: '保存', + cancel: '取消', + close: '关闭', + reload: '重新加载', + success: '成功', + closeTab: '关闭标签页', + closeTheLeftTab: '关闭左侧标签页', + closeTheRightTab: '关闭右侧标签页', + closeOther: '关闭其他标签页', + closeAll: '关闭全部标签页', + prevLabel: '上一步', + nextLabel: '下一步', + skipLabel: '跳过', + doneLabel: '结束', + menu: '菜单', + menuDes: '以路由的结构渲染的菜单栏', + collapse: '展开缩收', + collapseDes: '展开和缩放菜单栏', + tagsView: '标签页', + tagsViewDes: '用于记录路由历史记录', + tool: '工具', + toolDes: '用于设置定制系统', + query: '查询', + reset: '重置', + shrink: '收起', + expand: '展开', + confirmTitle: '系统提示', + exportMessage: '是否确认导出数据项?', + importMessage: '是否确认导入数据项?', + createSuccess: '新增成功', + updateSuccess: '修改成功', + delMessage: '是否删除所选中数据?', + delDataMessage: '是否删除数据?', + delNoData: '请选择需要删除的数据', + delSuccess: '删除成功', + index: '序号', + status: '状态', + createTime: '创建时间', + updateTime: '更新时间', + copy: '复制', + copySuccess: '复制成功', + copyError: '复制失败' + }, + lock: { + lockScreen: '锁定屏幕', + lock: '锁定', + lockPassword: '锁屏密码', + unlock: '点击解锁', + backToLogin: '返回登录', + entrySystem: '进入系统', + placeholder: '请输入锁屏密码', + message: '锁屏密码错误' + }, + error: { + noPermission: `抱歉,您无权访问此页面。`, + pageError: '抱歉,您访问的页面不存在。', + networkError: '抱歉,服务器报告错误。', + returnToHome: '返回首页' + }, + permission: { + hasPermission: `请设置操作权限标签值`, + hasRole: `请设置角色权限标签值` + }, + setting: { + projectSetting: '项目配置', + theme: '主题', + layout: '布局', + systemTheme: '系统主题', + menuTheme: '菜单主题', + interfaceDisplay: '界面显示', + breadcrumb: '面包屑', + breadcrumbIcon: '面包屑图标', + collapseMenu: '折叠菜单', + hamburgerIcon: '折叠图标', + screenfullIcon: '全屏图标', + sizeIcon: '尺寸图标', + localeIcon: '多语言图标', + messageIcon: '消息图标', + tagsView: '标签页', + tagsViewImmerse: '标签页沉浸', + logo: '标志', + greyMode: '灰色模式', + fixedHeader: '固定头部', + headerTheme: '头部主题', + cutMenu: '切割菜单', + copy: '拷贝', + clearAndReset: '清除缓存并且重置', + copySuccess: '拷贝成功', + copyFailed: '拷贝失败', + footer: '页脚', + uniqueOpened: '菜单手风琴', + tagsViewIcon: '标签页图标', + reExperienced: '请重新退出登录体验', + fixedMenu: '固定菜单' + }, + size: { + default: '默认', + large: '大', + small: '小' + }, + login: { + welcome: '欢迎使用本系统', + message: '开箱即用的中后台管理系统', + tenantname: '租户名称', + username: '用户名', + password: '密码', + code: '验证码', + login: '登录', + relogin: '重新登录', + otherLogin: '其他登录方式', + register: '注册', + checkPassword: '确认密码', + remember: '记住我', + hasUser: '已有账号?去登录', + forgetPassword: '忘记密码?', + tenantNamePlaceholder: '请输入租户名称', + usernamePlaceholder: '请输入用户名', + passwordPlaceholder: '请输入密码', + codePlaceholder: '请输入验证码', + mobileTitle: '手机登录', + mobileNumber: '手机号码', + mobileNumberPlaceholder: '请输入手机号码', + backLogin: '返回', + getSmsCode: '获取验证码', + btnMobile: '手机登录', + btnQRCode: '二维码登录', + qrcode: '扫描二维码登录', + btnRegister: '注册', + SmsSendMsg: '验证码已发送', + resetPassword: "重置密码", + resetPasswordSuccess: "重置密码成功", + invalidTenantName: "无效的租户名称" + }, + captcha: { + verification: '请完成安全验证', + slide: '向右滑动完成验证', + point: '请依次点击', + success: '验证成功', + fail: '验证失败' + }, + router: { + login: '登录', + socialLogin: '社交登录', + home: '首页', + analysis: '分析页', + workplace: '工作台' + }, + analysis: { + newUser: '新增用户', + unreadInformation: '未读消息', + transactionAmount: '成交金额', + totalShopping: '购物总量', + monthlySales: '每月销售额', + userAccessSource: '用户访问来源', + january: '一月', + february: '二月', + march: '三月', + april: '四月', + may: '五月', + june: '六月', + july: '七月', + august: '八月', + september: '九月', + october: '十月', + november: '十一月', + december: '十二月', + estimate: '预计', + actual: '实际', + directAccess: '直接访问', + mailMarketing: '邮件营销', + allianceAdvertising: '联盟广告', + videoAdvertising: '视频广告', + searchEngines: '搜索引擎', + weeklyUserActivity: '每周用户活跃量', + activeQuantity: '活跃量', + monday: '周一', + tuesday: '周二', + wednesday: '周三', + thursday: '周四', + friday: '周五', + saturday: '周六', + sunday: '周日' + }, + workplace: { + welcome: '你好', + happyDay: '祝你开心每一天!', + toady: '今日晴', + notice: '通知公告', + project: '项目数', + access: '项目访问', + toDo: '待办', + introduction: '一个正经的简介', + shortcutOperation: '快捷入口', + operation: '操作', + index: '指数', + personal: '个人', + team: '团队', + quote: '引用', + contribution: '贡献', + hot: '热度', + yield: '产量', + dynamic: '动态', + push: '推送', + follow: '关注' + }, + form: { + input: '输入框', + inputNumber: '数字输入框', + default: '默认', + icon: '图标', + mixed: '复合型', + textarea: '多行文本', + slot: '插槽', + position: '位置', + autocomplete: '自动补全', + select: '选择器', + selectGroup: '选项分组', + selectV2: '虚拟列表选择器', + cascader: '级联选择器', + switch: '开关', + rate: '评分', + colorPicker: '颜色选择器', + transfer: '穿梭框', + render: '渲染器', + radio: '单选框', + button: '按钮', + checkbox: '多选框', + slider: '滑块', + datePicker: '日期选择器', + shortcuts: '快捷选项', + today: '今天', + yesterday: '昨天', + aWeekAgo: '一周前', + week: '周', + year: '年', + month: '月', + dates: '日期', + daterange: '日期范围', + monthrange: '月份范围', + dateTimePicker: '日期时间选择器', + dateTimerange: '日期时间范围', + timePicker: '时间选择器', + timeSelect: '时间选择', + inputPassword: '密码输入框', + passwordStrength: '密码强度', + operate: '操作', + change: '更改', + restore: '还原', + disabled: '禁用', + disablement: '解除禁用', + delete: '删除', + add: '添加', + setValue: '设置值', + resetValue: '重置值', + set: '设置', + subitem: '子项', + formValidation: '表单验证', + verifyReset: '验证重置', + remark: '备注' + }, + watermark: { + watermark: '水印' + }, + table: { + table: '表格', + index: '序号', + title: '标题', + author: '作者', + createTime: '创建时间', + action: '操作', + pagination: '分页', + reserveIndex: '叠加序号', + restoreIndex: '还原序号', + showSelections: '显示多选', + hiddenSelections: '隐藏多选', + showExpandedRows: '显示展开行', + hiddenExpandedRows: '隐藏展开行', + header: '头部' + }, + action: { + create: '新增', + add: '新增', + del: '删除', + delete: '删除', + edit: '编辑', + update: '编辑', + preview: '预览', + more: '更多', + sync: '同步', + save: '保存', + detail: '详情', + export: '导出', + import: '导入', + generate: '生成', + logout: '强制退出', + test: '测试', + typeCreate: '字典类型新增', + typeUpdate: '字典类型编辑', + dataCreate: '字典数据新增', + dataUpdate: '字典数据编辑' + }, + dialog: { + dialog: '弹窗', + open: '打开', + close: '关闭' + }, + sys: { + api: { + operationFailed: '操作失败', + errorTip: '错误提示', + errorMessage: '操作失败,系统异常!', + timeoutMessage: '登录超时,请重新登录!', + apiTimeoutMessage: '接口请求超时,请刷新页面重试!', + apiRequestFailed: '请求出错,请稍候重试', + networkException: '网络异常', + networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', + errMsg401: '用户没有权限(令牌、用户名、密码错误)!', + errMsg403: '用户得到授权,但是访问是被禁止的。!', + errMsg404: '网络请求错误,未找到该资源!', + errMsg405: '网络请求错误,请求方法未允许!', + errMsg408: '网络请求超时!', + errMsg500: '服务器错误,请联系管理员!', + errMsg501: '网络未实现!', + errMsg502: '网络错误!', + errMsg503: '服务不可用,服务器暂时过载或维护!', + errMsg504: '网络超时!', + errMsg505: 'http版本不支持该请求!', + errMsg901: '演示模式,无法进行写操作!' + }, + app: { + logoutTip: '温馨提醒', + logoutMessage: '是否确认退出系统?', + menuLoading: '菜单加载中...' + }, + exception: { + backLogin: '返回登录', + backHome: '返回首页', + subTitle403: '抱歉,您无权访问此页面。', + subTitle404: '抱歉,您访问的页面不存在。', + subTitle500: '抱歉,服务器报告错误。', + noDataTitle: '当前页无数据', + networkErrorTitle: '网络错误', + networkErrorSubTitle: '抱歉,您的网络连接已断开,请检查您的网络!' + }, + lock: { + unlock: '点击解锁', + alert: '锁屏密码错误', + backToLogin: '返回登录', + entry: '进入系统', + placeholder: '请输入锁屏密码或者用户密码' + }, + login: { + backSignIn: '返回', + signInFormTitle: '登录', + ssoFormTitle: '三方授权', + mobileSignInFormTitle: '手机登录', + qrSignInFormTitle: '二维码登录', + signUpFormTitle: '注册', + forgetFormTitle: '重置密码', + signInTitle: '开箱即用的中后台管理系统', + signInDesc: '输入您的个人详细信息开始使用!', + policy: '我同意xxx隐私政策', + scanSign: `扫码后点击"确认",即可完成登录`, + loginButton: '登录', + registerButton: '注册', + rememberMe: '记住我', + forgetPassword: '忘记密码?', + otherSignIn: '其他登录方式', + // notify + loginSuccessTitle: '登录成功', + loginSuccessDesc: '欢迎回来', + // placeholder + accountPlaceholder: '请输入账号', + passwordPlaceholder: '请输入密码', + smsPlaceholder: '请输入验证码', + mobilePlaceholder: '请输入手机号码', + policyPlaceholder: '勾选后才能注册', + diffPwd: '两次输入密码不一致', + userName: '账号', + password: '密码', + confirmPassword: '确认密码', + email: '邮箱', + smsCode: '短信验证码', + mobile: '手机号码' + } + }, + profile: { + user: { + title: '个人信息', + username: '用户名称', + nickname: '用户昵称', + mobile: '手机号码', + email: '用户邮箱', + dept: '所属部门', + posts: '所属岗位', + roles: '所属角色', + sex: '性别', + man: '男', + woman: '女', + createTime: '创建日期' + }, + info: { + title: '基本信息', + basicInfo: '基本资料', + resetPwd: '修改密码', + userSocial: '社交信息' + }, + rules: { + nickname: '请输入用户昵称', + mail: '请输入邮箱地址', + truemail: '请输入正确的邮箱地址', + phone: '请输入正确的手机号码', + truephone: '请输入正确的手机号码' + }, + password: { + oldPassword: '旧密码', + newPassword: '新密码', + confirmPassword: '确认密码', + oldPwdMsg: '请输入旧密码', + newPwdMsg: '请输入新密码', + cfPwdMsg: '请输入确认密码', + pwdRules: '长度在 6 到 20 个字符', + diffPwd: '两次输入密码不一致' + } + }, + cropper: { + selectImage: '选择图片', + uploadSuccess: '上传成功', + modalTitle: '头像上传', + okText: '确认并上传', + btn_reset: '重置', + btn_rotate_left: '逆时针旋转', + btn_rotate_right: '顺时针旋转', + btn_scale_x: '水平翻转', + btn_scale_y: '垂直翻转', + btn_zoom_in: '放大', + btn_zoom_out: '缩小', + preview: '预览' + }, + 'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错 +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..874f766 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,74 @@ +// 引入unocss css +import '@/plugins/unocss' + +// 导入全局的svg图标 +import '@/plugins/svgIcon' + +// 初始化多语言 +import { setupI18n } from '@/plugins/vueI18n' + +// 引入状态管理 +import { setupStore } from '@/store' + +// 全局组件 +import { setupGlobCom } from '@/components' + +// 引入 element-plus +import { setupElementPlus } from '@/plugins/elementPlus' + +// 引入 form-create +import { setupFormCreate } from '@/plugins/formCreate' + +// 引入全局样式 +import '@/styles/index.scss' + +// 引入动画 +import '@/plugins/animate.css' + +// 路由 +import router, { setupRouter } from '@/router' + +// 指令 +import { setupAuth, setupMountedFocus } from '@/directives' + +import { createApp } from 'vue' + +import App from './App.vue' + +import './permission' + +import '@/plugins/tongji' // 百度统计 +import Logger from '@/utils/Logger' + +import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患 + +// 创建实例 +const setupAll = async () => { + const app = createApp(App) + + await setupI18n(app) + + setupStore(app) + + setupGlobCom(app) + + setupElementPlus(app) + + setupFormCreate(app) + + setupRouter(app) + + // directives 指令 + setupAuth(app) + setupMountedFocus(app) + + await router.isReady() + + app.use(VueDOMPurifyHTML) + + app.mount('#app') +} + +setupAll() + +Logger.prettyPrimary(`欢迎使用`, import.meta.env.VITE_APP_TITLE) diff --git a/src/permission.ts b/src/permission.ts new file mode 100644 index 0000000..b04bc3c --- /dev/null +++ b/src/permission.ts @@ -0,0 +1,106 @@ +import router from './router' +import type { RouteRecordRaw } from 'vue-router' +import { isRelogin } from '@/config/axios/service' +import { getAccessToken } from '@/utils/auth' +import { useTitle } from '@/hooks/web/useTitle' +import { useNProgress } from '@/hooks/web/useNProgress' +import { usePageLoading } from '@/hooks/web/usePageLoading' +import { useDictStoreWithOut } from '@/store/modules/dict' +import { useUserStoreWithOut } from '@/store/modules/user' +import { usePermissionStoreWithOut } from '@/store/modules/permission' + +const { start, done } = useNProgress() + +const { loadStart, loadDone } = usePageLoading() + +const parseURL = ( + url: string | null | undefined +): { basePath: string; paramsObject: { [key: string]: string } } => { + // 如果输入为 null 或 undefined,返回空字符串和空对象 + if (url == null) { + return { basePath: '', paramsObject: {} } + } + + // 找到问号 (?) 的位置,它之前是基础路径,之后是查询参数 + const questionMarkIndex = url.indexOf('?') + let basePath = url + const paramsObject: { [key: string]: string } = {} + + // 如果找到了问号,说明有查询参数 + if (questionMarkIndex !== -1) { + // 获取 basePath + basePath = url.substring(0, questionMarkIndex) + + // 从 URL 中获取查询字符串部分 + const queryString = url.substring(questionMarkIndex + 1) + + // 使用 URLSearchParams 遍历参数 + const searchParams = new URLSearchParams(queryString) + searchParams.forEach((value, key) => { + // 封装进 paramsObject 对象 + paramsObject[key] = value + }) + } + + // 返回 basePath 和 paramsObject + return { basePath, paramsObject } +} + +// 路由不重定向白名单 +const whiteList = [ + '/login', + '/social-login', + '/auth-redirect', + '/bind', + '/register', + '/oauthLogin/gitee' +] + +// 路由加载前 +router.beforeEach(async (to, from, next) => { + start() + loadStart() + if (getAccessToken()) { + if (to.path === '/login') { + next({ path: '/' }) + } else { + // 获取所有字典 + const dictStore = useDictStoreWithOut() + const userStore = useUserStoreWithOut() + const permissionStore = usePermissionStoreWithOut() + if (!dictStore.getIsSetDict) { + await dictStore.setDictMap() + } + if (!userStore.getIsSetUser) { + isRelogin.show = true + await userStore.setUserInfoAction() + isRelogin.show = false + // 后端过滤菜单 + await permissionStore.generateRoutes() + permissionStore.getAddRouters.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 + }) + const redirectPath = from.query.redirect || to.path + // 修复跳转时不带参数的问题 + const redirect = decodeURIComponent(redirectPath as string) + const { paramsObject: query } = parseURL(redirect) + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query } + next(nextData) + } else { + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { + next() + } else { + next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 + } + } +}) + +router.afterEach((to) => { + useTitle(to?.meta?.title as string) + done() // 结束Progress + loadDone() +}) diff --git a/src/plugins/animate.css/index.ts b/src/plugins/animate.css/index.ts new file mode 100644 index 0000000..3e93451 --- /dev/null +++ b/src/plugins/animate.css/index.ts @@ -0,0 +1 @@ +import 'animate.css' diff --git a/src/plugins/echarts/index.ts b/src/plugins/echarts/index.ts new file mode 100644 index 0000000..18d05aa --- /dev/null +++ b/src/plugins/echarts/index.ts @@ -0,0 +1,49 @@ +import * as echarts from 'echarts/core' + +import { + BarChart, + FunnelChart, + GaugeChart, + LineChart, + MapChart, + PictorialBarChart, + PieChart, + RadarChart +} from 'echarts/charts' + +import { + AriaComponent, + GridComponent, + LegendComponent, + ParallelComponent, + PolarComponent, + TitleComponent, + ToolboxComponent, + TooltipComponent, + VisualMapComponent +} from 'echarts/components' + +import { CanvasRenderer } from 'echarts/renderers' + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + ToolboxComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + VisualMapComponent, + BarChart, + LineChart, + PieChart, + MapChart, + CanvasRenderer, + PictorialBarChart, + RadarChart, + GaugeChart, + FunnelChart +]) + +export default echarts diff --git a/src/plugins/elementPlus/index.ts b/src/plugins/elementPlus/index.ts new file mode 100644 index 0000000..0ae2a8b --- /dev/null +++ b/src/plugins/elementPlus/index.ts @@ -0,0 +1,17 @@ +import type { App } from 'vue' +// 需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题 +import { ElLoading, ElScrollbar, ElButton } from 'element-plus' + +const plugins = [ElLoading] + +const components = [ElScrollbar, ElButton] + +export const setupElementPlus = (app: App) => { + plugins.forEach((plugin) => { + app.use(plugin) + }) + + components.forEach((component) => { + app.component(component.name, component) + }) +} diff --git a/src/plugins/formCreate/index.ts b/src/plugins/formCreate/index.ts new file mode 100644 index 0000000..07d2c51 --- /dev/null +++ b/src/plugins/formCreate/index.ts @@ -0,0 +1,133 @@ +import type { App } from 'vue' +// 👇使用 form-create 需额外全局引入 element plus 组件 +import { + // ElAutocomplete, + // ElButton, + // ElCascader, + // ElCheckbox, + // ElCheckboxButton, + // ElCheckboxGroup, + // ElCol, + // ElColorPicker, + // ElDatePicker, + // ElDialog, + // ElForm, + // ElInput, + // ElInputNumber, + // ElPopover, + // ElRadio, + // ElRadioButton, + // ElRadioGroup, + // ElRate, + // ElRow, + // ElSelect, + // ElSlider, + // ElSwitch, + // ElTimePicker, + // ElTooltip, + // ElTree, + // ElUpload, + // ElIcon, + // ElProgress, + // 以上会由 @form-create/element-ui/auto-import 自动引入 + ElAlert, + ElTransfer, + ElAside, + ElContainer, + ElDivider, + ElHeader, + ElMain, + ElPopconfirm, + ElTable, + ElTableColumn, + ElTabPane, + ElTabs, + ElDropdown, + ElDropdownMenu, + ElDropdownItem, + ElBadge, + ElTag, + ElText, + ElMenu, + ElMenuItem, + ElFooter, + ElMessage, + ElCollapse, + ElCollapseItem, + ElCard, + // ElFormItem, + // ElOption +} from 'element-plus' +import FcDesigner from '@form-create/designer' +import formCreate from '@form-create/element-ui' +import install from '@form-create/element-ui/auto-import' + +//======================= 自定义组件 ======================= +import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile' +import { useApiSelect } from '@/components/FormCreate' +import { Editor } from '@/components/Editor' +import DictSelect from '@/components/FormCreate/src/components/DictSelect.vue' + +const UserSelect = useApiSelect({ + name: 'UserSelect', + labelField: 'nickname', + valueField: 'id', + url: '/system/user/simple-list' +}) +const DeptSelect = useApiSelect({ + name: 'DeptSelect', + labelField: 'name', + valueField: 'id', + url: '/system/dept/simple-list' +}) +const ApiSelect = useApiSelect({ + name: 'ApiSelect' +}) + +const components = [ + ElAlert, + ElTransfer, + ElAside, + ElContainer, + ElDivider, + ElHeader, + ElMain, + ElPopconfirm, + ElTable, + ElTableColumn, + ElTabPane, + ElTabs, + ElDropdown, + ElDropdownMenu, + ElDropdownItem, + ElBadge, + ElTag, + ElText, + ElMenu, + ElMenuItem, + ElFooter, + ElMessage, + // ElFormItem, + // ElOption, + UploadImg, + UploadImgs, + UploadFile, + DictSelect, + UserSelect, + DeptSelect, + ApiSelect, + Editor, + ElCollapse, + ElCollapseItem, + ElCard, +] + +// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档 +export const setupFormCreate = (app: App) => { + components.forEach((component) => { + app.component(component.name, component) + }) + formCreate.use(install) + app.use(formCreate) + app.use(FcDesigner) +} diff --git a/src/plugins/svgIcon/index.ts b/src/plugins/svgIcon/index.ts new file mode 100644 index 0000000..b5b7f70 --- /dev/null +++ b/src/plugins/svgIcon/index.ts @@ -0,0 +1,3 @@ +import 'virtual:svg-icons-register' + +import '@purge-icons/generated' diff --git a/src/plugins/tongji/index.ts b/src/plugins/tongji/index.ts new file mode 100644 index 0000000..ec261a1 --- /dev/null +++ b/src/plugins/tongji/index.ts @@ -0,0 +1,23 @@ +import router from '@/router' + +// 用于 router push +window._hmt = window._hmt || [] +// HM_ID +const HM_ID = import.meta.env.VITE_APP_BAIDU_CODE +;(function () { + // 有值的时候,才开启 + if (!HM_ID) { + return + } + const hm = document.createElement('script') + hm.src = 'https://hm.baidu.com/hm.js?' + HM_ID + const s = document.getElementsByTagName('script')[0] + s.parentNode.insertBefore(hm, s) +})() + +router.afterEach(function (to) { + if (!HM_ID) { + return + } + _hmt.push(['_trackPageview', to.fullPath]) +}) diff --git a/src/plugins/unocss/index.ts b/src/plugins/unocss/index.ts new file mode 100644 index 0000000..d366b5a --- /dev/null +++ b/src/plugins/unocss/index.ts @@ -0,0 +1 @@ +import 'virtual:uno.css' diff --git a/src/plugins/vueI18n/helper.ts b/src/plugins/vueI18n/helper.ts new file mode 100644 index 0000000..da6bc8c --- /dev/null +++ b/src/plugins/vueI18n/helper.ts @@ -0,0 +1,3 @@ +export const setHtmlPageLang = (locale: LocaleType) => { + document.querySelector('html')?.setAttribute('lang', locale) +} diff --git a/src/plugins/vueI18n/index.ts b/src/plugins/vueI18n/index.ts new file mode 100644 index 0000000..f845b13 --- /dev/null +++ b/src/plugins/vueI18n/index.ts @@ -0,0 +1,42 @@ +import type { App } from 'vue' +import { createI18n } from 'vue-i18n' +import { useLocaleStoreWithOut } from '@/store/modules/locale' +import type { I18n, I18nOptions } from 'vue-i18n' +import { setHtmlPageLang } from './helper' + +export let i18n: ReturnType + +const createI18nOptions = async (): Promise => { + const localeStore = useLocaleStoreWithOut() + const locale = localeStore.getCurrentLocale + const localeMap = localeStore.getLocaleMap + const defaultLocal = await import(`../../locales/${locale.lang}.ts`) + const message = defaultLocal.default ?? {} + + setHtmlPageLang(locale.lang) + + localeStore.setCurrentLocale({ + lang: locale.lang + // elLocale: elLocal + }) + + return { + legacy: false, + locale: locale.lang, + fallbackLocale: locale.lang, + messages: { + [locale.lang]: message + }, + availableLocales: localeMap.map((v) => v.lang), + sync: true, + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true + } +} + +export const setupI18n = async (app: App) => { + const options = await createI18nOptions() + i18n = createI18n(options) as I18n + app.use(i18n) +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..b818421 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,28 @@ +import type { App } from 'vue' +import type { RouteRecordRaw } from 'vue-router' +import { createRouter, createWebHistory } from 'vue-router' +import remainingRouter from './modules/remaining' + +// 创建路由实例 +const router = createRouter({ + history: createWebHistory(import.meta.env.VITE_BASE_PATH), // createWebHashHistory URL带#,createWebHistory URL不带# + strict: true, + routes: remainingRouter as RouteRecordRaw[], + scrollBehavior: () => ({ left: 0, top: 0 }) +}) + +export const resetRouter = (): void => { + const resetWhiteNameList = ['Redirect', 'Login', 'NoFind', 'Root'] + router.getRoutes().forEach((route) => { + const { name } = route + if (name && !resetWhiteNameList.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name) + } + }) +} + +export const setupRouter = (app: App) => { + app.use(router) +} + +export default router diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts new file mode 100644 index 0000000..806f954 --- /dev/null +++ b/src/router/modules/remaining.ts @@ -0,0 +1,670 @@ +import { Layout } from '@/utils/routerHelper' + +const { t } = useI18n() +/** + * redirect: noredirect 当设置 noredirect 的时候该路由在面包屑导航中不可被点击 + * name:'router-name' 设定路由的名字,一定要填写不然使用时会出现各种问题 + * meta : { + hidden: true 当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false) + + alwaysShow: true 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式, + 只有一个时,会将那个子路由当做根路由显示在侧边栏, + 若你想不管路由下面的 children 声明的个数都显示你的根路由, + 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则, + 一直显示根路由(默认 false) + + title: 'title' 设置该路由在侧边栏和面包屑中展示的名字 + + icon: 'svg-name' 设置该路由的图标 + + noCache: true 如果设置为true,则不会被 缓存(默认 false) + + breadcrumb: false 如果设置为false,则不会在breadcrumb面包屑中显示(默认 true) + + affix: true 如果设置为true,则会一直固定在tag项中(默认 false) + + noTagsView: true 如果设置为true,则不会出现在tag中(默认 false) + + activeMenu: '/dashboard' 显示高亮的路由路径 + + followAuth: '/dashboard' 跟随哪个路由进行权限过滤 + + canTo: true 设置为true即使hidden为true,也依然可以进行路由跳转(默认 false) + } + **/ +const remainingRouter: AppRouteRecordRaw[] = [ + { + path: '/redirect', + component: Layout, + name: 'Redirect', + children: [ + { + path: '/redirect/:path(.*)', + name: 'Redirect', + component: () => import('@/views/Redirect/Redirect.vue'), + meta: {} + } + ], + meta: { + hidden: true, + noTagsView: true + } + }, + { + path: '/', + component: Layout, + redirect: '/index', + name: 'Home', + meta: {}, + children: [ + { + path: 'index', + component: () => import('@/views/Home/Index.vue'), + name: 'Index', + meta: { + title: t('router.home'), + icon: 'ep:home-filled', + noCache: false, + affix: true + } + } + ] + }, + { + path: '/user', + component: Layout, + name: 'UserInfo', + meta: { + hidden: true + }, + children: [ + { + path: 'profile', + component: () => import('@/views/Profile/Index.vue'), + name: 'Profile', + meta: { + canTo: true, + hidden: true, + noTagsView: false, + icon: 'ep:user', + title: t('common.profile') + } + }, + { + path: 'notify-message', + component: () => import('@/views/system/notify/my/index.vue'), + name: 'MyNotifyMessage', + meta: { + canTo: true, + hidden: true, + noTagsView: false, + icon: 'ep:message', + title: '我的站内信' + } + } + ] + }, + { + path: '/dict', + component: Layout, + name: 'dict', + meta: { + hidden: true + }, + children: [ + { + path: 'type/data/:dictType', + component: () => import('@/views/system/dict/data/index.vue'), + name: 'SystemDictData', + meta: { + title: '字典数据', + noCache: true, + hidden: true, + canTo: true, + icon: '', + activeMenu: '/system/dict' + } + } + ] + }, + + { + path: '/codegen', + component: Layout, + name: 'CodegenEdit', + meta: { + hidden: true + }, + children: [ + { + path: 'edit', + component: () => import('@/views/infra/codegen/EditTable.vue'), + name: 'InfraCodegenEditTable', + meta: { + noCache: true, + hidden: true, + canTo: true, + icon: 'ep:edit', + title: '修改生成配置', + activeMenu: 'infra/codegen/index' + } + } + ] + }, + { + path: '/job', + component: Layout, + name: 'JobL', + meta: { + hidden: true + }, + children: [ + { + path: 'job-log', + component: () => import('@/views/infra/job/logger/index.vue'), + name: 'InfraJobLog', + meta: { + noCache: true, + hidden: true, + canTo: true, + icon: 'ep:edit', + title: '调度日志', + activeMenu: 'infra/job/index' + } + } + ] + }, + { + path: '/login', + component: () => import('@/views/Login/Login.vue'), + name: 'Login', + meta: { + hidden: true, + title: t('router.login'), + noTagsView: true + } + }, + { + path: '/sso', + component: () => import('@/views/Login/Login.vue'), + name: 'SSOLogin', + meta: { + hidden: true, + title: t('router.login'), + noTagsView: true + } + }, + { + path: '/social-login', + component: () => import('@/views/Login/SocialLogin.vue'), + name: 'SocialLogin', + meta: { + hidden: true, + title: t('router.socialLogin'), + noTagsView: true + } + }, + { + path: '/403', + component: () => import('@/views/Error/403.vue'), + name: 'NoAccess', + meta: { + hidden: true, + title: '403', + noTagsView: true + } + }, + { + path: '/404', + component: () => import('@/views/Error/404.vue'), + name: 'NoFound', + meta: { + hidden: true, + title: '404', + noTagsView: true + } + }, + { + path: '/500', + component: () => import('@/views/Error/500.vue'), + name: 'Error', + meta: { + hidden: true, + title: '500', + noTagsView: true + } + }, + { + path: '/bpm', + component: Layout, + name: 'bpm', + meta: { + hidden: true + }, + children: [ + { + path: 'manager/form/edit', + component: () => import('@/views/bpm/form/editor/index.vue'), + name: 'BpmFormEditor', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '设计流程表单', + activeMenu: '/bpm/manager/form' + } + }, + { + path: 'manager/model/edit', + component: () => import('@/views/bpm/model/editor/index.vue'), + name: 'BpmModelEditor', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '设计流程', + activeMenu: '/bpm/manager/model' + } + }, + { + path: 'manager/simple/model', + component: () => import('@/views/bpm/simple/SimpleModelDesign.vue'), + name: 'SimpleModelDesign', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '仿钉钉设计流程', + activeMenu: '/bpm/manager/model' + } + }, + { + path: 'manager/definition', + component: () => import('@/views/bpm/definition/index.vue'), + name: 'BpmProcessDefinition', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '流程定义', + activeMenu: '/bpm/manager/model' + } + }, + { + path: 'process-instance/detail', + component: () => import('@/views/bpm/processInstance/detail/index.vue'), + name: 'BpmProcessInstanceDetail', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '流程详情', + activeMenu: '/bpm/task/my' + }, + props: (route) => ({ + id: route.query.id, + taskId: route.query.taskId, + activityId: route.query.activityId + }) + }, + { + path: 'oa/leave/create', + component: () => import('@/views/bpm/oa/leave/create.vue'), + name: 'OALeaveCreate', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '发起 OA 请假', + activeMenu: '/bpm/oa/leave' + } + }, + { + path: 'oa/leave/detail', + component: () => import('@/views/bpm/oa/leave/detail.vue'), + name: 'OALeaveDetail', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '查看 OA 请假', + activeMenu: '/bpm/oa/leave' + } + }, + { + path: 'manager/model/create', + component: () => import('@/views/bpm/model/form/index.vue'), + name: 'BpmModelCreate', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '创建流程', + activeMenu: '/bpm/manager/model' + } + }, + { + path: 'manager/model/update/:id', + component: () => import('@/views/bpm/model/form/index.vue'), + name: 'BpmModelUpdate', + meta: { + noCache: true, + hidden: true, + canTo: true, + title: '修改流程', + activeMenu: '/bpm/manager/model' + } + } + ] + }, + { + path: '/mall/product', // 商品中心 + component: Layout, + name: 'ProductCenter', + meta: { + hidden: true + }, + children: [ + { + path: 'spu/add', + component: () => import('@/views/mall/product/spu/form/index.vue'), + name: 'ProductSpuAdd', + meta: { + noCache: false, // 需要缓存 + hidden: true, + canTo: true, + icon: 'ep:edit', + title: '商品添加', + activeMenu: '/mall/product/spu' + } + }, + { + path: 'spu/edit/:id(\\d+)', + component: () => import('@/views/mall/product/spu/form/index.vue'), + name: 'ProductSpuEdit', + meta: { + noCache: true, + hidden: true, + canTo: true, + icon: 'ep:edit', + title: '商品编辑', + activeMenu: '/mall/product/spu' + } + }, + { + path: 'spu/detail/:id(\\d+)', + component: () => import('@/views/mall/product/spu/form/index.vue'), + name: 'ProductSpuDetail', + meta: { + noCache: true, + hidden: true, + canTo: true, + icon: 'ep:view', + title: '商品详情', + activeMenu: '/mall/product/spu' + } + }, + { + path: 'property/value/:propertyId(\\d+)', + component: () => import('@/views/mall/product/property/value/index.vue'), + name: 'ProductPropertyValue', + meta: { + noCache: true, + hidden: true, + canTo: true, + icon: 'ep:view', + title: '商品属性值', + activeMenu: '/product/property' + } + } + ] + }, + { + path: '/mall/trade', // 交易中心 + component: Layout, + name: 'TradeCenter', + meta: { + hidden: true + }, + children: [ + { + path: 'order/detail/:id(\\d+)', + component: () => import('@/views/mall/trade/order/detail/index.vue'), + name: 'TradeOrderDetail', + meta: { title: '订单详情', icon: 'ep:view', activeMenu: '/mall/trade/order' } + }, + { + path: 'after-sale/detail/:id(\\d+)', + component: () => import('@/views/mall/trade/afterSale/detail/index.vue'), + name: 'TradeAfterSaleDetail', + meta: { title: '退款详情', icon: 'ep:view', activeMenu: '/mall/trade/after-sale' } + } + ] + }, + { + path: '/member', + component: Layout, + name: 'MemberCenter', + meta: { hidden: true }, + children: [ + { + path: 'user/detail/:id', + name: 'MemberUserDetail', + meta: { + title: '会员详情', + noCache: true, + hidden: true + }, + component: () => import('@/views/member/user/detail/index.vue') + } + ] + }, + { + path: '/pay', + component: Layout, + name: 'pay', + meta: { hidden: true }, + children: [ + { + path: 'cashier', + name: 'PayCashier', + meta: { + title: '收银台', + noCache: true, + hidden: true + }, + component: () => import('@/views/pay/cashier/index.vue') + } + ] + }, + { + path: '/diy', + name: 'DiyCenter', + meta: { hidden: true }, + component: Layout, + children: [ + { + path: 'template/decorate/:id', + name: 'DiyTemplateDecorate', + meta: { + title: '模板装修', + noCache: true, + hidden: true, + activeMenu: '/mall/promotion/diy/template' + }, + component: () => import('@/views/mall/promotion/diy/template/decorate.vue') + }, + { + path: 'page/decorate/:id', + name: 'DiyPageDecorate', + meta: { + title: '页面装修', + noCache: true, + hidden: true, + activeMenu: '/mall/promotion/diy/page' + }, + component: () => import('@/views/mall/promotion/diy/page/decorate.vue') + } + ] + }, + { + path: '/crm', + component: Layout, + name: 'CrmCenter', + meta: { hidden: true }, + children: [ + { + path: 'clue/detail/:id', + name: 'CrmClueDetail', + meta: { + title: '线索详情', + noCache: true, + hidden: true, + activeMenu: '/crm/clue' + }, + component: () => import('@/views/crm/clue/detail/index.vue') + }, + { + path: 'customer/detail/:id', + name: 'CrmCustomerDetail', + meta: { + title: '客户详情', + noCache: true, + hidden: true, + activeMenu: '/crm/customer' + }, + component: () => import('@/views/crm/customer/detail/index.vue') + }, + { + path: 'business/detail/:id', + name: 'CrmBusinessDetail', + meta: { + title: '商机详情', + noCache: true, + hidden: true, + activeMenu: '/crm/business' + }, + component: () => import('@/views/crm/business/detail/index.vue') + }, + { + path: 'contract/detail/:id', + name: 'CrmContractDetail', + meta: { + title: '合同详情', + noCache: true, + hidden: true, + activeMenu: '/crm/contract' + }, + component: () => import('@/views/crm/contract/detail/index.vue') + }, + { + path: 'receivable-plan/detail/:id', + name: 'CrmReceivablePlanDetail', + meta: { + title: '回款计划详情', + noCache: true, + hidden: true, + activeMenu: '/crm/receivable-plan' + }, + component: () => import('@/views/crm/receivable/plan/detail/index.vue') + }, + { + path: 'receivable/detail/:id', + name: 'CrmReceivableDetail', + meta: { + title: '回款详情', + noCache: true, + hidden: true, + activeMenu: '/crm/receivable' + }, + component: () => import('@/views/crm/receivable/detail/index.vue') + }, + { + path: 'contact/detail/:id', + name: 'CrmContactDetail', + meta: { + title: '联系人详情', + noCache: true, + hidden: true, + activeMenu: '/crm/contact' + }, + component: () => import('@/views/crm/contact/detail/index.vue') + }, + { + path: 'product/detail/:id', + name: 'CrmProductDetail', + meta: { + title: '产品详情', + noCache: true, + hidden: true, + activeMenu: '/crm/product' + }, + component: () => import('@/views/crm/product/detail/index.vue') + } + ] + }, + { + path: '/ai', + component: Layout, + name: 'Ai', + meta: { + hidden: true + }, + children: [ + { + path: 'image/square', + component: () => import('@/views/ai/image/square/index.vue'), + name: 'AiImageSquare', + meta: { + title: '绘图作品', + icon: 'ep:home-filled', + noCache: false + } + } + ] + }, + { + path: '/:pathMatch(.*)*', + component: () => import('@/views/Error/404.vue'), + name: '', + meta: { + title: '404', + hidden: true, + breadcrumb: false + } + }, + { + path: '/iot', + component: Layout, + name: 'IOT', + meta: { + hidden: true + }, + children: [ + { + path: 'product/detail/:id', + name: 'IoTProductDetail', + meta: { + title: '产品详情', + noCache: true, + hidden: true, + activeMenu: '/iot/product' + }, + component: () => import('@/views/iot/product/detail/index.vue') + }, + { + path: 'device/detail/:id', + name: 'IoTDeviceDetail', + meta: { + title: '设备详情', + noCache: true, + hidden: true, + activeMenu: '/iot/device' + }, + component: () => import('@/views/iot/device/detail/index.vue') + } + ] + } +] + +export default remainingRouter diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..63f0045 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,12 @@ +import type { App } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +const store = createPinia() +store.use(piniaPluginPersistedstate) + +export const setupStore = (app: App) => { + app.use(store) +} + +export { store } diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts new file mode 100644 index 0000000..e3d6a56 --- /dev/null +++ b/src/store/modules/app.ts @@ -0,0 +1,285 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import { humpToUnderline, setCssVar } from '@/utils' +import { ElMessage } from 'element-plus' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' +import { ElementPlusSize } from '@/types/elementPlus' +import { LayoutType } from '@/types/layout' +import { ThemeTypes } from '@/types/theme' + +const { wsCache } = useCache() + +interface AppState { + breadcrumb: boolean + breadcrumbIcon: boolean + collapse: boolean + uniqueOpened: boolean + hamburger: boolean + screenfull: boolean + search: boolean + size: boolean + locale: boolean + message: boolean + tagsView: boolean + tagsViewImmerse: boolean + tagsViewIcon: boolean + logo: boolean + fixedHeader: boolean + greyMode: boolean + pageLoading: boolean + layout: LayoutType + title: string + userInfo: string + isDark: boolean + currentSize: ElementPlusSize + sizeMap: ElementPlusSize[] + mobile: boolean + footer: boolean + theme: ThemeTypes + fixedMenu: boolean +} + +export const useAppStore = defineStore('app', { + state: (): AppState => { + return { + userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突 + sizeMap: ['default', 'large', 'small'], + mobile: false, // 是否是移动端 + title: import.meta.env.VITE_APP_TITLE, // 标题 + pageLoading: false, // 路由跳转loading + + breadcrumb: true, // 面包屑 + breadcrumbIcon: true, // 面包屑图标 + collapse: false, // 折叠菜单 + uniqueOpened: true, // 是否只保持一个子菜单的展开 + hamburger: true, // 折叠图标 + screenfull: true, // 全屏图标 + search: true, // 搜索图标 + size: true, // 尺寸图标 + locale: true, // 多语言图标 + message: true, // 消息图标 + tagsView: true, // 标签页 + tagsViewImmerse: false, // 标签页沉浸 + tagsViewIcon: true, // 是否显示标签图标 + logo: true, // logo + fixedHeader: true, // 固定toolheader + footer: true, // 显示页脚 + greyMode: false, // 是否开始灰色模式,用于特殊悼念日 + fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单 + + layout: wsCache.get(CACHE_KEY.LAYOUT) || 'classic', // layout布局 + isDark: wsCache.get(CACHE_KEY.IS_DARK) || false, // 是否是暗黑模式 + currentSize: wsCache.get('default') || 'default', // 组件尺寸 + theme: wsCache.get(CACHE_KEY.THEME) || { + // 主题色 + elColorPrimary: '#409eff', + // 左侧菜单边框颜色 + leftMenuBorderColor: 'inherit', + // 左侧菜单背景颜色 + leftMenuBgColor: '#001529', + // 左侧菜单浅色背景颜色 + leftMenuBgLightColor: '#0f2438', + // 左侧菜单选中背景颜色 + leftMenuBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单收起选中背景颜色 + leftMenuCollapseBgActiveColor: 'var(--el-color-primary)', + // 左侧菜单字体颜色 + leftMenuTextColor: '#bfcbd9', + // 左侧菜单选中字体颜色 + leftMenuTextActiveColor: '#fff', + // logo字体颜色 + logoTitleTextColor: '#fff', + // logo边框颜色 + logoBorderColor: 'inherit', + // 头部背景颜色 + topHeaderBgColor: '#fff', + // 头部字体颜色 + topHeaderTextColor: 'inherit', + // 头部悬停颜色 + topHeaderHoverColor: '#f6f6f6', + // 头部边框颜色 + topToolBorderColor: '#eee' + } + } + }, + getters: { + getBreadcrumb(): boolean { + return this.breadcrumb + }, + getBreadcrumbIcon(): boolean { + return this.breadcrumbIcon + }, + getCollapse(): boolean { + return this.collapse + }, + getUniqueOpened(): boolean { + return this.uniqueOpened + }, + getHamburger(): boolean { + return this.hamburger + }, + getScreenfull(): boolean { + return this.screenfull + }, + getSize(): boolean { + return this.size + }, + getLocale(): boolean { + return this.locale + }, + getMessage(): boolean { + return this.message + }, + getTagsView(): boolean { + return this.tagsView + }, + getTagsViewImmerse(): boolean { + return this.tagsViewImmerse + }, + getTagsViewIcon(): boolean { + return this.tagsViewIcon + }, + getLogo(): boolean { + return this.logo + }, + getFixedHeader(): boolean { + return this.fixedHeader + }, + getGreyMode(): boolean { + return this.greyMode + }, + getFixedMenu(): boolean { + return this.fixedMenu + }, + getPageLoading(): boolean { + return this.pageLoading + }, + getLayout(): LayoutType { + return this.layout + }, + getTitle(): string { + return this.title + }, + getUserInfo(): string { + return this.userInfo + }, + getIsDark(): boolean { + return this.isDark + }, + getCurrentSize(): ElementPlusSize { + return this.currentSize + }, + getSizeMap(): ElementPlusSize[] { + return this.sizeMap + }, + getMobile(): boolean { + return this.mobile + }, + getTheme(): ThemeTypes { + return this.theme + }, + getFooter(): boolean { + return this.footer + } + }, + actions: { + setBreadcrumb(breadcrumb: boolean) { + this.breadcrumb = breadcrumb + }, + setBreadcrumbIcon(breadcrumbIcon: boolean) { + this.breadcrumbIcon = breadcrumbIcon + }, + setCollapse(collapse: boolean) { + this.collapse = collapse + }, + setUniqueOpened(uniqueOpened: boolean) { + this.uniqueOpened = uniqueOpened + }, + setHamburger(hamburger: boolean) { + this.hamburger = hamburger + }, + setScreenfull(screenfull: boolean) { + this.screenfull = screenfull + }, + setSize(size: boolean) { + this.size = size + }, + setLocale(locale: boolean) { + this.locale = locale + }, + setMessage(message: boolean) { + this.message = message + }, + setTagsView(tagsView: boolean) { + this.tagsView = tagsView + }, + setTagsViewImmerse(tagsViewImmerse: boolean) { + this.tagsViewImmerse = tagsViewImmerse + }, + setTagsViewIcon(tagsViewIcon: boolean) { + this.tagsViewIcon = tagsViewIcon + }, + setLogo(logo: boolean) { + this.logo = logo + }, + setFixedHeader(fixedHeader: boolean) { + this.fixedHeader = fixedHeader + }, + setGreyMode(greyMode: boolean) { + this.greyMode = greyMode + }, + setFixedMenu(fixedMenu: boolean) { + wsCache.set('fixedMenu', fixedMenu) + this.fixedMenu = fixedMenu + }, + setPageLoading(pageLoading: boolean) { + this.pageLoading = pageLoading + }, + setLayout(layout: LayoutType) { + if (this.mobile && layout !== 'classic') { + ElMessage.warning('移动端模式下不支持切换其他布局') + return + } + this.layout = layout + wsCache.set(CACHE_KEY.LAYOUT, this.layout) + }, + setTitle(title: string) { + this.title = title + }, + setIsDark(isDark: boolean) { + this.isDark = isDark + if (this.isDark) { + document.documentElement.classList.add('dark') + document.documentElement.classList.remove('light') + } else { + document.documentElement.classList.add('light') + document.documentElement.classList.remove('dark') + } + wsCache.set(CACHE_KEY.IS_DARK, this.isDark) + }, + setCurrentSize(currentSize: ElementPlusSize) { + this.currentSize = currentSize + wsCache.set('currentSize', this.currentSize) + }, + setMobile(mobile: boolean) { + this.mobile = mobile + }, + setTheme(theme: ThemeTypes) { + this.theme = Object.assign(this.theme, theme) + wsCache.set(CACHE_KEY.THEME, this.theme) + }, + setCssVarTheme() { + for (const key in this.theme) { + setCssVar(`--${humpToUnderline(key)}`, this.theme[key]) + } + }, + setFooter(footer: boolean) { + this.footer = footer + } + }, + persist: false +}) + +export const useAppStoreWithOut = () => { + return useAppStore(store) +} diff --git a/src/store/modules/bpm/simpleWorkflow.ts b/src/store/modules/bpm/simpleWorkflow.ts new file mode 100644 index 0000000..2942951 --- /dev/null +++ b/src/store/modules/bpm/simpleWorkflow.ts @@ -0,0 +1,55 @@ +import { store } from '../../index' +import { defineStore } from 'pinia' + +export const useWorkFlowStore = defineStore('simpleWorkflow', { + state: () => ({ + tableId: '', + isTried: false, + promoterDrawer: false, + approverDrawer: false, + approverConfig1: {}, + copyerDrawer: false, + copyerConfig: {}, + conditionDrawer: false, + conditionsConfig1: { + conditionNodes: [] + }, + userTaskConfig: {} + }), + actions: { + setTableId(payload) { + this.tableId = payload + }, + setIsTried(payload) { + this.isTried = payload + }, + setPromoter(payload) { + this.promoterDrawer = payload + }, + setApproverDrawer(payload) { + this.approverDrawer = payload + }, + setApproverConfig(payload) { + this.approverConfig1 = payload + }, + setCopyerDrawer(payload) { + this.copyerDrawer = payload + }, + setCopyerConfig(payload) { + this.copyerConfig = payload + }, + setCondition(payload) { + this.conditionDrawer = payload + }, + setConditionsConfig(payload) { + this.conditionsConfig1 = payload + }, + setUserTaskConfig(payload) { + this.userTaskConfig = payload + } + } +}) + +export const useWorkFlowStoreWithOut = () => { + return useWorkFlowStore(store) +} diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts new file mode 100644 index 0000000..e239fb0 --- /dev/null +++ b/src/store/modules/dict.ts @@ -0,0 +1,104 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +// @ts-ignore +import { DictDataVO } from '@/api/system/dict/types' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' +const { wsCache } = useCache('sessionStorage') +import { getSimpleDictDataList } from '@/api/system/dict/dict.data' + +export interface DictValueType { + value: any + label: string + clorType?: string + cssClass?: string +} +export interface DictTypeType { + dictType: string + dictValue: DictValueType[] +} +export interface DictState { + dictMap: Map + isSetDict: boolean +} + +export const useDictStore = defineStore('dict', { + state: (): DictState => ({ + dictMap: new Map(), + isSetDict: false + }), + getters: { + getDictMap(): Recordable { + const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE) + if (dictMap) { + this.dictMap = dictMap + } + return this.dictMap + }, + getIsSetDict(): boolean { + return this.isSetDict + } + }, + actions: { + async setDictMap() { + const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE) + if (dictMap) { + this.dictMap = dictMap + this.isSetDict = true + } else { + const res = await getSimpleDictDataList() + // 设置数据 + const dictDataMap = new Map() + res.forEach((dictData: DictDataVO) => { + // 获得 dictType 层级 + const enumValueObj = dictDataMap[dictData.dictType] + if (!enumValueObj) { + dictDataMap[dictData.dictType] = [] + } + // 处理 dictValue 层级 + dictDataMap[dictData.dictType].push({ + value: dictData.value, + label: dictData.label, + colorType: dictData.colorType, + cssClass: dictData.cssClass + }) + }) + this.dictMap = dictDataMap + this.isSetDict = true + wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期 + } + }, + getDictByType(type: string) { + if (!this.isSetDict) { + this.setDictMap() + } + return this.dictMap[type] + }, + async resetDict() { + wsCache.delete(CACHE_KEY.DICT_CACHE) + const res = await getSimpleDictDataList() + // 设置数据 + const dictDataMap = new Map() + res.forEach((dictData: DictDataVO) => { + // 获得 dictType 层级 + const enumValueObj = dictDataMap[dictData.dictType] + if (!enumValueObj) { + dictDataMap[dictData.dictType] = [] + } + // 处理 dictValue 层级 + dictDataMap[dictData.dictType].push({ + value: dictData.value, + label: dictData.label, + colorType: dictData.colorType, + cssClass: dictData.cssClass + }) + }) + this.dictMap = dictDataMap + this.isSetDict = true + wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期 + } + } +}) + +export const useDictStoreWithOut = () => { + return useDictStore(store) +} diff --git a/src/store/modules/locale.ts b/src/store/modules/locale.ts new file mode 100644 index 0000000..1fc772a --- /dev/null +++ b/src/store/modules/locale.ts @@ -0,0 +1,59 @@ +import { defineStore } from 'pinia' +import { store } from '../index' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import en from 'element-plus/es/locale/lang/en' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' +import { LocaleDropdownType } from '@/types/localeDropdown' + +const { wsCache } = useCache() + +const elLocaleMap = { + 'zh-CN': zhCn, + en: en +} +interface LocaleState { + currentLocale: LocaleDropdownType + localeMap: LocaleDropdownType[] +} + +export const useLocaleStore = defineStore('locales', { + state: (): LocaleState => { + return { + currentLocale: { + lang: wsCache.get(CACHE_KEY.LANG) || 'zh-CN', + elLocale: elLocaleMap[wsCache.get(CACHE_KEY.LANG) || 'zh-CN'] + }, + // 多语言 + localeMap: [ + { + lang: 'zh-CN', + name: '简体中文' + }, + { + lang: 'en', + name: 'English' + } + ] + } + }, + getters: { + getCurrentLocale(): LocaleDropdownType { + return this.currentLocale + }, + getLocaleMap(): LocaleDropdownType[] { + return this.localeMap + } + }, + actions: { + setCurrentLocale(localeMap: LocaleDropdownType) { + // this.locale = Object.assign(this.locale, localeMap) + this.currentLocale.lang = localeMap?.lang + this.currentLocale.elLocale = elLocaleMap[localeMap?.lang] + wsCache.set(CACHE_KEY.LANG, localeMap?.lang) + } + } +}) + +export const useLocaleStoreWithOut = () => { + return useLocaleStore(store) +} diff --git a/src/store/modules/lock.ts b/src/store/modules/lock.ts new file mode 100644 index 0000000..68ae1d7 --- /dev/null +++ b/src/store/modules/lock.ts @@ -0,0 +1,48 @@ +import { defineStore } from 'pinia' +import { store } from '@/store' + +interface lockInfo { + isLock?: boolean + password?: string +} + +interface LockState { + lockInfo: lockInfo +} + +export const useLockStore = defineStore('lock', { + state: (): LockState => { + return { + lockInfo: { + // isLock: false, // 是否锁定屏幕 + // password: '' // 锁屏密码 + } + } + }, + getters: { + getLockInfo(): lockInfo { + return this.lockInfo + } + }, + actions: { + setLockInfo(lockInfo: lockInfo) { + this.lockInfo = lockInfo + }, + resetLockInfo() { + this.lockInfo = {} + }, + unLock(password: string) { + if (this.lockInfo?.password === password) { + this.resetLockInfo() + return true + } else { + return false + } + } + }, + persist: true +}) + +export const useLockStoreWithOut = () => { + return useLockStore(store) +} diff --git a/src/store/modules/mall/kefu.ts b/src/store/modules/mall/kefu.ts new file mode 100644 index 0000000..2aecee0 --- /dev/null +++ b/src/store/modules/mall/kefu.ts @@ -0,0 +1,81 @@ +import { store } from '@/store' +import { defineStore } from 'pinia' +import { KeFuConversationApi, KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation' +import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message' +import { isEmpty } from '@/utils/is' + +interface MallKefuInfoVO { + conversationList: KeFuConversationRespVO[] // 会话列表 + conversationMessageList: Map // 会话消息 +} + +export const useMallKefuStore = defineStore('mall-kefu', { + state: (): MallKefuInfoVO => ({ + conversationList: [], + conversationMessageList: new Map() // key 会话,value 会话消息列表 + }), + getters: { + getConversationList(): KeFuConversationRespVO[] { + return this.conversationList + }, + getConversationMessageList(): (conversationId: number) => KeFuMessageRespVO[] | undefined { + return (conversationId: number) => this.conversationMessageList.get(conversationId) + } + }, + actions: { + // ======================= 会话消息相关 ======================= + /** 缓存历史消息 */ + saveMessageList(conversationId: number, messageList: KeFuMessageRespVO[]) { + this.conversationMessageList.set(conversationId, messageList) + }, + + // ======================= 会话相关 ======================= + /** 加载会话缓存列表 */ + async setConversationList() { + this.conversationList = await KeFuConversationApi.getConversationList() + this.conversationSort() + }, + /** 更新会话缓存已读 */ + async updateConversationStatus(conversationId: number) { + if (isEmpty(this.conversationList)) { + return + } + const conversation = this.conversationList.find((item) => item.id === conversationId) + conversation && (conversation.adminUnreadMessageCount = 0) + }, + /** 更新会话缓存 */ + async updateConversation(conversationId: number) { + if (isEmpty(this.conversationList)) { + return + } + + const conversation = await KeFuConversationApi.getConversation(conversationId) + this.deleteConversation(conversationId) + conversation && this.conversationList.push(conversation) + this.conversationSort() + }, + /** 删除会话缓存 */ + deleteConversation(conversationId: number) { + const index = this.conversationList.findIndex((item) => item.id === conversationId) + // 存在则删除 + if (index > -1) { + this.conversationList.splice(index, 1) + } + }, + conversationSort() { + // 按置顶属性和最后消息时间排序 + this.conversationList.sort((a, b) => { + // 按照置顶排序,置顶的会在前面 + if (a.adminPinned !== b.adminPinned) { + return a.adminPinned ? -1 : 1 + } + // 按照最后消息时间排序,最近的会在前面 + return (b.lastMessageTime as unknown as number) - (a.lastMessageTime as unknown as number) + }) + } + } +}) + +export const useMallKefuStoreWithOut = () => { + return useMallKefuStore(store) +} diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts new file mode 100644 index 0000000..2ff8111 --- /dev/null +++ b/src/store/modules/permission.ts @@ -0,0 +1,71 @@ +import { defineStore } from 'pinia' +import { store } from '@/store' +import { cloneDeep } from 'lodash-es' +import remainingRouter from '@/router/modules/remaining' +import { flatMultiLevelRoutes, generateRoute } from '@/utils/routerHelper' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' + +const { wsCache } = useCache() + +export interface PermissionState { + routers: AppRouteRecordRaw[] + addRouters: AppRouteRecordRaw[] + menuTabRouters: AppRouteRecordRaw[] +} + +export const usePermissionStore = defineStore('permission', { + state: (): PermissionState => ({ + routers: [], + addRouters: [], + menuTabRouters: [] + }), + getters: { + getRouters(): AppRouteRecordRaw[] { + return this.routers + }, + getAddRouters(): AppRouteRecordRaw[] { + return flatMultiLevelRoutes(cloneDeep(this.addRouters)) + }, + getMenuTabRouters(): AppRouteRecordRaw[] { + return this.menuTabRouters + } + }, + actions: { + async generateRoutes(): Promise { + return new Promise(async (resolve) => { + // 获得菜单列表,它在登录的时候,setUserInfoAction 方法中已经进行获取 + let res: AppCustomRouteRecordRaw[] = [] + const roleRouters = wsCache.get(CACHE_KEY.ROLE_ROUTERS) + if (roleRouters) { + res = roleRouters as AppCustomRouteRecordRaw[] + } + const routerMap: AppRouteRecordRaw[] = generateRoute(res) + // 动态路由,404一定要放到最后面 + // preschooler:vue-router@4以后已支持静态404路由,此处可不再追加 + this.addRouters = routerMap.concat([ + { + path: '/:path(.*)*', + // redirect: '/404', + component: () => import('@/views/Error/404.vue'), + name: '404Page', + meta: { + hidden: true, + breadcrumb: false + } + } + ]) + // 渲染菜单的所有路由 + this.routers = cloneDeep(remainingRouter).concat(routerMap) + resolve() + }) + }, + setMenuTabRouters(routers: AppRouteRecordRaw[]): void { + this.menuTabRouters = routers + } + }, + persist: false +}) + +export const usePermissionStoreWithOut = () => { + return usePermissionStore(store) +} diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts new file mode 100644 index 0000000..4368efe --- /dev/null +++ b/src/store/modules/tagsView.ts @@ -0,0 +1,155 @@ +import router from '@/router' +import type { RouteLocationNormalizedLoaded } from 'vue-router' +import { getRawRoute } from '@/utils/routerHelper' +import { defineStore } from 'pinia' +import { store } from '../index' +import { findIndex } from '@/utils' + +export interface TagsViewState { + visitedViews: RouteLocationNormalizedLoaded[] + cachedViews: Set +} + +export const useTagsViewStore = defineStore('tagsView', { + state: (): TagsViewState => ({ + visitedViews: [], + cachedViews: new Set() + }), + getters: { + getVisitedViews(): RouteLocationNormalizedLoaded[] { + return this.visitedViews + }, + getCachedViews(): string[] { + return Array.from(this.cachedViews) + } + }, + actions: { + // 新增缓存和tag + addView(view: RouteLocationNormalizedLoaded): void { + this.addVisitedView(view) + this.addCachedView() + }, + // 新增tag + addVisitedView(view: RouteLocationNormalizedLoaded) { + if (this.visitedViews.some((v) => v.fullPath === view.fullPath)) return + if (view.meta?.noTagsView) return + const visitedView = Object.assign({}, view, { title: view.meta?.title || 'no-name' }) + + if (visitedView.meta) { + const titleSuffixList: string[] = [] + this.visitedViews.forEach((v) => { + if (v.path === visitedView.path && v.meta?.title === visitedView.meta?.title) { + titleSuffixList.push(v.meta?.titleSuffix || '1') + } + }) + if (titleSuffixList.length) { + let titleSuffix = 1 + while (titleSuffixList.includes(`${titleSuffix}`)) { + titleSuffix += 1 + } + visitedView.meta.titleSuffix = titleSuffix === 1 ? undefined : `${titleSuffix}` + } + } + + this.visitedViews.push(visitedView) + }, + // 新增缓存 + addCachedView() { + const cacheMap: Set = new Set() + for (const v of this.visitedViews) { + const item = getRawRoute(v) + const needCache = !item.meta?.noCache + if (!needCache) { + continue + } + const name = item.name as string + cacheMap.add(name) + } + if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString()) + return + this.cachedViews = cacheMap + }, + // 删除某个 + delView(view: RouteLocationNormalizedLoaded) { + this.delVisitedView(view) + this.delCachedView() + }, + // 删除tag + delVisitedView(view: RouteLocationNormalizedLoaded) { + for (const [i, v] of this.visitedViews.entries()) { + if (v.fullPath === view.fullPath) { + this.visitedViews.splice(i, 1) + break + } + } + }, + // 删除缓存 + delCachedView() { + const route = router.currentRoute.value + const index = findIndex(this.getCachedViews, (v) => v === route.name) + if (index > -1) { + this.cachedViews.delete(this.getCachedViews[index]) + } + }, + // 删除所有缓存和tag + delAllViews() { + this.delAllVisitedViews() + this.delCachedView() + }, + // 删除所有tag + delAllVisitedViews() { + // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) + this.visitedViews = [] + }, + // 删除其他 + delOthersViews(view: RouteLocationNormalizedLoaded) { + this.delOthersVisitedViews(view) + this.addCachedView() + }, + // 删除其他tag + delOthersVisitedViews(view: RouteLocationNormalizedLoaded) { + this.visitedViews = this.visitedViews.filter((v) => { + return v?.meta?.affix || v.fullPath === view.fullPath + }) + }, + // 删除左侧 + delLeftViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.fullPath === view.fullPath + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.fullPath === view.fullPath || i > index + }) + this.addCachedView() + } + }, + // 删除右侧 + delRightViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.fullPath === view.fullPath + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.fullPath === view.fullPath || i < index + }) + this.addCachedView() + } + }, + updateVisitedView(view: RouteLocationNormalizedLoaded) { + for (let v of this.visitedViews) { + if (v.fullPath === view.fullPath) { + v = Object.assign(v, view) + break + } + } + } + }, + persist: false +}) + +export const useTagsViewStoreWithOut = () => { + return useTagsViewStore(store) +} diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..b386180 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,103 @@ +import { store } from '@/store' +import { defineStore } from 'pinia' +import { getAccessToken, removeToken } from '@/utils/auth' +import { CACHE_KEY, useCache, deleteUserCache } from '@/hooks/web/useCache' +import { getInfo, loginOut } from '@/api/login' + +const { wsCache } = useCache() + +interface UserVO { + id: number + avatar: string + nickname: string + deptId: number +} + +interface UserInfoVO { + // USER 缓存 + permissions: string[] + roles: string[] + isSetUser: boolean + user: UserVO +} + +export const useUserStore = defineStore('admin-user', { + state: (): UserInfoVO => ({ + permissions: [], + roles: [], + isSetUser: false, + user: { + id: 0, + avatar: '', + nickname: '', + deptId: 0 + } + }), + getters: { + getPermissions(): string[] { + return this.permissions + }, + getRoles(): string[] { + return this.roles + }, + getIsSetUser(): boolean { + return this.isSetUser + }, + getUser(): UserVO { + return this.user + } + }, + actions: { + async setUserInfoAction() { + if (!getAccessToken()) { + this.resetState() + return null + } + let userInfo = wsCache.get(CACHE_KEY.USER) + if (!userInfo) { + userInfo = await getInfo() + } + this.permissions = userInfo.permissions + this.roles = userInfo.roles + this.user = userInfo.user + this.isSetUser = true + wsCache.set(CACHE_KEY.USER, userInfo) + wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus) + }, + async setUserAvatarAction(avatar: string) { + const userInfo = wsCache.get(CACHE_KEY.USER) + // NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null` + this.user.avatar = avatar + userInfo.user.avatar = avatar + wsCache.set(CACHE_KEY.USER, userInfo) + }, + async setUserNicknameAction(nickname: string) { + const userInfo = wsCache.get(CACHE_KEY.USER) + // NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null` + this.user.nickname = nickname + userInfo.user.nickname = nickname + wsCache.set(CACHE_KEY.USER, userInfo) + }, + async loginOut() { + await loginOut() + removeToken() + deleteUserCache() // 删除用户缓存 + this.resetState() + }, + resetState() { + this.permissions = [] + this.roles = [] + this.isSetUser = false + this.user = { + id: 0, + avatar: '', + nickname: '', + deptId: 0 + } + } + } +}) + +export const useUserStoreWithOut = () => { + return useUserStore(store) +} diff --git a/src/styles/FormCreate/fonts/fontello.woff b/src/styles/FormCreate/fonts/fontello.woff new file mode 100644 index 0000000..1e00f49 Binary files /dev/null and b/src/styles/FormCreate/fonts/fontello.woff differ diff --git a/src/styles/FormCreate/index.scss b/src/styles/FormCreate/index.scss new file mode 100644 index 0000000..bb62000 --- /dev/null +++ b/src/styles/FormCreate/index.scss @@ -0,0 +1,22 @@ +// 使用字体图标来源 https://fontello.com/ + +@font-face { + font-family: 'fc-icon'; + src: url('@/styles/FormCreate/fonts/fontello.woff') format('woff'); +} + +.icon-doc-text:before { + content: '\f0f6'; +} + +.icon-server:before { + content: '\f233'; +} + +.icon-address-card-o:before { + content: '\f2bc'; +} + +.icon-user-o:before { + content: '\f2c0'; +} diff --git a/src/styles/global.module.scss b/src/styles/global.module.scss new file mode 100644 index 0000000..af793f0 --- /dev/null +++ b/src/styles/global.module.scss @@ -0,0 +1,6 @@ +@use './variables.scss' as *; +// 导出变量 +:export { + namespace: $namespace; + elNamespace: $elNamespace; +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..7607941 --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,37 @@ +@use './var.css'; +@use './FormCreate/index.scss'; +@use './theme.scss'; +@use 'element-plus/theme-chalk/dark/css-vars.css'; + +.reset-margin [class*='el-icon'] + span { + margin-left: 2px !important; +} + +// 解决抽屉弹出时,body宽度变化的问题 +.el-popup-parent--hidden { + width: 100% !important; +} + +// 解决表格内容超过表格总宽度后,横向滚动条前端顶不到表格边缘的问题 +.el-scrollbar__bar { + display: flex; + justify-content: flex-start; +} + +/* nprogress 适配 element-plus 的主题色 */ +#nprogress { + & .bar { + background-color: var(--el-color-primary) !important; + } + + & .peg { + box-shadow: + 0 0 10px var(--el-color-primary), + 0 0 5px var(--el-color-primary) !important; + } + + & .spinner-icon { + border-top-color: var(--el-color-primary); + border-left-color: var(--el-color-primary); + } +} diff --git a/src/styles/theme.scss b/src/styles/theme.scss new file mode 100644 index 0000000..39b03b3 --- /dev/null +++ b/src/styles/theme.scss @@ -0,0 +1,6 @@ +// .text-color { +// color: var(--el-text-color-regular); +// } +// .dark .dark\:text-color { +// color: rgba(255, 255, 255, var(--dark-text-color)); +// } diff --git a/src/styles/var.css b/src/styles/var.css new file mode 100644 index 0000000..44f9405 --- /dev/null +++ b/src/styles/var.css @@ -0,0 +1,74 @@ +:root { + --login-bg-color: #293146; + + --left-menu-max-width: 200px; + + --left-menu-min-width: 64px; + + --left-menu-bg-color: #001529; + + --left-menu-bg-light-color: #0f2438; + + --left-menu-bg-active-color: var(--el-color-primary); + + --left-menu-text-color: #bfcbd9; + + --left-menu-text-active-color: #fff; + + --left-menu-collapse-bg-active-color: var(--el-color-primary); + /* left menu end */ + + /* logo start */ + --logo-height: 50px; + + --logo-title-text-color: #fff; + /* logo end */ + + /* header start */ + --top-header-bg-color: '#fff'; + + --top-header-text-color: 'inherit'; + + --top-header-hover-color: #f6f6f6; + + --top-tool-height: var(--logo-height); + + --top-tool-p-x: 0; + + --tags-view-height: 35px; + /* header start */ + + /* tab menu start */ + --tab-menu-max-width: 80px; + + --tab-menu-min-width: 30px; + + --tab-menu-collapse-height: 36px; + /* tab menu end */ + + --app-content-padding: 20px; + + --app-content-bg-color: #f5f7f9; + + --app-footer-height: 50px; + + --transition-time-02: 0.2s; +} + +.dark { + --app-content-bg-color: var(--el-bg-color); +} + +html, +body { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +*, +:after, +:before { + margin: 0; + padding: 0; + box-sizing: border-box; +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..00b66f1 --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,4 @@ +// 命名空间 +$namespace: v; +// el命名空间 +$elNamespace: el; diff --git a/src/types/components.d.ts b/src/types/components.d.ts new file mode 100644 index 0000000..8de1f33 --- /dev/null +++ b/src/types/components.d.ts @@ -0,0 +1,56 @@ +export type ComponentName = + | 'Radio' + | 'RadioButton' + | 'Checkbox' + | 'CheckboxButton' + | 'Input' + | 'Autocomplete' + | 'InputNumber' + | 'Select' + | 'Cascader' + | 'Switch' + | 'Slider' + | 'TimePicker' + | 'DatePicker' + | 'Rate' + | 'ColorPicker' + | 'Transfer' + | 'Divider' + | 'TimeSelect' + | 'SelectV2' + | 'TreeSelect' + | 'InputPassword' + | 'Editor' + | 'UploadImg' + | 'UploadImgs' + | 'UploadFile' + +export type ColProps = { + span?: number + xs?: number + sm?: number + md?: number + lg?: number + xl?: number + tag?: string +} + +export type ComponentOptions = { + label?: string + value?: FormValueType + disabled?: boolean + key?: string | number + children?: ComponentOptions[] + options?: ComponentOptions[] +} & Recordable + +export type ComponentOptionsAlias = { + labelField?: string + valueField?: string +} + +export type ComponentProps = { + optionsAlias?: ComponentOptionsAlias + options?: ComponentOptions[] + optionsSlot?: boolean +} & Recordable diff --git a/src/types/configGlobal.d.ts b/src/types/configGlobal.d.ts new file mode 100644 index 0000000..f6d7b3c --- /dev/null +++ b/src/types/configGlobal.d.ts @@ -0,0 +1,4 @@ +import { ElementPlusSize } from './elementPlus' +export interface ConfigGlobalTypes { + size?: ElementPlusSize +} diff --git a/src/types/contextMenu.d.ts b/src/types/contextMenu.d.ts new file mode 100644 index 0000000..0738d0e --- /dev/null +++ b/src/types/contextMenu.d.ts @@ -0,0 +1,7 @@ +export type contextMenuSchema = { + disabled?: boolean + divided?: boolean + icon?: string + label: string + command?: (item: contextMenuSchema) => void +} diff --git a/src/types/descriptions.d.ts b/src/types/descriptions.d.ts new file mode 100644 index 0000000..af6d68c --- /dev/null +++ b/src/types/descriptions.d.ts @@ -0,0 +1,14 @@ +export interface DescriptionsSchema { + span?: number // 占多少分 + field: string // 字段名 + label?: string // label名 + mappedField?: string // 字段映射 + width?: string | number + minWidth?: string | number + align?: 'left' | 'center' | 'right' + labelAlign?: 'left' | 'center' | 'right' + className?: string + labelClassName?: string + dateFormat?: string // add by 星语:支持时间的格式化 + dictType?: string // add by 星语:支持 dict 字典数据 +} diff --git a/src/types/elementPlus.d.ts b/src/types/elementPlus.d.ts new file mode 100644 index 0000000..2c6b76e --- /dev/null +++ b/src/types/elementPlus.d.ts @@ -0,0 +1,3 @@ +export type ElementPlusSize = 'default' | 'small' | 'large' + +export type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger' diff --git a/src/types/form.d.ts b/src/types/form.d.ts new file mode 100644 index 0000000..980c8cc --- /dev/null +++ b/src/types/form.d.ts @@ -0,0 +1,44 @@ +import type { CSSProperties } from 'vue' +import { ColProps, ComponentProps, ComponentName } from '@/types/components' +import type { AxiosPromise } from 'axios' + +export type FormSetPropsType = { + field: string + path: string + value: any +} + +export type FormValueType = string | number | string[] | number[] | boolean | undefined | null + +export type FormItemProps = { + labelWidth?: string | number + required?: boolean + rules?: Recordable + error?: string + showMessage?: boolean + inlineMessage?: boolean + style?: CSSProperties +} + +export type FormSchema = { + // 唯一值 + field: string + // 标题 + label?: string + // 提示 + labelMessage?: string + // col组件属性 + colProps?: ColProps + // 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档 + componentProps?: { slots?: Recordable } & ComponentProps + // formItem组件属性 + formItemProps?: FormItemProps + // 渲染的组件 + component?: ComponentName + // 初始值 + value?: FormValueType + // 是否隐藏 + hidden?: boolean + // 远程加载下拉项 + api?: () => AxiosPromise +} diff --git a/src/types/icon.d.ts b/src/types/icon.d.ts new file mode 100644 index 0000000..d1ffcdb --- /dev/null +++ b/src/types/icon.d.ts @@ -0,0 +1,5 @@ +export interface IconTypes { + size?: number + color?: string + icon: string +} diff --git a/src/types/infoTip.d.ts b/src/types/infoTip.d.ts new file mode 100644 index 0000000..6eff083 --- /dev/null +++ b/src/types/infoTip.d.ts @@ -0,0 +1,4 @@ +export interface TipSchema { + label: string + keys?: string[] +} diff --git a/src/types/layout.d.ts b/src/types/layout.d.ts new file mode 100644 index 0000000..cad3e2a --- /dev/null +++ b/src/types/layout.d.ts @@ -0,0 +1 @@ +export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu' diff --git a/src/types/localeDropdown.d.ts b/src/types/localeDropdown.d.ts new file mode 100644 index 0000000..c749dce --- /dev/null +++ b/src/types/localeDropdown.d.ts @@ -0,0 +1,10 @@ +export interface Language { + el: Recordable + name: string +} + +export interface LocaleDropdownType { + lang: LocaleType + name?: string + elLocale?: Language +} diff --git a/src/types/qrcode.d.ts b/src/types/qrcode.d.ts new file mode 100644 index 0000000..86cdf0b --- /dev/null +++ b/src/types/qrcode.d.ts @@ -0,0 +1,9 @@ +export interface QrcodeLogo { + src?: string + logoSize?: number + bgColor?: string + borderSize?: number + crossOrigin?: string + borderRadius?: number + logoRadius?: number +} diff --git a/src/types/table.d.ts b/src/types/table.d.ts new file mode 100644 index 0000000..9cb4205 --- /dev/null +++ b/src/types/table.d.ts @@ -0,0 +1,44 @@ +export type TableColumn = { + field: string + label?: string + width?: number | string + fixed?: 'left' | 'right' + children?: TableColumn[] +} & Recordable + +export type VxeTableColumn = { + field: string + title?: string + children?: TableColumn[] +} & Recordable + +export type TableSlotDefault = { + row: Recordable + column: TableColumn + $index: number +} & Recordable + +export interface Pagination { + small?: boolean + background?: boolean + pageSize?: number + defaultPageSize?: number + total?: number + pageCount?: number + pagerCount?: number + currentPage?: number + defaultCurrentPage?: number + layout?: string + pageSizes?: number[] + popperClass?: string + prevText?: string + nextText?: string + disabled?: boolean + hideOnSinglePage?: boolean +} + +export interface TableSetPropsType { + field: string + path: string + value: any +} diff --git a/src/types/theme.d.ts b/src/types/theme.d.ts new file mode 100644 index 0000000..ad649b0 --- /dev/null +++ b/src/types/theme.d.ts @@ -0,0 +1,16 @@ +export type ThemeTypes = { + elColorPrimary?: string + leftMenuBorderColor?: string + leftMenuBgColor?: string + leftMenuBgLightColor?: string + leftMenuBgActiveColor?: string + leftMenuCollapseBgActiveColor?: string + leftMenuTextColor?: string + leftMenuTextActiveColor?: string + logoTitleTextColor?: string + logoBorderColor?: string + topHeaderBgColor?: string + topHeaderTextColor?: string + topHeaderHoverColor?: string + topToolBorderColor?: string +} diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts new file mode 100644 index 0000000..ca58df2 --- /dev/null +++ b/src/utils/Logger.ts @@ -0,0 +1,100 @@ +const isArray = function (obj: any): boolean { + return Object.prototype.toString.call(obj) === '[object Array]' +} + +const Logger = () => {} + +Logger.typeColor = function (type: string) { + let color = '' + switch (type) { + case 'primary': + color = '#2d8cf0' + break + case 'success': + color = '#19be6b' + break + case 'info': + color = '#909399' + break + case 'warn': + color = '#ff9900' + break + case 'error': + color = '#f03f14' + break + default: + color = '#35495E' + break + } + return color +} + +Logger.print = function (type = 'default', text: any, back = false) { + if (typeof text === 'object') { + // 如果是對象則調用打印對象方式 + isArray(text) ? console.table(text) : console.dir(text) + return + } + if (back) { + // 如果是打印帶背景圖的 + console.log( + `%c ${text} `, + `background:${Logger.typeColor(type)}; padding: 2px; border-radius: 4px; color: #fff;` + ) + } else { + console.log( + `%c ${text} `, + `border: 1px solid ${Logger.typeColor(type)}; + padding: 2px; border-radius: 4px; + color: ${Logger.typeColor(type)};` + ) + } +} + +Logger.printBack = function (type = 'primary', text) { + this.print(type, text, true) +} + +Logger.pretty = function (type = 'primary', title, text) { + if (typeof text === 'object') { + console.group('Console Group', title) + console.log( + `%c ${title}`, + `background:${Logger.typeColor(type)};border:1px solid ${Logger.typeColor(type)}; + padding: 1px; border-radius: 4px; color: #fff;` + ) + isArray(text) ? console.table(text) : console.dir(text) + console.groupEnd() + return + } + console.log( + `%c ${title} %c ${text} %c`, + `background:${Logger.typeColor(type)};border:1px solid ${Logger.typeColor(type)}; + padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`, + `border:1px solid ${Logger.typeColor(type)}; + padding: 1px; border-radius: 0 4px 4px 0; color: ${Logger.typeColor(type)};`, + 'background:transparent' + ) +} + +Logger.prettyPrimary = function (title, ...text) { + text.forEach((t) => this.pretty('primary', title, t)) +} + +Logger.prettySuccess = function (title, ...text) { + text.forEach((t) => this.pretty('success', title, t)) +} + +Logger.prettyWarn = function (title, ...text) { + text.forEach((t) => this.pretty('warn', title, t)) +} + +Logger.prettyError = function (title, ...text) { + text.forEach((t) => this.pretty('error', title, t)) +} + +Logger.prettyInfo = function (title, ...text) { + text.forEach((t) => this.pretty('info', title, t)) +} + +export default Logger diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..d9e8565 --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,72 @@ +import { useCache, CACHE_KEY } from '@/hooks/web/useCache' +import { TokenType } from '@/api/login/types' +import { decrypt, encrypt } from '@/utils/jsencrypt' + +const { wsCache } = useCache() + +const AccessTokenKey = 'ACCESS_TOKEN' +const RefreshTokenKey = 'REFRESH_TOKEN' + +// 获取token +export const getAccessToken = () => { + // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错 + const accessToken = wsCache.get(AccessTokenKey) + return accessToken ? accessToken : wsCache.get('ACCESS_TOKEN') +} + +// 刷新token +export const getRefreshToken = () => { + return wsCache.get(RefreshTokenKey) +} + +// 设置token +export const setToken = (token: TokenType) => { + wsCache.set(RefreshTokenKey, token.refreshToken) + wsCache.set(AccessTokenKey, token.accessToken) +} + +// 删除token +export const removeToken = () => { + wsCache.delete(AccessTokenKey) + wsCache.delete(RefreshTokenKey) +} + +/** 格式化token(jwt格式) */ +export const formatToken = (token: string): string => { + return 'Bearer ' + token +} +// ========== 账号相关 ========== + +export type LoginFormType = { + tenantName: string + username: string + password: string + rememberMe: boolean +} + +export const getLoginForm = () => { + const loginForm: LoginFormType = wsCache.get(CACHE_KEY.LoginForm) + if (loginForm) { + loginForm.password = decrypt(loginForm.password) as string + } + return loginForm +} + +export const setLoginForm = (loginForm: LoginFormType) => { + loginForm.password = encrypt(loginForm.password) as string + wsCache.set(CACHE_KEY.LoginForm, loginForm, { exp: 30 * 24 * 60 * 60 }) +} + +export const removeLoginForm = () => { + wsCache.delete(CACHE_KEY.LoginForm) +} + +// ========== 租户相关 ========== + +export const getTenantId = () => { + return wsCache.get(CACHE_KEY.TenantId) +} + +export const setTenantId = (username: string) => { + wsCache.set(CACHE_KEY.TenantId, username) +} diff --git a/src/utils/color.ts b/src/utils/color.ts new file mode 100644 index 0000000..13424e5 --- /dev/null +++ b/src/utils/color.ts @@ -0,0 +1,174 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export const isHexColor = (color: string) => { + const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/ + return reg.test(color) +} + +/** + * RGB 颜色值转换为 十六进制颜色值. + * r, g, 和 b 需要在 [0, 255] 范围内 + * + * @return String 类似#ff00ff + * @param r + * @param g + * @param b + */ +export const rgbToHex = (r: number, g: number, b: number) => { + // tslint:disable-next-line:no-bitwise + const hex = ((r << 16) | (g << 8) | b).toString(16) + return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex +} + +/** + * Transform a HEX color to its RGB representation + * @param {string} hex The color to transform + * @returns The RGB representation of the passed color + */ +export const hexToRGB = (hex: string, opacity?: number) => { + let sHex = hex.toLowerCase() + if (isHexColor(hex)) { + if (sHex.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)) + } + sHex = sColorNew + } + const sColorChange: number[] = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))) + } + return opacity + ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')' + : 'RGB(' + sColorChange.join(',') + ')' + } + return sHex +} + +export const colorIsDark = (color: string) => { + if (!isHexColor(color)) return + const [r, g, b] = hexToRGB(color) + .replace(/(?:\(|\)|rgb|RGB)*/g, '') + .split(',') + .map((item) => Number(item)) + return r * 0.299 + g * 0.578 + b * 0.114 < 192 +} + +/** + * Darkens a HEX color given the passed percentage + * @param {string} color The color to process + * @param {number} amount The amount to change the color by + * @returns {string} The HEX representation of the processed color + */ +export const darken = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount + )}${subtractLight(color.substring(4, 6), amount)}` +} + +/** + * Lightens a 6 char HEX color according to the passed percentage + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed color represented as HEX + */ +export const lighten = (color: string, amount: number) => { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount + )}${addLight(color.substring(4, 6), amount)}` +} + +/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ +/** + * Sums the passed percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const addLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) + amount + const c = cc > 255 ? 255 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +/** + * Calculates luminance of an rgb color + * @param {number} r red + * @param {number} g green + * @param {number} b blue + */ +const luminanace = (r: number, g: number, b: number) => { + const a = [r, g, b].map((v) => { + v /= 255 + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4) + }) + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722 +} + +/** + * Calculates contrast between two rgb colors + * @param {string} rgb1 rgb color 1 + * @param {string} rgb2 rgb color 2 + */ +const contrast = (rgb1: string[], rgb2: number[]) => { + return ( + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ) +} + +/** + * Determines what the best text color is (black or white) based con the contrast with the background + * @param hexColor - Last selected color by the user + */ +export const calculateBestTextColor = (hexColor: string) => { + const rgbColor = hexToRGB(hexColor.substring(1)) + const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]) + + return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF' +} + +/** + * Subtracts the indicated percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +const subtractLight = (color: string, amount: number) => { + const cc = parseInt(color, 16) - amount + const c = cc < 0 ? 0 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +// 预设颜色 +export const PREDEFINE_COLORS = [ + '#ff4500', + '#ff8c00', + '#ffd700', + '#90ee90', + '#00ced1', + '#1e90ff', + '#c71585', + '#409EFF', + '#909399', + '#C0C4CC', + '#b7390b', + '#ff7800', + '#fad400', + '#5b8c5f', + '#00babd', + '#1f73c3', + '#711f57' +] diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..692a45f --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,459 @@ +/** + * Created by 芋道源码 + * + * 枚举类 + */ + +// ========== COMMON 模块 ========== +// 全局通用状态枚举 +export const CommonStatusEnum = { + ENABLE: 0, // 开启 + DISABLE: 1 // 禁用 +} + +// 全局用户类型枚举 +export const UserTypeEnum = { + MEMBER: 1, // 会员 + ADMIN: 2 // 管理员 +} + +// ========== SYSTEM 模块 ========== +/** + * 菜单的类型枚举 + */ +export const SystemMenuTypeEnum = { + DIR: 1, // 目录 + MENU: 2, // 菜单 + BUTTON: 3 // 按钮 +} + +/** + * 角色的类型枚举 + */ +export const SystemRoleTypeEnum = { + SYSTEM: 1, // 内置角色 + CUSTOM: 2 // 自定义角色 +} + +/** + * 数据权限的范围枚举 + */ +export const SystemDataScopeEnum = { + ALL: 1, // 全部数据权限 + DEPT_CUSTOM: 2, // 指定部门数据权限 + DEPT_ONLY: 3, // 部门数据权限 + DEPT_AND_CHILD: 4, // 部门及以下数据权限 + DEPT_SELF: 5 // 仅本人数据权限 +} + +/** + * 用户的社交平台的类型枚举 + */ +export const SystemUserSocialTypeEnum = { + DINGTALK: { + title: '钉钉', + type: 20, + source: 'dingtalk', + img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png' + }, + WECHAT_ENTERPRISE: { + title: '企业微信', + type: 30, + source: 'wechat_enterprise', + img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png' + } +} + +// ========== INFRA 模块 ========== +/** + * 代码生成模板类型 + */ +export const InfraCodegenTemplateTypeEnum = { + CRUD: 1, // 基础 CRUD + TREE: 2, // 树形 CRUD + SUB: 3 // 主子表 CRUD +} + +/** + * 任务状态的枚举 + */ +export const InfraJobStatusEnum = { + INIT: 0, // 初始化中 + NORMAL: 1, // 运行中 + STOP: 2 // 暂停运行 +} + +/** + * API 异常数据的处理状态 + */ +export const InfraApiErrorLogProcessStatusEnum = { + INIT: 0, // 未处理 + DONE: 1, // 已处理 + IGNORE: 2 // 已忽略 +} + +// ========== PAY 模块 ========== +/** + * 支付渠道枚举 + */ +export const PayChannelEnum = { + WX_PUB: { + code: 'wx_pub', + name: '微信 JSAPI 支付' + }, + WX_LITE: { + code: 'wx_lite', + name: '微信小程序支付' + }, + WX_APP: { + code: 'wx_app', + name: '微信 APP 支付' + }, + WX_NATIVE: { + code: 'wx_native', + name: '微信 Native 支付' + }, + WX_WAP: { + code: 'wx_wap', + name: '微信 WAP 网站支付' + }, + WX_BAR: { + code: 'wx_bar', + name: '微信条码支付' + }, + ALIPAY_PC: { + code: 'alipay_pc', + name: '支付宝 PC 网站支付' + }, + ALIPAY_WAP: { + code: 'alipay_wap', + name: '支付宝 WAP 网站支付' + }, + ALIPAY_APP: { + code: 'alipay_app', + name: '支付宝 APP 支付' + }, + ALIPAY_QR: { + code: 'alipay_qr', + name: '支付宝扫码支付' + }, + ALIPAY_BAR: { + code: 'alipay_bar', + name: '支付宝条码支付' + }, + WALLET: { + code: 'wallet', + name: '钱包支付' + }, + MOCK: { + code: 'mock', + name: '模拟支付' + } +} + +/** + * 支付的展示模式每局 + */ +export const PayDisplayModeEnum = { + URL: { + mode: 'url' + }, + IFRAME: { + mode: 'iframe' + }, + FORM: { + mode: 'form' + }, + QR_CODE: { + mode: 'qr_code' + }, + APP: { + mode: 'app' + } +} + +/** + * 支付类型枚举 + */ +export const PayType = { + WECHAT: 'WECHAT', + ALIPAY: 'ALIPAY', + MOCK: 'MOCK' +} + +/** + * 支付订单状态枚举 + */ +export const PayOrderStatusEnum = { + WAITING: { + status: 0, + name: '未支付' + }, + SUCCESS: { + status: 10, + name: '已支付' + }, + CLOSED: { + status: 20, + name: '未支付' + } +} + +// ========== MALL - 商品模块 ========== +/** + * 商品 SPU 状态 + */ +export const ProductSpuStatusEnum = { + RECYCLE: { + status: -1, + name: '回收站' + }, + DISABLE: { + status: 0, + name: '下架' + }, + ENABLE: { + status: 1, + name: '上架' + } +} + +// ========== MALL - 营销模块 ========== +/** + * 优惠劵模板的有限期类型的枚举 + */ +export const CouponTemplateValidityTypeEnum = { + DATE: { + type: 1, + name: '固定日期可用' + }, + TERM: { + type: 2, + name: '领取之后可用' + } +} + +/** + * 优惠劵模板的领取方式的枚举 + */ +export const CouponTemplateTakeTypeEnum = { + USER: { + type: 1, + name: '直接领取' + }, + ADMIN: { + type: 2, + name: '指定发放' + }, + REGISTER: { + type: 3, + name: '新人券' + } +} + +/** + * 营销的商品范围枚举 + */ +export const PromotionProductScopeEnum = { + ALL: { + scope: 1, + name: '通用劵' + }, + SPU: { + scope: 2, + name: '商品劵' + }, + CATEGORY: { + scope: 3, + name: '品类劵' + } +} + +/** + * 营销的条件类型枚举 + */ +export const PromotionConditionTypeEnum = { + PRICE: { + type: 10, + name: '满 N 元' + }, + COUNT: { + type: 20, + name: '满 N 件' + } +} + +/** + * 优惠类型枚举 + */ +export const PromotionDiscountTypeEnum = { + PRICE: { + type: 1, + name: '满减' + }, + PERCENT: { + type: 2, + name: '折扣' + } +} + +// ========== MALL - 交易模块 ========== +/** + * 分销关系绑定模式枚举 + */ +export const BrokerageBindModeEnum = { + ANYTIME: { + mode: 1, + name: '首次绑定' + }, + REGISTER: { + mode: 2, + name: '注册绑定' + }, + OVERRIDE: { + mode: 3, + name: '覆盖绑定' + } +} +/** + * 分佣模式枚举 + */ +export const BrokerageEnabledConditionEnum = { + ALL: { + condition: 1, + name: '人人分销' + }, + ADMIN: { + condition: 2, + name: '指定分销' + } +} +/** + * 佣金记录业务类型枚举 + */ +export const BrokerageRecordBizTypeEnum = { + ORDER: { + type: 1, + name: '获得推广佣金' + }, + WITHDRAW: { + type: 2, + name: '提现申请' + } +} +/** + * 佣金提现状态枚举 + */ +export const BrokerageWithdrawStatusEnum = { + AUDITING: { + status: 0, + name: '审核中' + }, + AUDIT_SUCCESS: { + status: 10, + name: '审核通过' + }, + AUDIT_FAIL: { + status: 20, + name: '审核不通过' + }, + WITHDRAW_SUCCESS: { + status: 11, + name: '提现成功' + }, + WITHDRAW_FAIL: { + status: 21, + name: '提现失败' + } +} +/** + * 佣金提现类型枚举 + */ +export const BrokerageWithdrawTypeEnum = { + WALLET: { + type: 1, + name: '钱包' + }, + BANK: { + type: 2, + name: '银行卡' + }, + WECHAT: { + type: 3, + name: '微信' + }, + ALIPAY: { + type: 4, + name: '支付宝' + } +} + +/** + * 配送方式枚举 + */ +export const DeliveryTypeEnum = { + EXPRESS: { + type: 1, + name: '快递发货' + }, + PICK_UP: { + type: 2, + name: '到店自提' + } +} +/** + * 交易订单 - 状态 + */ +export const TradeOrderStatusEnum = { + UNPAID: { + status: 0, + name: '待支付' + }, + UNDELIVERED: { + status: 10, + name: '待发货' + }, + DELIVERED: { + status: 20, + name: '已发货' + }, + COMPLETED: { + status: 30, + name: '已完成' + }, + CANCELED: { + status: 40, + name: '已取消' + } +} + +// ========== ERP - 企业资源计划 ========== + +export const ErpBizType = { + PURCHASE_ORDER: 10, + PURCHASE_IN: 11, + PURCHASE_RETURN: 12, + SALE_ORDER: 20, + SALE_OUT: 21, + SALE_RETURN: 22 +} + +// ========== BPM 模块 ========== + +export const BpmModelType = { + BPMN: 10, // BPMN 设计器 + SIMPLE: 20 // 简易设计器 +} + +export const BpmModelFormType = { + NORMAL: 10, // 流程表单 + CUSTOM: 20 // 业务表单 +} + +export const BpmProcessInstanceStatus = { + NOT_START: -1, // 未开始 + RUNNING: 1, // 审批中 + APPROVE: 2, // 审批通过 + REJECT: 3, // 审批不通过 + CANCEL: 4 // 已取消 +} diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 0000000..316b870 --- /dev/null +++ b/src/utils/dateUtil.ts @@ -0,0 +1,18 @@ +/** + * Independent time operation tool to facilitate subsequent switch to dayjs + */ +// TODO 芋艿:【锁屏】可能后面删除掉 +import dayjs from 'dayjs' + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' +const DATE_FORMAT = 'YYYY-MM-DD' + +export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string { + return dayjs(date).format(format) +} + +export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string { + return dayjs(date).format(format) +} + +export const dateUtil = dayjs diff --git a/src/utils/dict.ts b/src/utils/dict.ts new file mode 100644 index 0000000..1134152 --- /dev/null +++ b/src/utils/dict.ts @@ -0,0 +1,243 @@ +/** + * 数据字典工具类 + */ +import { useDictStoreWithOut } from '@/store/modules/dict' +import { ElementPlusInfoType } from '@/types/elementPlus' + +const dictStore = useDictStoreWithOut() + +/** + * 获取 dictType 对应的数据字典数组 + * + * @param dictType 数据类型 + * @returns {*|Array} 数据字典数组 + */ +export interface DictDataType { + dictType: string + label: string + value: string | number | boolean + colorType: ElementPlusInfoType | '' + cssClass: string +} + +export interface NumberDictDataType extends DictDataType { + value: number +} + +export interface StringDictDataType extends DictDataType { + value: string +} + +export const getDictOptions = (dictType: string) => { + return dictStore.getDictByType(dictType) || [] +} + +export const getIntDictOptions = (dictType: string): NumberDictDataType[] => { + // 获得通用的 DictDataType 列表 + const dictOptions: DictDataType[] = getDictOptions(dictType) + // 转换成 number 类型的 NumberDictDataType 类型 + // why 需要特殊转换:避免 IDEA 在 v-for="dict in getIntDictOptions(...)" 时,el-option 的 key 会告警 + const dictOption: NumberDictDataType[] = [] + dictOptions.forEach((dict: DictDataType) => { + dictOption.push({ + ...dict, + value: parseInt(dict.value + '') + }) + }) + return dictOption +} + +export const getStrDictOptions = (dictType: string) => { + // 获得通用的 DictDataType 列表 + const dictOptions: DictDataType[] = getDictOptions(dictType) + // 转换成 string 类型的 StringDictDataType 类型 + // why 需要特殊转换:避免 IDEA 在 v-for="dict in getStrDictOptions(...)" 时,el-option 的 key 会告警 + const dictOption: StringDictDataType[] = [] + dictOptions.forEach((dict: DictDataType) => { + dictOption.push({ + ...dict, + value: dict.value + '' + }) + }) + return dictOption +} + +export const getBoolDictOptions = (dictType: string) => { + const dictOption: DictDataType[] = [] + const dictOptions: DictDataType[] = getDictOptions(dictType) + dictOptions.forEach((dict: DictDataType) => { + dictOption.push({ + ...dict, + value: dict.value + '' === 'true' + }) + }) + return dictOption +} + +/** + * 获取指定字典类型的指定值对应的字典对象 + * @param dictType 字典类型 + * @param value 字典值 + * @return DictDataType 字典对象 + */ +export const getDictObj = (dictType: string, value: any): DictDataType | undefined => { + const dictOptions: DictDataType[] = getDictOptions(dictType) + for (const dict of dictOptions) { + if (dict.value === value + '') { + return dict + } + } +} + +/** + * 获得字典数据的文本展示 + * + * @param dictType 字典类型 + * @param value 字典数据的值 + * @return 字典名称 + */ +export const getDictLabel = (dictType: string, value: any): string => { + const dictOptions: DictDataType[] = getDictOptions(dictType) + const dictLabel = ref('') + dictOptions.forEach((dict: DictDataType) => { + if (dict.value === value + '') { + dictLabel.value = dict.label + } + }) + return dictLabel.value +} + +export enum DICT_TYPE { + USER_TYPE = 'user_type', + COMMON_STATUS = 'common_status', + TERMINAL = 'terminal', // 终端 + DATE_INTERVAL = 'date_interval', // 数据间隔 + + // ========== SYSTEM 模块 ========== + SYSTEM_USER_SEX = 'system_user_sex', + SYSTEM_MENU_TYPE = 'system_menu_type', + SYSTEM_ROLE_TYPE = 'system_role_type', + SYSTEM_DATA_SCOPE = 'system_data_scope', + SYSTEM_NOTICE_TYPE = 'system_notice_type', + SYSTEM_LOGIN_TYPE = 'system_login_type', + SYSTEM_LOGIN_RESULT = 'system_login_result', + SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code', + SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type', + SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status', + SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status', + SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type', + SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status', + SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type', + SYSTEM_SOCIAL_TYPE = 'system_social_type', + + // ========== INFRA 模块 ========== + INFRA_BOOLEAN_STRING = 'infra_boolean_string', + INFRA_JOB_STATUS = 'infra_job_status', + INFRA_JOB_LOG_STATUS = 'infra_job_log_status', + INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status', + INFRA_CONFIG_TYPE = 'infra_config_type', + INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type', + INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type', + INFRA_CODEGEN_SCENE = 'infra_codegen_scene', + INFRA_FILE_STORAGE = 'infra_file_storage', + INFRA_OPERATE_TYPE = 'infra_operate_type', + + // ========== BPM 模块 ========== + BPM_MODEL_TYPE = 'bpm_model_type', + BPM_MODEL_FORM_TYPE = 'bpm_model_form_type', + BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy', + BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status', + BPM_TASK_STATUS = 'bpm_task_status', + BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type', + BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type', + BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type', + + // ========== PAY 模块 ========== + PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型 + PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态 + PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态 + PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态 + PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态 + PAY_TRANSFER_STATUS = 'pay_transfer_status', // 转账订单状态 + PAY_TRANSFER_TYPE = 'pay_transfer_type', // 转账订单状态 + + // ========== MP 模块 ========== + MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型 + MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型 + + // ========== Member 会员模块 ========== + MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型 + MEMBER_EXPERIENCE_BIZ_TYPE = 'member_experience_biz_type', // 会员经验业务类型 + + // ========== MALL - 商品模块 ========== + PRODUCT_SPU_STATUS = 'product_spu_status', //商品状态 + + // ========== MALL - 交易模块 ========== + EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode', //快递的计费方式 + TRADE_AFTER_SALE_STATUS = 'trade_after_sale_status', // 售后 - 状态 + TRADE_AFTER_SALE_WAY = 'trade_after_sale_way', // 售后 - 方式 + TRADE_AFTER_SALE_TYPE = 'trade_after_sale_type', // 售后 - 类型 + TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型 + TRADE_ORDER_STATUS = 'trade_order_status', // 订单 - 状态 + TRADE_ORDER_ITEM_AFTER_SALE_STATUS = 'trade_order_item_after_sale_status', // 订单项 - 售后状态 + TRADE_DELIVERY_TYPE = 'trade_delivery_type', // 配送方式 + BROKERAGE_ENABLED_CONDITION = 'brokerage_enabled_condition', // 分佣模式 + BROKERAGE_BIND_MODE = 'brokerage_bind_mode', // 分销关系绑定模式 + BROKERAGE_BANK_NAME = 'brokerage_bank_name', // 佣金提现银行 + BROKERAGE_WITHDRAW_TYPE = 'brokerage_withdraw_type', // 佣金提现类型 + BROKERAGE_RECORD_BIZ_TYPE = 'brokerage_record_biz_type', // 佣金业务类型 + BROKERAGE_RECORD_STATUS = 'brokerage_record_status', // 佣金状态 + BROKERAGE_WITHDRAW_STATUS = 'brokerage_withdraw_status', // 佣金提现状态 + + // ========== MALL - 营销模块 ========== + PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型 + PROMOTION_PRODUCT_SCOPE = 'promotion_product_scope', // 营销的商品范围 + PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE = 'promotion_coupon_template_validity_type', // 优惠劵模板的有限期类型 + PROMOTION_COUPON_STATUS = 'promotion_coupon_status', // 优惠劵的状态 + PROMOTION_COUPON_TAKE_TYPE = 'promotion_coupon_take_type', // 优惠劵的领取方式 + PROMOTION_CONDITION_TYPE = 'promotion_condition_type', // 营销的条件类型枚举 + PROMOTION_BARGAIN_RECORD_STATUS = 'promotion_bargain_record_status', // 砍价记录的状态 + PROMOTION_COMBINATION_RECORD_STATUS = 'promotion_combination_record_status', // 拼团记录的状态 + PROMOTION_BANNER_POSITION = 'promotion_banner_position', // banner 定位 + + // ========== CRM - 客户管理模块 ========== + CRM_AUDIT_STATUS = 'crm_audit_status', // CRM 审批状态 + CRM_BIZ_TYPE = 'crm_biz_type', // CRM 业务类型 + CRM_BUSINESS_END_STATUS_TYPE = 'crm_business_end_status_type', // CRM 商机结束状态类型 + CRM_RECEIVABLE_RETURN_TYPE = 'crm_receivable_return_type', // CRM 回款的还款方式 + CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry', // CRM 客户所属行业 + CRM_CUSTOMER_LEVEL = 'crm_customer_level', // CRM 客户级别 + CRM_CUSTOMER_SOURCE = 'crm_customer_source', // CRM 客户来源 + CRM_PRODUCT_STATUS = 'crm_product_status', // CRM 商品状态 + CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别 + CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位 + CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式 + + // ========== ERP - 企业资源计划模块 ========== + ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态 + ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型 + + // ========== AI - 人工智能模块 ========== + AI_PLATFORM = 'ai_platform', // AI 平台 + AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态 + AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态 + AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式 + AI_WRITE_TYPE = 'ai_write_type', // AI 写作类型 + AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度 + AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式 + AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气 + AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言 + + // ========== IOT - 物联网模块 ========== + IOT_NET_TYPE = 'iot_net_type', // IOT 联网方式 + IOT_VALIDATE_TYPE = 'iot_validate_type', // IOT 数据校验级别 + IOT_PRODUCT_STATUS = 'iot_product_status', // IOT 产品状态 + IOT_PRODUCT_DEVICE_TYPE = 'iot_product_device_type', // IOT 产品设备类型 + IOT_DATA_FORMAT = 'iot_data_format', // IOT 数据格式 + IOT_PROTOCOL_TYPE = 'iot_protocol_type', // IOT 接入网关协议 + IOT_DEVICE_STATUS = 'iot_device_status', // IOT 设备状态 + IOT_PRODUCT_FUNCTION_TYPE = 'iot_product_function_type', // IOT 产品功能类型 + IOT_DATA_TYPE = 'iot_data_type', // IOT 数据类型 + IOT_UNIT_TYPE = 'iot_unit_type', // IOT 单位类型 + IOT_RW_TYPE = 'iot_rw_type' // IOT 读写类型 +} diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts new file mode 100644 index 0000000..dbc1989 --- /dev/null +++ b/src/utils/domUtils.ts @@ -0,0 +1,289 @@ +import { isServer } from './is' +const ieVersion = isServer ? 0 : Number((document as any).documentMode) +const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g +const MOZ_HACK_REGEXP = /^moz([A-Z])/ + +export interface ViewportOffsetResult { + left: number + top: number + right: number + bottom: number + rightIncludeBody: number + bottomIncludeBody: number +} + +/* istanbul ignore next */ +const trim = function (string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') +} + +/* istanbul ignore next */ +const camelCase = function (name: string) { + return name + .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) { + return offset ? letter.toUpperCase() : letter + }) + .replace(MOZ_HACK_REGEXP, 'Moz$1') +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false + if (cls.indexOf(' ') !== -1) { + throw new Error('className should not contain space.') + } + if (el.classList) { + return el.classList.contains(cls) + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return + let curClass = el.className + const classes = (cls || '').split(' ') + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.add(clsName) + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName + } + } + if (!el.classList) { + el.className = curClass + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return + const classes = cls.split(' ') + let curClass = ' ' + el.className + ' ' + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.remove(clsName) + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' ') + } + } + if (!el.classList) { + el.className = trim(curClass) + } +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0 + } + return element.getBoundingClientRect() +} + +/** + * 获取当前元素的left、top偏移 + * left:元素最左侧距离文档左侧的距离 + * top:元素最顶端距离文档顶端的距离 + * right:元素最右侧距离文档右侧的距离 + * bottom:元素最底端距离文档底端的距离 + * rightIncludeBody:元素最左侧距离文档右侧的距离 + * bottomIncludeBody:元素最底端距离文档最底部的距离 + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement + + const docScrollLeft = doc.scrollLeft + const docScrollTop = doc.scrollTop + const docClientLeft = doc.clientLeft + const docClientTop = doc.clientTop + + const pageXOffset = window.pageXOffset + const pageYOffset = window.pageYOffset + + const box = getBoundingClientRect(element) + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0) + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0) + const offsetLeft = retLeft + pageXOffset + const offsetTop = rectTop + pageYOffset + + const left = offsetLeft - scrollLeft + const top = offsetTop - scrollTop + + const clientWidth = window.document.documentElement.clientWidth + const clientHeight = window.document.documentElement.clientHeight + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top + } +} + +/* istanbul ignore next */ +export const on = function ( + element: HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const off = function ( + element: HTMLElement | Document | Window, + event: string, + handler: any +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const once = function (el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + // @ts-ignore + fn.apply(this, args) + } + off(el, event, listener) + } + on(el, event, listener) +} + +/* istanbul ignore next */ +export const getStyle = + ieVersion < 9 + ? function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'styleFloat' + } + try { + switch (styleName) { + case 'opacity': + try { + return element.filters.item('alpha').opacity / 100 + } catch (e) { + return 1.0 + } + default: + return element.style[styleName] || element.currentStyle + ? element.currentStyle[styleName] + : null + } + } catch (e) { + return element.style[styleName] + } + } + : function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'cssFloat' + } + try { + const computed = (document as any).defaultView.getComputedStyle(element, '') + return element.style[styleName] || computed ? computed[styleName] : null + } catch (e) { + return element.style[styleName] + } + } + +/* istanbul ignore next */ +export function setStyle(element: Element | any, styleName: any, value: any) { + if (!element || !styleName) return + + if (typeof styleName === 'object') { + for (const prop in styleName) { + if (Object.prototype.hasOwnProperty.call(styleName, prop)) { + setStyle(element, prop, styleName[prop]) + } + } + } else { + styleName = camelCase(styleName) + if (styleName === 'opacity' && ieVersion < 9) { + element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')' + } else { + element.style[styleName] = value + } + } +} + +/* istanbul ignore next */ +export const isScroll = (el: Element, vertical: any) => { + if (isServer) return + + const determinedDirection = vertical !== null || vertical !== undefined + const overflow = determinedDirection + ? vertical + ? getStyle(el, 'overflow-y') + : getStyle(el, 'overflow-x') + : getStyle(el, 'overflow') + + return overflow.match(/(scroll|auto)/) +} + +/* istanbul ignore next */ +export const getScrollContainer = (el: Element, vertical?: any) => { + if (isServer) return + + let parent: any = el + while (parent) { + if ([window, document, document.documentElement].includes(parent)) { + return window + } + if (isScroll(parent, vertical)) { + return parent + } + parent = parent.parentNode + } + + return parent +} + +/* istanbul ignore next */ +export const isInContainer = (el: Element, container: any) => { + if (isServer || !el || !container) return false + + const elRect = el.getBoundingClientRect() + let containerRect + + if ([window, document, document.documentElement, null, undefined].includes(container)) { + containerRect = { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0 + } + } else { + containerRect = container.getBoundingClientRect() + } + + return ( + elRect.top < containerRect.bottom && + elRect.bottom > containerRect.top && + elRect.right > containerRect.left && + elRect.left < containerRect.right + ) +} diff --git a/src/utils/download.ts b/src/utils/download.ts new file mode 100644 index 0000000..5bbfb9f --- /dev/null +++ b/src/utils/download.ts @@ -0,0 +1,71 @@ +const download0 = (data: Blob, fileName: string, mineType: string) => { + // 创建 blob + const blob = new Blob([data], { type: mineType }) + // 创建 href 超链接,点击进行下载 + window.URL = window.URL || window.webkitURL + const href = URL.createObjectURL(blob) + const downA = document.createElement('a') + downA.href = href + downA.download = fileName + downA.click() + // 销毁超连接 + window.URL.revokeObjectURL(href) +} + +const download = { + // 下载 Excel 方法 + excel: (data: Blob, fileName: string) => { + download0(data, fileName, 'application/vnd.ms-excel') + }, + // 下载 Word 方法 + word: (data: Blob, fileName: string) => { + download0(data, fileName, 'application/msword') + }, + // 下载 Zip 方法 + zip: (data: Blob, fileName: string) => { + download0(data, fileName, 'application/zip') + }, + // 下载 Html 方法 + html: (data: Blob, fileName: string) => { + download0(data, fileName, 'text/html') + }, + // 下载 Markdown 方法 + markdown: (data: Blob, fileName: string) => { + download0(data, fileName, 'text/markdown') + }, + // 下载图片(允许跨域) + image: ({ + url, + canvasWidth, + canvasHeight, + drawWithImageSize = true + }: { + url: string + canvasWidth?: number // 指定画布宽度 + canvasHeight?: number // 指定画布高度 + drawWithImageSize?: boolean // 将图片绘制在画布上时带上图片的宽高值, 默认是要带上的 + }) => { + const image = new Image() + // image.setAttribute('crossOrigin', 'anonymous') + image.src = url + image.onload = () => { + const canvas = document.createElement('canvas') + canvas.width = canvasWidth || image.width + canvas.height = canvasHeight || image.height + const ctx = canvas.getContext('2d') as CanvasRenderingContext2D + ctx?.clearRect(0, 0, canvas.width, canvas.height) + if (drawWithImageSize) { + ctx.drawImage(image, 0, 0, image.width, image.height) + } else { + ctx.drawImage(image, 0, 0) + } + const url = canvas.toDataURL('image/png') + const a = document.createElement('a') + a.href = url + a.download = 'image.png' + a.click() + } + } +} + +export default download diff --git a/src/utils/filt.ts b/src/utils/filt.ts new file mode 100644 index 0000000..b1a7b2c --- /dev/null +++ b/src/utils/filt.ts @@ -0,0 +1,157 @@ +export const openWindow = ( + url: string, + opt?: { + target?: '_self' | '_blank' | string + noopener?: boolean + noreferrer?: boolean + } +) => { + const { target = '__blank', noopener = true, noreferrer = true } = opt || {} + const feature: string[] = [] + + noopener && feature.push('noopener=yes') + noreferrer && feature.push('noreferrer=yes') + + window.open(url, target, feature.join(',')) +} + +/** + * @description: base64 to blob + */ +export const dataURLtoBlob = (base64Buf: string): Blob => { + const arr = base64Buf.split(',') + const typeItem = arr[0] + const mime = typeItem.match(/:(.*?);/)![1] + const bstr = window.atob(arr[1]) + let n = bstr.length + const u8arr = new Uint8Array(n) + while (n--) { + u8arr[n] = bstr.charCodeAt(n) + } + return new Blob([u8arr], { type: mime }) +} + +/** + * img url to base64 + * @param url + */ +export const urlToBase64 = (url: string, mineType?: string): Promise => { + return new Promise((resolve, reject) => { + let canvas = document.createElement('CANVAS') as Nullable + const ctx = canvas!.getContext('2d') + + const img = new Image() + img.crossOrigin = '' + img.onload = function () { + if (!canvas || !ctx) { + return reject() + } + canvas.height = img.height + canvas.width = img.width + ctx.drawImage(img, 0, 0) + const dataURL = canvas.toDataURL(mineType || 'image/png') + canvas = null + resolve(dataURL) + } + img.src = url + }) +} + +/** + * Download online pictures + * @param url + * @param filename + * @param mime + * @param bom + */ +export const downloadByOnlineUrl = ( + url: string, + filename: string, + mime?: string, + bom?: BlobPart +) => { + urlToBase64(url).then((base64) => { + downloadByBase64(base64, filename, mime, bom) + }) +} + +/** + * Download pictures based on base64 + * @param buf + * @param filename + * @param mime + * @param bom + */ +export const downloadByBase64 = (buf: string, filename: string, mime?: string, bom?: BlobPart) => { + const base64Buf = dataURLtoBlob(buf) + downloadByData(base64Buf, filename, mime, bom) +} + +/** + * Download according to the background interface file stream + * @param {*} data + * @param {*} filename + * @param {*} mime + * @param {*} bom + */ +export const downloadByData = (data: BlobPart, filename: string, mime?: string, bom?: BlobPart) => { + const blobData = typeof bom !== 'undefined' ? [bom, data] : [data] + const blob = new Blob(blobData, { type: mime || 'application/octet-stream' }) + + const blobURL = window.URL.createObjectURL(blob) + const tempLink = document.createElement('a') + tempLink.style.display = 'none' + tempLink.href = blobURL + tempLink.setAttribute('download', filename) + if (typeof tempLink.download === 'undefined') { + tempLink.setAttribute('target', '_blank') + } + document.body.appendChild(tempLink) + tempLink.click() + document.body.removeChild(tempLink) + window.URL.revokeObjectURL(blobURL) +} + +/** + * Download file according to file address + * @param {*} sUrl + */ +export const downloadByUrl = ({ + url, + target = '_blank', + fileName +}: { + url: string + target?: '_self' | '_blank' + fileName?: string +}): boolean => { + const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1 + const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1 + + if (/(iP)/g.test(window.navigator.userAgent)) { + console.error('Your browser does not support download!') + return false + } + if (isChrome || isSafari) { + const link = document.createElement('a') + link.href = url + link.target = target + + if (link.download !== undefined) { + link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length) + } + + if (document.createEvent) { + const e = document.createEvent('MouseEvents') + e.initEvent('click', true, true) + link.dispatchEvent(e) + return true + } + } + if (url.indexOf('?') === -1) { + url += '?download' + } + + openWindow(url, { target }) + return true +} diff --git a/src/utils/formCreate.ts b/src/utils/formCreate.ts new file mode 100644 index 0000000..a93d9cd --- /dev/null +++ b/src/utils/formCreate.ts @@ -0,0 +1,58 @@ +/** + * 针对 https://github.com/xaboy/form-create-designer 封装的工具类 + */ + +// 编码表单 Conf +export const encodeConf = (designerRef: object) => { + // @ts-ignore + return JSON.stringify(designerRef.value.getOption()) +} + +// 编码表单 Fields +export const encodeFields = (designerRef: object) => { + // @ts-ignore + const rule = designerRef.value.getRule() + const fields: string[] = [] + rule.forEach((item) => { + fields.push(JSON.stringify(item)) + }) + return fields +} + +// 解码表单 Fields +export const decodeFields = (fields: string[]) => { + const rule: object[] = [] + fields.forEach((item) => { + rule.push(JSON.parse(item)) + }) + return rule +} + +// 设置表单的 Conf 和 Fields,适用 FcDesigner 场景 +export const setConfAndFields = (designerRef: object, conf: string, fields: string) => { + // @ts-ignore + designerRef.value.setOption(JSON.parse(conf)) + // @ts-ignore + designerRef.value.setRule(decodeFields(fields)) +} + +// 设置表单的 Conf 和 Fields,适用 form-create 场景 +export const setConfAndFields2 = ( + detailPreview: object, + conf: string, + fields: string[], + value?: object +) => { + if (isRef(detailPreview)) { + // @ts-ignore + detailPreview = detailPreview.value + } + // @ts-ignore + detailPreview.option = JSON.parse(conf) + // @ts-ignore + detailPreview.rule = decodeFields(fields) + if (value) { + // @ts-ignore + detailPreview.value = value + } +} diff --git a/src/utils/formRules.ts b/src/utils/formRules.ts new file mode 100644 index 0000000..2989867 --- /dev/null +++ b/src/utils/formRules.ts @@ -0,0 +1,7 @@ +const { t } = useI18n() + +// 必填项 +export const required = { + required: true, + message: t('common.required') +} diff --git a/src/utils/formatTime.ts b/src/utils/formatTime.ts new file mode 100644 index 0000000..99eb428 --- /dev/null +++ b/src/utils/formatTime.ts @@ -0,0 +1,332 @@ +import dayjs from 'dayjs' +import type { TableColumnCtx } from 'element-plus' + +/** + * 日期快捷选项适用于 el-date-picker + */ +export const defaultShortcuts = [ + { + text: '今天', + value: () => { + return new Date() + } + }, + { + text: '昨天', + value: () => { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24) + return [date, date] + } + }, + { + text: '最近七天', + value: () => { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7) + return [date, new Date()] + } + }, + { + text: '最近 30 天', + value: () => { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24 * 30) + return [date, new Date()] + } + }, + { + text: '本月', + value: () => { + const date = new Date() + date.setDate(1) // 设置为当前月的第一天 + return [date, new Date()] + } + }, + { + text: '今年', + value: () => { + const date = new Date() + return [new Date(`${date.getFullYear()}-01-01`), date] + } + } +] + +/** + * 时间日期转换 + * @param date 当前时间,new Date() 格式 + * @param format 需要转换的时间格式字符串 + * @description format 字符串随意,如 `YYYY-MM、YYYY-MM-DD` + * @description format 季度:"YYYY-MM-DD HH:mm:ss QQQQ" + * @description format 星期:"YYYY-MM-DD HH:mm:ss WWW" + * @description format 几周:"YYYY-MM-DD HH:mm:ss ZZZ" + * @description format 季度 + 星期 + 几周:"YYYY-MM-DD HH:mm:ss WWW QQQQ ZZZ" + * @returns 返回拼接后的时间字符串 + */ +export function formatDate(date: Date, format?: string): string { + // 日期不存在,则返回空 + if (!date) { + return '' + } + // 日期存在,则进行格式化 + return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : '' +} + +/** + * 获取当前的日期+时间 + */ +export function getNowDateTime() { + return dayjs() +} + +/** + * 获取当前日期是第几周 + * @param dateTime 当前传入的日期值 + * @returns 返回第几周数字值 + */ +export function getWeek(dateTime: Date): number { + const temptTime = new Date(dateTime.getTime()) + // 周几 + const weekday = temptTime.getDay() || 7 + // 周1+5天=周六 + temptTime.setDate(temptTime.getDate() - weekday + 1 + 5) + let firstDay = new Date(temptTime.getFullYear(), 0, 1) + const dayOfWeek = firstDay.getDay() + let spendDay = 1 + if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1 + firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay) + const d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000) + return Math.ceil(d / 7) +} + +/** + * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前` + * @param param 当前时间,new Date() 格式或者字符串时间格式 + * @param format 需要转换的时间格式字符串 + * @description param 10秒: 10 * 1000 + * @description param 1分: 60 * 1000 + * @description param 1小时: 60 * 60 * 1000 + * @description param 24小时:60 * 60 * 24 * 1000 + * @description param 3天: 60 * 60* 24 * 1000 * 3 + * @returns 返回拼接后的时间字符串 + */ +export function formatPast(param: string | Date, format = 'YYYY-MM-DD HH:mm:ss'): string { + // 传入格式处理、存储转换值 + let t: any, s: number + // 获取js 时间戳 + let time: number = new Date().getTime() + // 是否是对象 + typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param) + // 当前时间戳 - 传入时间戳 + time = Number.parseInt(`${time - t}`) + if (time < 10000) { + // 10秒内 + return '刚刚' + } else if (time < 60000 && time >= 10000) { + // 超过10秒少于1分钟内 + s = Math.floor(time / 1000) + return `${s}秒前` + } else if (time < 3600000 && time >= 60000) { + // 超过1分钟少于1小时 + s = Math.floor(time / 60000) + return `${s}分钟前` + } else if (time < 86400000 && time >= 3600000) { + // 超过1小时少于24小时 + s = Math.floor(time / 3600000) + return `${s}小时前` + } else if (time < 259200000 && time >= 86400000) { + // 超过1天少于3天内 + s = Math.floor(time / 86400000) + return `${s}天前` + } else { + // 超过3天 + const date = typeof param === 'string' || 'object' ? new Date(param) : param + return formatDate(date, format) + } +} + +/** + * 时间问候语 + * @param param 当前时间,new Date() 格式 + * @description param 调用 `formatAxis(new Date())` 输出 `上午好` + * @returns 返回拼接后的时间字符串 + */ +export function formatAxis(param: Date): string { + const hour: number = new Date(param).getHours() + if (hour < 6) return '凌晨好' + else if (hour < 9) return '早上好' + else if (hour < 12) return '上午好' + else if (hour < 14) return '中午好' + else if (hour < 17) return '下午好' + else if (hour < 19) return '傍晚好' + else if (hour < 22) return '晚上好' + else return '夜里好' +} + +/** + * 将毫秒,转换成时间字符串。例如说,xx 分钟 + * + * @param ms 毫秒 + * @returns {string} 字符串 + */ +export function formatPast2(ms: number): string { + const day = Math.floor(ms / (24 * 60 * 60 * 1000)) + const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24) + const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60) + const second = Math.floor(ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60) + if (day > 0) { + return day + ' 天' + hour + ' 小时 ' + minute + ' 分钟' + } + if (hour > 0) { + return hour + ' 小时 ' + minute + ' 分钟' + } + if (minute > 0) { + return minute + ' 分钟' + } + if (second > 0) { + return second + ' 秒' + } else { + return 0 + ' 秒' + } +} + +/** + * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD HH:mm:ss 格式 + * + * @param row 行数据 + * @param column 字段 + * @param cellValue 字段值 + */ +export function dateFormatter(_row: any, _column: TableColumnCtx, cellValue: any): string { + return cellValue ? formatDate(cellValue) : '' +} + +/** + * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD 格式 + * + * @param row 行数据 + * @param column 字段 + * @param cellValue 字段值 + */ +export function dateFormatter2(_row: any, _column: TableColumnCtx, cellValue: any): string { + return cellValue ? formatDate(cellValue, 'YYYY-MM-DD') : '' +} + +/** + * 设置起始日期,时间为00:00:00 + * @param param 传入日期 + * @returns 带时间00:00:00的日期 + */ +export function beginOfDay(param: Date): Date { + return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 0, 0, 0) +} + +/** + * 设置结束日期,时间为23:59:59 + * @param param 传入日期 + * @returns 带时间23:59:59的日期 + */ +export function endOfDay(param: Date): Date { + return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 23, 59, 59) +} + +/** + * 计算两个日期间隔天数 + * @param param1 日期1 + * @param param2 日期2 + */ +export function betweenDay(param1: Date, param2: Date): number { + param1 = convertDate(param1) + param2 = convertDate(param2) + // 计算差值 + return Math.floor((param2.getTime() - param1.getTime()) / (24 * 3600 * 1000)) +} + +/** + * 日期计算 + * @param param1 日期 + * @param param2 添加的时间 + */ +export function addTime(param1: Date, param2: number): Date { + param1 = convertDate(param1) + return new Date(param1.getTime() + param2) +} + +/** + * 日期转换 + * @param param 日期 + */ +export function convertDate(param: Date | string): Date { + if (typeof param === 'string') { + return new Date(param) + } + return param +} + +/** + * 指定的两个日期, 是否为同一天 + * @param a 日期 A + * @param b 日期 B + */ +export function isSameDay(a: dayjs.ConfigType, b: dayjs.ConfigType): boolean { + if (!a || !b) return false + + const aa = dayjs(a) + const bb = dayjs(b) + return aa.year() == bb.year() && aa.month() == bb.month() && aa.day() == bb.day() +} + +/** + * 获取一天的开始时间、截止时间 + * @param date 日期 + * @param days 天数 + */ +export function getDayRange( + date: dayjs.ConfigType, + days: number +): [dayjs.ConfigType, dayjs.ConfigType] { + const day = dayjs(date).add(days, 'd') + return getDateRange(day, day) +} + +/** + * 获取最近7天的开始时间、截止时间 + */ +export function getLast7Days(): [dayjs.ConfigType, dayjs.ConfigType] { + const lastWeekDay = dayjs().subtract(7, 'd') + const yesterday = dayjs().subtract(1, 'd') + return getDateRange(lastWeekDay, yesterday) +} + +/** + * 获取最近30天的开始时间、截止时间 + */ +export function getLast30Days(): [dayjs.ConfigType, dayjs.ConfigType] { + const lastMonthDay = dayjs().subtract(30, 'd') + const yesterday = dayjs().subtract(1, 'd') + return getDateRange(lastMonthDay, yesterday) +} + +/** + * 获取最近1年的开始时间、截止时间 + */ +export function getLast1Year(): [dayjs.ConfigType, dayjs.ConfigType] { + const lastYearDay = dayjs().subtract(1, 'y') + const yesterday = dayjs().subtract(1, 'd') + return getDateRange(lastYearDay, yesterday) +} + +/** + * 获取指定日期的开始时间、截止时间 + * @param beginDate 开始日期 + * @param endDate 截止日期 + */ +export function getDateRange( + beginDate: dayjs.ConfigType, + endDate: dayjs.ConfigType +): [string, string] { + return [ + dayjs(beginDate).startOf('d').format('YYYY-MM-DD HH:mm:ss'), + dayjs(endDate).endOf('d').format('YYYY-MM-DD HH:mm:ss') + ] +} diff --git a/src/utils/formatter.ts b/src/utils/formatter.ts new file mode 100644 index 0000000..8777f32 --- /dev/null +++ b/src/utils/formatter.ts @@ -0,0 +1,7 @@ +import { floatToFixed2 } from '@/utils' + +// 格式化金额【分转元】 +// @ts-ignore +export const fenToYuanFormat = (_, __, cellValue: any, ___) => { + return `¥${floatToFixed2(cellValue)}` +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..2c2fbbd --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,451 @@ +import { toNumber } from 'lodash-es' + +/** + * + * @param component 需要注册的组件 + * @param alias 组件别名 + * @returns any + */ +export const withInstall = (component: T, alias?: string) => { + const comp = component as any + comp.install = (app: any) => { + app.component(comp.name || comp.displayName, component) + if (alias) { + app.config.globalProperties[alias] = component + } + } + return component as T & Plugin +} + +/** + * @param str 需要转下划线的驼峰字符串 + * @returns 字符串下划线 + */ +export const humpToUnderline = (str: string): string => { + return str.replace(/([A-Z])/g, '-$1').toLowerCase() +} + +/** + * @param str 需要转驼峰的下划线字符串 + * @returns 字符串驼峰 + */ +export const underlineToHump = (str: string): string => { + if (!str) return '' + return str.replace(/\-(\w)/g, (_, letter: string) => { + return letter.toUpperCase() + }) +} + +/** + * 驼峰转横杠 + */ +export const humpToDash = (str: string): string => { + return str.replace(/([A-Z])/g, '-$1').toLowerCase() +} + +export const setCssVar = (prop: string, val: any, dom = document.documentElement) => { + dom.style.setProperty(prop, val) +} + +/** + * 查找数组对象的某个下标 + * @param {Array} ary 查找的数组 + * @param {Functon} fn 判断的方法 + */ +// eslint-disable-next-line +export const findIndex = (ary: Array, fn: Fn): number => { + if (ary.findIndex) { + return ary.findIndex(fn) + } + let index = -1 + ary.some((item: T, i: number, ary: Array) => { + const ret: T = fn(item, i, ary) + if (ret) { + index = i + return ret + } + }) + return index +} + +export const trim = (str: string) => { + return str.replace(/(^\s*)|(\s*$)/g, '') +} + +/** + * @param {Date | number | string} time 需要转换的时间 + * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss + */ +export function formatTime(time: Date | number | string, fmt: string) { + if (!time) return '' + else { + const date = new Date(time) + const o = { + 'M+': date.getMonth() + 1, + 'd+': date.getDate(), + 'H+': date.getHours(), + 'm+': date.getMinutes(), + 's+': date.getSeconds(), + 'q+': Math.floor((date.getMonth() + 3) / 3), + S: date.getMilliseconds() + } + if (/(y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) + } + for (const k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { + fmt = fmt.replace( + RegExp.$1, + RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length) + ) + } + } + return fmt + } +} + +/** + * 生成随机字符串 + */ +export function toAnyString() { + const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => { + const r: number = (Math.random() * 16) | 0 + const v: number = c === 'x' ? r : (r & 0x3) | 0x8 + return v.toString() + }) + return str +} + +/** + * 首字母大写 + */ +export function firstUpperCase(str: string) { + return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase()) +} + +export const generateUUID = () => { + if (typeof crypto === 'object') { + if (typeof crypto.randomUUID === 'function') { + return crypto.randomUUID() + } + if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') { + const callback = (c: any) => { + const num = Number(c) + return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString( + 16 + ) + } + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback) + } + } + let timestamp = new Date().getTime() + let performanceNow = + (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0 + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + let random = Math.random() * 16 + if (timestamp > 0) { + random = (timestamp + random) % 16 | 0 + timestamp = Math.floor(timestamp / 16) + } else { + random = (performanceNow + random) % 16 | 0 + performanceNow = Math.floor(performanceNow / 16) + } + return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16) + }) +} + +/** + * element plus 的文件大小 Formatter 实现 + * + * @param row 行数据 + * @param column 字段 + * @param cellValue 字段值 + */ +// @ts-ignore +export const fileSizeFormatter = (row, column, cellValue) => { + const fileSize = cellValue + const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + const srcSize = parseFloat(fileSize) + const index = Math.floor(Math.log(srcSize) / Math.log(1024)) + const size = srcSize / Math.pow(1024, index) + const sizeStr = size.toFixed(2) //保留的小数位数 + return sizeStr + ' ' + unitArr[index] +} + +/** + * 将值复制到目标对象,且以目标对象属性为准,例:target: {a:1} source:{a:2,b:3} 结果为:{a:2} + * @param target 目标对象 + * @param source 源对象 + */ +export const copyValueToTarget = (target: any, source: any) => { + const newObj = Object.assign({}, target, source) + // 删除多余属性 + Object.keys(newObj).forEach((key) => { + // 如果不是target中的属性则删除 + if (Object.keys(target).indexOf(key) === -1) { + delete newObj[key] + } + }) + // 更新目标对象值 + Object.assign(target, newObj) +} + +/** + * 获取链接的参数值 + * @param key 参数键名 + * @param urlStr 链接地址,默认为当前浏览器的地址 + */ +export const getUrlValue = (key: string, urlStr: string = location.href): string => { + if (!urlStr || !key) return '' + const url = new URL(decodeURIComponent(urlStr)) + return url.searchParams.get(key) ?? '' +} + +/** + * 获取链接的参数值(值类型) + * @param key 参数键名 + * @param urlStr 链接地址,默认为当前浏览器的地址 + */ +export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => { + return toNumber(getUrlValue(key, urlStr)) +} + +/** + * 构建排序字段 + * @param prop 字段名称 + * @param order 顺序 + */ +export const buildSortingField = ({ prop, order }) => { + return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' } +} + +// ========== NumberUtils 数字方法 ========== + +/** + * 数组求和 + * + * @param values 数字数组 + * @return 求和结果,默认为 0 + */ +export const getSumValue = (values: number[]): number => { + return values.reduce((prev, curr) => { + const value = Number(curr) + if (!Number.isNaN(value)) { + return prev + curr + } else { + return prev + } + }, 0) +} + +// ========== 通用金额方法 ========== + +/** + * 将一个整数转换为分数保留两位小数 + * @param num + */ +export const formatToFraction = (num: number | string | undefined): string => { + if (typeof num === 'undefined') return '0.00' + const parsedNumber = typeof num === 'string' ? parseFloat(num) : num + return (parsedNumber / 100.0).toFixed(2) +} + +/** + * 将一个数转换为 1.00 这样 + * 数据呈现的时候使用 + * + * @param num 整数 + */ +// TODO @芋艿:看看怎么融合掉 +export const floatToFixed2 = (num: number | string | undefined): string => { + let str = '0.00' + if (typeof num === 'undefined') { + return str + } + const f = formatToFraction(num) + const decimalPart = f.toString().split('.')[1] + const len = decimalPart ? decimalPart.length : 0 + switch (len) { + case 0: + str = f.toString() + '.00' + break + case 1: + str = f.toString() + '0' + break + case 2: + str = f.toString() + break + } + return str +} + +/** + * 将一个分数转换为整数 + * @param num + */ +// TODO @芋艿:看看怎么融合掉 +export const convertToInteger = (num: number | string | undefined): number => { + if (typeof num === 'undefined') return 0 + const parsedNumber = typeof num === 'string' ? parseFloat(num) : num + // TODO 分转元后还有小数则四舍五入 + return Math.round(parsedNumber * 100) +} + +/** + * 元转分 + */ +export const yuanToFen = (amount: string | number): number => { + return convertToInteger(amount) +} + +/** + * 分转元 + */ +export const fenToYuan = (price: string | number): string => { + return formatToFraction(price) +} + +/** + * 计算环比 + * + * @param value 当前数值 + * @param reference 对比数值 + */ +export const calculateRelativeRate = (value?: number, reference?: number) => { + // 防止除0 + if (!reference || reference == 0) return 0 + + return ((100 * ((value || 0) - reference)) / reference).toFixed(0) +} + +// ========== ERP 专属方法 ========== + +const ERP_COUNT_DIGIT = 3 +const ERP_PRICE_DIGIT = 2 + +/** + * 【ERP】格式化 Input 数字 + * + * 例如说:库存数量 + * + * @param num 数量 + * @package digit 保留的小数位数 + * @return 格式化后的数量 + */ +export const erpNumberFormatter = (num: number | string | undefined, digit: number) => { + if (num == null) { + return '' + } + if (typeof num === 'string') { + num = parseFloat(num) + } + // 如果非 number,则直接返回空串 + if (isNaN(num)) { + return '' + } + return num.toFixed(digit) +} + +/** + * 【ERP】格式化数量,保留三位小数 + * + * 例如说:库存数量 + * + * @param num 数量 + * @return 格式化后的数量 + */ +export const erpCountInputFormatter = (num: number | string | undefined) => { + return erpNumberFormatter(num, ERP_COUNT_DIGIT) +} + +// noinspection JSCommentMatchesSignature +/** + * 【ERP】格式化数量,保留三位小数 + * + * @param cellValue 数量 + * @return 格式化后的数量 + */ +export const erpCountTableColumnFormatter = (_, __, cellValue: any, ___) => { + return erpNumberFormatter(cellValue, ERP_COUNT_DIGIT) +} + +/** + * 【ERP】格式化金额,保留二位小数 + * + * 例如说:库存数量 + * + * @param num 数量 + * @return 格式化后的数量 + */ +export const erpPriceInputFormatter = (num: number | string | undefined) => { + return erpNumberFormatter(num, ERP_PRICE_DIGIT) +} + +// noinspection JSCommentMatchesSignature +/** + * 【ERP】格式化金额,保留二位小数 + * + * @param cellValue 数量 + * @return 格式化后的数量 + */ +export const erpPriceTableColumnFormatter = (_, __, cellValue: any, ___) => { + return erpNumberFormatter(cellValue, ERP_PRICE_DIGIT) +} + +/** + * 【ERP】价格计算,四舍五入保留两位小数 + * + * @param price 价格 + * @param count 数量 + * @return 总价格。如果有任一为空,则返回 undefined + */ +export const erpPriceMultiply = (price: number, count: number) => { + if (price == null || count == null) { + return undefined + } + return parseFloat((price * count).toFixed(ERP_PRICE_DIGIT)) +} + +/** + * 【ERP】百分比计算,四舍五入保留两位小数 + * + * 如果 total 为 0,则返回 0 + * + * @param value 当前值 + * @param total 总值 + */ +export const erpCalculatePercentage = (value: number, total: number) => { + if (total === 0) return 0 + return ((value / total) * 100).toFixed(2) +} + +/** + * 适配 echarts map 的地名 + * + * @param areaName 地区名称 + */ +export const areaReplace = (areaName: string) => { + if (!areaName) { + return areaName + } + return areaName + .replace('维吾尔自治区', '') + .replace('壮族自治区', '') + .replace('回族自治区', '') + .replace('自治区', '') + .replace('省', '') +} + +/** + * 解析 JSON 字符串 + * + * @param str + */ +export function jsonParse(str: string) { + try { + return JSON.parse(str) + } catch (e) { + console.error(`str[${str}] 不是一个 JSON 字符串`) + return '' + } +} diff --git a/src/utils/is.ts b/src/utils/is.ts new file mode 100644 index 0000000..24d7191 --- /dev/null +++ b/src/utils/is.ts @@ -0,0 +1,118 @@ +// copy to vben-admin + +const toString = Object.prototype.toString + +export const is = (val: unknown, type: string) => { + return toString.call(val) === `[object ${type}]` +} + +export const isDef = (val?: T): val is T => { + return typeof val !== 'undefined' +} + +export const isUnDef = (val?: T): val is T => { + return !isDef(val) +} + +export const isObject = (val: any): val is Record => { + return val !== null && is(val, 'Object') +} + +export const isEmpty = (val: any): boolean => { + if (val === null || val === undefined || typeof val === 'undefined') { + return true + } + if (isArray(val) || isString(val)) { + return val.length === 0 + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0 + } + + if (isObject(val)) { + return Object.keys(val).length === 0 + } + + return false +} + +export const isDate = (val: unknown): val is Date => { + return is(val, 'Date') +} + +export const isNull = (val: unknown): val is null => { + return val === null +} + +export const isNullAndUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) && isNull(val) +} + +export const isNullOrUnDef = (val: unknown): val is null | undefined => { + return isUnDef(val) || isNull(val) +} + +export const isNumber = (val: unknown): val is number => { + return is(val, 'Number') +} + +export const isPromise = (val: unknown): val is Promise => { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) +} + +export const isString = (val: unknown): val is string => { + return is(val, 'String') +} + +export const isFunction = (val: unknown): val is Function => { + return typeof val === 'function' +} + +export const isBoolean = (val: unknown): val is boolean => { + return is(val, 'Boolean') +} + +export const isRegExp = (val: unknown): val is RegExp => { + return is(val, 'RegExp') +} + +export const isArray = (val: any): val is Array => { + return val && Array.isArray(val) +} + +export const isWindow = (val: any): val is Window => { + return typeof window !== 'undefined' && is(val, 'Window') +} + +export const isElement = (val: unknown): val is Element => { + return isObject(val) && !!val.tagName +} + +export const isMap = (val: unknown): val is Map => { + return is(val, 'Map') +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer + +export const isUrl = (path: string): boolean => { + // fix:修复hash路由无法跳转的问题 + const reg = + /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%#\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/ + return reg.test(path) +} + +export const isDark = (): boolean => { + return window.matchMedia('(prefers-color-scheme: dark)').matches +} + +// 是否是图片链接 +export const isImgPath = (path: string): boolean => { + return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path) +} + +export const isEmptyVal = (val: any): boolean => { + return val === '' || val === null || val === undefined +} diff --git a/src/utils/jsencrypt.ts b/src/utils/jsencrypt.ts new file mode 100644 index 0000000..374d5f6 --- /dev/null +++ b/src/utils/jsencrypt.ts @@ -0,0 +1,31 @@ +import { JSEncrypt } from 'jsencrypt' + +// 密钥对生成 http://web.chacuo.net/netrsakeypair + +const publicKey = + 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' + +const privateKey = + 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + + 'UP8iWi1Qw0Y=' + +// 加密 +export const encrypt = (txt: string) => { + const encryptor = new JSEncrypt() + encryptor.setPublicKey(publicKey) // 设置公钥 + return encryptor.encrypt(txt) // 对数据进行加密 +} + +// 解密 +export const decrypt = (txt: string) => { + const encryptor = new JSEncrypt() + encryptor.setPrivateKey(privateKey) // 设置私钥 + return encryptor.decrypt(txt) // 对数据进行解密 +} diff --git a/src/utils/permission.ts b/src/utils/permission.ts new file mode 100644 index 0000000..3bf67b6 --- /dev/null +++ b/src/utils/permission.ts @@ -0,0 +1,47 @@ +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' + +const { t } = useI18n() // 国际化 + +/** + * 字符权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkPermi(value: string[]) { + if (value && value instanceof Array && value.length > 0) { + const { wsCache } = useCache() + const permissionDatas = value + const all_permission = '*:*:*' + const userInfo = wsCache.get(CACHE_KEY.USER) + const permissions = userInfo?.permissions || [] + const hasPermission = permissions.some((permission: string) => { + return all_permission === permission || permissionDatas.includes(permission) + }) + return !!hasPermission + } else { + console.error(t('permission.hasPermission')) + return false + } +} + +/** + * 角色权限校验 + * @param {string[]} value 校验值 + * @returns {Boolean} + */ +export function checkRole(value: string[]) { + if (value && value instanceof Array && value.length > 0) { + const { wsCache } = useCache() + const permissionRoles = value + const super_admin = 'super_admin' + const userInfo = wsCache.get(CACHE_KEY.USER) + const roles = userInfo?.roles || [] + const hasRole = roles.some((role: string) => { + return super_admin === role || permissionRoles.includes(role) + }) + return !!hasRole + } else { + console.error(t('permission.hasRole')) + return false + } +} diff --git a/src/utils/propTypes.ts b/src/utils/propTypes.ts new file mode 100644 index 0000000..863f55c --- /dev/null +++ b/src/utils/propTypes.ts @@ -0,0 +1,24 @@ +import { VueTypeValidableDef, VueTypesInterface, createTypes, toValidableType } from 'vue-types' +import { CSSProperties } from 'vue' + +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef +} +const newPropTypes = createTypes({ + func: undefined, + bool: undefined, + string: undefined, + number: undefined, + object: undefined, + integer: undefined +}) as PropTypes + +class propTypes extends newPropTypes { + static get style() { + return toValidableType('style', { + type: [String, Object] + }) + } +} + +export { propTypes } diff --git a/src/utils/routerHelper.ts b/src/utils/routerHelper.ts new file mode 100644 index 0000000..f9f95c4 --- /dev/null +++ b/src/utils/routerHelper.ts @@ -0,0 +1,253 @@ +import type { RouteLocationNormalized, Router, RouteRecordNormalized } from 'vue-router' +import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' +import { isUrl } from '@/utils/is' +import { cloneDeep, omit } from 'lodash-es' +import qs from 'qs' + +const modules = import.meta.glob('../views/**/*.{vue,tsx}') +/** + * 注册一个异步组件 + * @param componentPath 例:/bpm/oa/leave/detail + */ +export const registerComponent = (componentPath: string) => { + for (const item in modules) { + if (item.includes(componentPath)) { + // 使用异步组件的方式来动态加载组件 + // @ts-ignore + return defineAsyncComponent(modules[item]) + } + } +} +/* Layout */ +export const Layout = () => import('@/layout/Layout.vue') + +export const getParentLayout = () => { + return () => + new Promise((resolve) => { + resolve({ + name: 'ParentLayout' + }) + }) +} + +// 按照路由中meta下的rank等级升序来排序路由 +export const ascending = (arr: any[]) => { + arr.forEach((v) => { + if (v?.meta?.rank === null) v.meta.rank = undefined + if (v?.meta?.rank === 0) { + if (v.name !== 'home' && v.path !== '/') { + console.warn('rank only the home page can be 0') + } + } + }) + return arr.sort((a: { meta: { rank: number } }, b: { meta: { rank: number } }) => { + return a?.meta?.rank - b?.meta?.rank + }) +} + +export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => { + if (!route) return route + const { matched, ...opt } = route + return { + ...opt, + matched: (matched + ? matched.map((item) => ({ + meta: item.meta, + name: item.name, + path: item.path + })) + : undefined) as RouteRecordNormalized[] + } +} + +// 后端控制路由生成 +export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => { + const res: AppRouteRecordRaw[] = [] + const modulesRoutesKeys = Object.keys(modules) + for (const route of routes) { + // 1. 生成 meta 菜单元数据 + const meta = { + title: route.name, + icon: route.icon, + hidden: !route.visible, + noCache: !route.keepAlive, + alwaysShow: + route.children && + route.children.length > 0 && + (route.alwaysShow !== undefined ? route.alwaysShow : true) + } as any + // 特殊逻辑:如果后端配置的 MenuDO.component 包含 ?,则表示需要传递参数 + // 此时,我们需要解析参数,并且将参数放到 meta.query 中 + // 这样,后续在 Vue 文件中,可以通过 const { currentRoute } = useRouter() 中,通过 meta.query 获取到参数 + if (route.component && route.component.indexOf('?') > -1) { + const query = route.component.split('?')[1] + route.component = route.component.split('?')[0] + meta.query = qs.parse(query) + } + + // 2. 生成 data(AppRouteRecordRaw) + // 路由地址转首字母大写驼峰,作为路由名称,适配keepAlive + let data: AppRouteRecordRaw = { + path: + route.path.indexOf('?') > -1 && !isUrl(route.path) ? route.path.split('?')[0] : route.path, // 注意,需要排除 http 这种 url,避免它带 ? 参数被截取掉 + name: + route.componentName && route.componentName.length > 0 + ? route.componentName + : toCamelCase(route.path, true), + redirect: route.redirect, + meta: meta + } + //处理顶级非目录路由 + if (!route.children && route.parentId == 0 && route.component) { + data.component = Layout + data.name = toCamelCase(route.path, true) + 'Parent' + data.redirect = '' + meta.alwaysShow = true + const childrenData: AppRouteRecordRaw = { + path: '', + name: + route.componentName && route.componentName.length > 0 + ? route.componentName + : toCamelCase(route.path, true), + redirect: route.redirect, + meta: meta + } + const index = route?.component + ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component)) + : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path)) + childrenData.component = modules[modulesRoutesKeys[index]] + data.children = [childrenData] + } else { + // 目录 + if (route.children?.length) { + data.component = Layout + data.redirect = getRedirect(route.path, route.children) + // 外链 + } else if (isUrl(route.path)) { + data = { + path: '/external-link', + component: Layout, + meta: { + name: route.name + }, + children: [data] + } as AppRouteRecordRaw + // 菜单 + } else { + // 对后端传component组件路径和不传做兼容(如果后端传component组件路径,那么path可以随便写,如果不传,component组件路径会根path保持一致) + const index = route?.component + ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component)) + : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path)) + data.component = modules[modulesRoutesKeys[index]] + } + if (route.children) { + data.children = generateRoute(route.children) + } + } + res.push(data as AppRouteRecordRaw) + } + return res +} +export const getRedirect = (parentPath: string, children: AppCustomRouteRecordRaw[]) => { + if (!children || children.length == 0) { + return parentPath + } + const path = generateRoutePath(parentPath, children[0].path) + // 递归子节点 + if (children[0].children) return getRedirect(path, children[0].children) +} +const generateRoutePath = (parentPath: string, path: string) => { + if (parentPath.endsWith('/')) { + parentPath = parentPath.slice(0, -1) // 移除默认的 / + } + if (!path.startsWith('/')) { + path = '/' + path + } + return parentPath + path +} +export const pathResolve = (parentPath: string, path: string) => { + if (isUrl(path)) return path + const childPath = path.startsWith('/') || !path ? path : `/${path}` + return `${parentPath}${childPath}`.replace(/\/\//g, '/') +} + +// 路由降级 +export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => { + const modules: AppRouteRecordRaw[] = cloneDeep(routes) + for (let index = 0; index < modules.length; index++) { + const route = modules[index] + if (!isMultipleRoute(route)) { + continue + } + promoteRouteLevel(route) + } + return modules +} + +// 层级是否大于2 +const isMultipleRoute = (route: AppRouteRecordRaw) => { + if (!route || !Reflect.has(route, 'children') || !route.children?.length) { + return false + } + + const children = route.children + + let flag = false + for (let index = 0; index < children.length; index++) { + const child = children[index] + if (child.children?.length) { + flag = true + break + } + } + return flag +} + +// 生成二级路由 +const promoteRouteLevel = (route: AppRouteRecordRaw) => { + let router: Router | null = createRouter({ + routes: [route as RouteRecordRaw], + history: createWebHashHistory() + }) + + const routes = router.getRoutes() + addToChildren(routes, route.children || [], route) + router = null + + route.children = route.children?.map((item) => omit(item, 'children')) +} + +// 添加所有子菜单 +const addToChildren = ( + routes: RouteRecordNormalized[], + children: AppRouteRecordRaw[], + routeModule: AppRouteRecordRaw +) => { + for (let index = 0; index < children.length; index++) { + const child = children[index] + const route = routes.find((item) => item.name === child.name) + if (!route) { + continue + } + routeModule.children = routeModule.children || [] + if (!routeModule.children.find((item) => item.name === route.name)) { + routeModule.children?.push(route as unknown as AppRouteRecordRaw) + } + if (child.children?.length) { + addToChildren(routes, child.children, routeModule) + } + } +} +const toCamelCase = (str: string, upperCaseFirst: boolean) => { + str = (str || '') + .replace(/-(.)/g, function (group1: string) { + return group1.toUpperCase() + }) + .replaceAll('-', '') + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1) + } + + return str +} diff --git a/src/utils/tree.ts b/src/utils/tree.ts new file mode 100644 index 0000000..e5db503 --- /dev/null +++ b/src/utils/tree.ts @@ -0,0 +1,403 @@ +interface TreeHelperConfig { + id: string + children: string + pid: string +} + +const DEFAULT_CONFIG: TreeHelperConfig = { + id: 'id', + children: 'children', + pid: 'pid' +} +export const defaultProps = { + children: 'children', + label: 'name', + value: 'id', + isLeaf: 'leaf', + emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值 +} + +const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config) + +// tree from list +export const listToTree = (list: any[], config: Partial = {}): T[] => { + const conf = getConfig(config) as TreeHelperConfig + const nodeMap = new Map() + const result: T[] = [] + const { id, children, pid } = conf + + for (const node of list) { + node[children] = node[children] || [] + nodeMap.set(node[id], node) + } + for (const node of list) { + const parent = nodeMap.get(node[pid]) + ;(parent ? parent.children : result).push(node) + } + return result +} + +export const treeToList = (tree: any, config: Partial = {}): T => { + config = getConfig(config) + const { children } = config + const result: any = [...tree] + for (let i = 0; i < result.length; i++) { + if (!result[i][children!]) continue + result.splice(i + 1, 0, ...result[i][children!]) + } + return result +} + +export const findNode = ( + tree: any, + func: Fn, + config: Partial = {} +): T | null => { + config = getConfig(config) + const { children } = config + const list = [...tree] + for (const node of list) { + if (func(node)) return node + node[children!] && list.push(...node[children!]) + } + return null +} + +export const findNodeAll = ( + tree: any, + func: Fn, + config: Partial = {} +): T[] => { + config = getConfig(config) + const { children } = config + const list = [...tree] + const result: T[] = [] + for (const node of list) { + func(node) && result.push(node) + node[children!] && list.push(...node[children!]) + } + return result +} + +export const findPath = ( + tree: any, + func: Fn, + config: Partial = {} +): T | T[] | null => { + config = getConfig(config) + const path: T[] = [] + const list = [...tree] + const visitedSet = new Set() + const { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + if (func(node)) { + return path + } + } + } + return null +} + +export const findPathAll = (tree: any, func: Fn, config: Partial = {}) => { + config = getConfig(config) + const path: any[] = [] + const list = [...tree] + const result: any[] = [] + const visitedSet = new Set(), + { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + func(node) && result.push([...path]) + } + } + return result +} + +export const filter = ( + tree: T[], + func: (n: T) => boolean, + config: Partial = {} +): T[] => { + config = getConfig(config) + const children = config.children as string + + function listFilter(list: T[]) { + return list + .map((node: any) => ({ ...node })) + .filter((node) => { + node[children] = node[children] && listFilter(node[children]) + return func(node) || (node[children] && node[children].length) + }) + } + + return listFilter(tree) +} + +export const forEach = ( + tree: T[], + func: (n: T) => any, + config: Partial = {} +): void => { + config = getConfig(config) + const list: any[] = [...tree] + const { children } = config + for (let i = 0; i < list.length; i++) { + // func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿 + if (func(list[i])) { + return + } + children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]) + } +} + +/** + * @description: Extract tree specified structure + */ +export const treeMap = ( + treeData: T[], + opt: { children?: string; conversion: Fn } +): T[] => { + return treeData.map((item) => treeMapEach(item, opt)) +} + +/** + * @description: Extract tree specified structure + */ +export const treeMapEach = ( + data: any, + { children = 'children', conversion }: { children?: string; conversion: Fn } +) => { + const haveChildren = Array.isArray(data[children]) && data[children].length > 0 + const conversionData = conversion(data) || {} + if (haveChildren) { + return { + ...conversionData, + [children]: data[children].map((i: number) => + treeMapEach(i, { + children, + conversion + }) + ) + } + } else { + return { + ...conversionData + } + } +} + +/** + * 递归遍历树结构 + * @param treeDatas 树 + * @param callBack 回调 + * @param parentNode 父节点 + */ +export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { + treeDatas.forEach((element) => { + const newNode = callBack(element, parentNode) || element + if (element.children) { + eachTree(element.children, callBack, newNode) + } + }) +} + +/** + * 构造树型结构数据 + * @param {*} data 数据源 + * @param {*} id id字段 默认 'id' + * @param {*} parentId 父节点字段 默认 'parentId' + * @param {*} children 孩子节点字段 默认 'children' + */ +export const handleTree = (data: any[], id?: string, parentId?: string, children?: string) => { + if (!Array.isArray(data)) { + console.warn('data must be an array') + return [] + } + const config = { + id: id || 'id', + parentId: parentId || 'parentId', + childrenList: children || 'children' + } + + const childrenListMap = {} + const nodeIds = {} + const tree: any[] = [] + + for (const d of data) { + const parentId = d[config.parentId] + if (childrenListMap[parentId] == null) { + childrenListMap[parentId] = [] + } + nodeIds[d[config.id]] = d + childrenListMap[parentId].push(d) + } + + for (const d of data) { + const parentId = d[config.parentId] + if (nodeIds[parentId] == null) { + tree.push(d) + } + } + + for (const t of tree) { + adaptToChildrenList(t) + } + + function adaptToChildrenList(o) { + if (childrenListMap[o[config.id]] !== null) { + o[config.childrenList] = childrenListMap[o[config.id]] + } + if (o[config.childrenList]) { + for (const c of o[config.childrenList]) { + adaptToChildrenList(c) + } + } + } + + return tree +} + +/** + * 构造树型结构数据 + * @param {*} data 数据源 + * @param {*} id id字段 默认 'id' + * @param {*} parentId 父节点字段 默认 'parentId' + * @param {*} children 孩子节点字段 默认 'children' + * @param {*} rootId 根Id 默认 0 + */ +// @ts-ignore +export const handleTree2 = (data, id, parentId, children, rootId) => { + id = id || 'id' + parentId = parentId || 'parentId' + // children = children || 'children' + rootId = + rootId || + Math.min( + ...data.map((item) => { + return item[parentId] + }) + ) || + 0 + // 对源数据深度克隆 + const cloneData = JSON.parse(JSON.stringify(data)) + // 循环所有项 + const treeData = cloneData.filter((father) => { + const branchArr = cloneData.filter((child) => { + // 返回每一项的子级数组 + return father[id] === child[parentId] + }) + branchArr.length > 0 ? (father.children = branchArr) : '' + // 返回第一层 + return father[parentId] === rootId + }) + return treeData !== '' ? treeData : data +} + +/** + * 校验选中的节点,是否为指定 level + * + * @param tree 要操作的树结构数据 + * @param nodeId 需要判断在什么层级的数据 + * @param level 检查的级别, 默认检查到二级 + * @return true 是;false 否 + */ +export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => { + if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) { + console.warn('tree must be an array') + return false + } + + // 校验是否是一级节点 + if (tree.some((item) => item.id === nodeId)) { + return false + } + + // 递归计数 + let count = 1 + + // 深层次校验 + function performAThoroughValidation(arr: any[]): boolean { + count += 1 + for (const item of arr) { + if (item.id === nodeId) { + return true + } else if (typeof item.children !== 'undefined' && item.children.length !== 0) { + if (performAThoroughValidation(item.children)) { + return true + } + } + } + return false + } + + for (const item of tree) { + count = 1 + if (performAThoroughValidation(item.children)) { + // 找到后对比是否是期望的层级 + if (count >= level) { + return true + } + } + } + + return false +} + +/** + * 获取节点的完整结构 + * @param tree 树数据 + * @param nodeId 节点 id + */ +export const treeToString = (tree: any[], nodeId) => { + if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) { + console.warn('tree must be an array') + return '' + } + // 校验是否是一级节点 + const node = tree.find((item) => item.id === nodeId) + if (typeof node !== 'undefined') { + return node.name + } + let str = '' + + function performAThoroughValidation(arr) { + if (typeof arr === 'undefined' || !Array.isArray(arr) || arr.length === 0) { + return false + } + for (const item of arr) { + if (item.id === nodeId) { + str += ` / ${item.name}` + return true + } else if (typeof item.children !== 'undefined' && item.children.length !== 0) { + str += ` / ${item.name}` + if (performAThoroughValidation(item.children)) { + return true + } + } + } + return false + } + + for (const item of tree) { + str = `${item.name}` + if (performAThoroughValidation(item.children)) { + break + } + } + return str +} diff --git a/src/utils/tsxHelper.ts b/src/utils/tsxHelper.ts new file mode 100644 index 0000000..6087fa3 --- /dev/null +++ b/src/utils/tsxHelper.ts @@ -0,0 +1,16 @@ +import { Slots } from 'vue' +import { isFunction } from '@/utils/is' + +export const getSlot = (slots: Slots, slot = 'default', data?: Recordable) => { + // Reflect.has 判断一个对象是否存在某个属性 + if (!slots || !Reflect.has(slots, slot)) { + return null + } + if (!isFunction(slots[slot])) { + console.error(`${slot} is not a function!`) + return null + } + const slotFn = slots[slot] + if (!slotFn) return null + return slotFn(data) +} diff --git a/src/views/Error/403.vue b/src/views/Error/403.vue new file mode 100644 index 0000000..a3ec487 --- /dev/null +++ b/src/views/Error/403.vue @@ -0,0 +1,8 @@ + + diff --git a/src/views/Error/404.vue b/src/views/Error/404.vue new file mode 100644 index 0000000..f6a08de --- /dev/null +++ b/src/views/Error/404.vue @@ -0,0 +1,7 @@ + + diff --git a/src/views/Error/500.vue b/src/views/Error/500.vue new file mode 100644 index 0000000..998487d --- /dev/null +++ b/src/views/Error/500.vue @@ -0,0 +1,7 @@ + + diff --git a/src/views/Home/Index.vue b/src/views/Home/Index.vue new file mode 100644 index 0000000..c59b9d2 --- /dev/null +++ b/src/views/Home/Index.vue @@ -0,0 +1,391 @@ + + diff --git a/src/views/Home/Index2.vue b/src/views/Home/Index2.vue new file mode 100644 index 0000000..c9429ab --- /dev/null +++ b/src/views/Home/Index2.vue @@ -0,0 +1,319 @@ + + + + diff --git a/src/views/Home/echarts-data.ts b/src/views/Home/echarts-data.ts new file mode 100644 index 0000000..56093f4 --- /dev/null +++ b/src/views/Home/echarts-data.ts @@ -0,0 +1,308 @@ +import { EChartsOption } from 'echarts' + +const { t } = useI18n() + +export const lineOptions: EChartsOption = { + title: { + text: t('analysis.monthlySales'), + left: 'center' + }, + xAxis: { + data: [ + t('analysis.january'), + t('analysis.february'), + t('analysis.march'), + t('analysis.april'), + t('analysis.may'), + t('analysis.june'), + t('analysis.july'), + t('analysis.august'), + t('analysis.september'), + t('analysis.october'), + t('analysis.november'), + t('analysis.december') + ], + boundaryGap: false, + axisTick: { + show: false + } + }, + grid: { + left: 20, + right: 20, + bottom: 20, + top: 80, + containLabel: true + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross' + }, + padding: [5, 10] + }, + yAxis: { + axisTick: { + show: false + } + }, + legend: { + data: [t('analysis.estimate'), t('analysis.actual')], + top: 50 + }, + series: [ + { + name: t('analysis.estimate'), + smooth: true, + type: 'line', + data: [100, 120, 161, 134, 105, 160, 165, 114, 163, 185, 118, 123], + animationDuration: 2800, + animationEasing: 'cubicInOut' + }, + { + name: t('analysis.actual'), + smooth: true, + type: 'line', + itemStyle: {}, + data: [120, 82, 91, 154, 162, 140, 145, 250, 134, 56, 99, 123], + animationDuration: 2800, + animationEasing: 'quadraticOut' + } + ] +} + +export const pieOptions: EChartsOption = { + title: { + text: t('analysis.userAccessSource'), + left: 'center' + }, + tooltip: { + trigger: 'item', + formatter: '{a}
{b} : {c} ({d}%)' + }, + legend: { + orient: 'vertical', + left: 'left', + data: [ + t('analysis.directAccess'), + t('analysis.mailMarketing'), + t('analysis.allianceAdvertising'), + t('analysis.videoAdvertising'), + t('analysis.searchEngines') + ] + }, + series: [ + { + name: t('analysis.userAccessSource'), + type: 'pie', + radius: '55%', + center: ['50%', '60%'], + data: [ + { value: 335, name: t('analysis.directAccess') }, + { value: 310, name: t('analysis.mailMarketing') }, + { value: 234, name: t('analysis.allianceAdvertising') }, + { value: 135, name: t('analysis.videoAdvertising') }, + { value: 1548, name: t('analysis.searchEngines') } + ] + } + ] +} + +export const barOptions: EChartsOption = { + title: { + text: t('analysis.weeklyUserActivity'), + left: 'center' + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + left: 50, + right: 20, + bottom: 20 + }, + xAxis: { + type: 'category', + data: [ + t('analysis.monday'), + t('analysis.tuesday'), + t('analysis.wednesday'), + t('analysis.thursday'), + t('analysis.friday'), + t('analysis.saturday'), + t('analysis.sunday') + ], + axisTick: { + alignWithLabel: true + } + }, + yAxis: { + type: 'value' + }, + series: [ + { + name: t('analysis.activeQuantity'), + data: [13253, 34235, 26321, 12340, 24643, 1322, 1324], + type: 'bar' + } + ] +} + +export const radarOption: EChartsOption = { + legend: { + data: [t('workplace.personal'), t('workplace.team')] + }, + radar: { + // shape: 'circle', + indicator: [ + { name: t('workplace.quote'), max: 65 }, + { name: t('workplace.contribution'), max: 160 }, + { name: t('workplace.hot'), max: 300 }, + { name: t('workplace.yield'), max: 130 }, + { name: t('workplace.follow'), max: 100 } + ] + }, + series: [ + { + name: `xxx${t('workplace.index')}`, + type: 'radar', + data: [ + { + value: [42, 30, 20, 35, 80], + name: t('workplace.personal') + }, + { + value: [50, 140, 290, 100, 90], + name: t('workplace.team') + } + ] + } + ] +} + +export const wordOptions = { + series: [ + { + type: 'wordCloud', + gridSize: 2, + sizeRange: [12, 50], + rotationRange: [-90, 90], + shape: 'pentagon', + width: 600, + height: 400, + drawOutOfBound: true, + textStyle: { + color: function () { + return ( + 'rgb(' + + [ + Math.round(Math.random() * 160), + Math.round(Math.random() * 160), + Math.round(Math.random() * 160) + ].join(',') + + ')' + ) + } + }, + emphasis: { + textStyle: { + shadowBlur: 10, + shadowColor: '#333' + } + }, + data: [ + { + name: 'Sam S Club', + value: 10000, + textStyle: { + color: 'black' + }, + emphasis: { + textStyle: { + color: 'red' + } + } + }, + { + name: 'Macys', + value: 6181 + }, + { + name: 'Amy Schumer', + value: 4386 + }, + { + name: 'Jurassic World', + value: 4055 + }, + { + name: 'Charter Communications', + value: 2467 + }, + { + name: 'Chick Fil A', + value: 2244 + }, + { + name: 'Planet Fitness', + value: 1898 + }, + { + name: 'Pitch Perfect', + value: 1484 + }, + { + name: 'Express', + value: 1112 + }, + { + name: 'Home', + value: 965 + }, + { + name: 'Johnny Depp', + value: 847 + }, + { + name: 'Lena Dunham', + value: 582 + }, + { + name: 'Lewis Hamilton', + value: 555 + }, + { + name: 'KXAN', + value: 550 + }, + { + name: 'Mary Ellen Mark', + value: 462 + }, + { + name: 'Farrah Abraham', + value: 366 + }, + { + name: 'Rita Ora', + value: 360 + }, + { + name: 'Serena Williams', + value: 282 + }, + { + name: 'NCAA baseball tournament', + value: 273 + }, + { + name: 'Point Break', + value: 265 + } + ] + } + ] +} diff --git a/src/views/Home/types.ts b/src/views/Home/types.ts new file mode 100644 index 0000000..e6313d3 --- /dev/null +++ b/src/views/Home/types.ts @@ -0,0 +1,55 @@ +export type WorkplaceTotal = { + project: number + access: number + todo: number +} + +export type Project = { + name: string + icon: string + message: string + personal: string + time: Date | number | string +} + +export type Notice = { + title: string + type: string + keys: string[] + date: Date | number | string +} + +export type Shortcut = { + name: string + icon: string + url: string +} + +export type RadarData = { + personal: number + team: number + max: number + name: string +} +export type AnalysisTotalTypes = { + users: number + messages: number + moneys: number + shoppings: number +} + +export type UserAccessSource = { + value: number + name: string +} + +export type WeeklyUserActivity = { + value: number + name: string +} + +export type MonthlySales = { + name: string + estimate: number + actual: number +} diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue new file mode 100644 index 0000000..b2ff380 --- /dev/null +++ b/src/views/Login/Login.vue @@ -0,0 +1,121 @@ + + + + + + \ No newline at end of file diff --git a/src/views/Login/SocialLogin.vue b/src/views/Login/SocialLogin.vue new file mode 100644 index 0000000..e0caace --- /dev/null +++ b/src/views/Login/SocialLogin.vue @@ -0,0 +1,347 @@ + + + + + diff --git a/src/views/Login/components/ForgetPasswordForm.vue b/src/views/Login/components/ForgetPasswordForm.vue new file mode 100644 index 0000000..0b6c56a --- /dev/null +++ b/src/views/Login/components/ForgetPasswordForm.vue @@ -0,0 +1,278 @@ + + + + diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue new file mode 100644 index 0000000..193f478 --- /dev/null +++ b/src/views/Login/components/LoginForm.vue @@ -0,0 +1,361 @@ + + + + diff --git a/src/views/Login/components/LoginFormTitle.vue b/src/views/Login/components/LoginFormTitle.vue new file mode 100644 index 0000000..cdf4fac --- /dev/null +++ b/src/views/Login/components/LoginFormTitle.vue @@ -0,0 +1,26 @@ + + diff --git a/src/views/Login/components/MobileForm.vue b/src/views/Login/components/MobileForm.vue new file mode 100644 index 0000000..7f5d994 --- /dev/null +++ b/src/views/Login/components/MobileForm.vue @@ -0,0 +1,226 @@ + + + + diff --git a/src/views/Login/components/QrCodeForm.vue b/src/views/Login/components/QrCodeForm.vue new file mode 100644 index 0000000..2670d00 --- /dev/null +++ b/src/views/Login/components/QrCodeForm.vue @@ -0,0 +1,30 @@ + + diff --git a/src/views/Login/components/RegisterForm.vue b/src/views/Login/components/RegisterForm.vue new file mode 100644 index 0000000..73f276c --- /dev/null +++ b/src/views/Login/components/RegisterForm.vue @@ -0,0 +1,280 @@ + + + + diff --git a/src/views/Login/components/SSOLogin.vue b/src/views/Login/components/SSOLogin.vue new file mode 100644 index 0000000..5ce34fb --- /dev/null +++ b/src/views/Login/components/SSOLogin.vue @@ -0,0 +1,199 @@ + + diff --git a/src/views/Login/components/index.ts b/src/views/Login/components/index.ts new file mode 100644 index 0000000..7c42415 --- /dev/null +++ b/src/views/Login/components/index.ts @@ -0,0 +1,9 @@ +import LoginForm from './LoginForm.vue' +import MobileForm from './MobileForm.vue' +import LoginFormTitle from './LoginFormTitle.vue' +import RegisterForm from './RegisterForm.vue' +import QrCodeForm from './QrCodeForm.vue' +import SSOLoginVue from './SSOLogin.vue' +import ForgetPasswordForm from './ForgetPasswordForm.vue' + +export { LoginForm, MobileForm, LoginFormTitle, RegisterForm, QrCodeForm, SSOLoginVue, ForgetPasswordForm } diff --git a/src/views/Login/components/useLogin.ts b/src/views/Login/components/useLogin.ts new file mode 100644 index 0000000..b4a02f8 --- /dev/null +++ b/src/views/Login/components/useLogin.ts @@ -0,0 +1,42 @@ +import { Ref } from 'vue' + +export enum LoginStateEnum { + LOGIN, + REGISTER, + RESET_PASSWORD, + MOBILE, + QR_CODE, + SSO +} + +const currentState = ref(LoginStateEnum.LOGIN) + +export function useLoginState() { + function setLoginState(state: LoginStateEnum) { + currentState.value = state + } + const getLoginState = computed(() => currentState.value) + + function handleBackLogin() { + setLoginState(LoginStateEnum.LOGIN) + } + + return { + setLoginState, + getLoginState, + handleBackLogin + } +} + +export function useFormValid(formRef: Ref) { + async function validForm() { + const form = unref(formRef) + if (!form) return + const data = await form.validate() + return data as T + } + + return { + validForm + } +} diff --git a/src/views/Profile/Index.vue b/src/views/Profile/Index.vue new file mode 100644 index 0000000..8e1695b --- /dev/null +++ b/src/views/Profile/Index.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/views/Profile/components/BasicInfo.vue b/src/views/Profile/components/BasicInfo.vue new file mode 100644 index 0000000..8dfafa6 --- /dev/null +++ b/src/views/Profile/components/BasicInfo.vue @@ -0,0 +1,96 @@ + + diff --git a/src/views/Profile/components/ProfileUser.vue b/src/views/Profile/components/ProfileUser.vue new file mode 100644 index 0000000..0d469ef --- /dev/null +++ b/src/views/Profile/components/ProfileUser.vue @@ -0,0 +1,99 @@ + + + + diff --git a/src/views/Profile/components/ResetPwd.vue b/src/views/Profile/components/ResetPwd.vue new file mode 100644 index 0000000..477be91 --- /dev/null +++ b/src/views/Profile/components/ResetPwd.vue @@ -0,0 +1,73 @@ + + diff --git a/src/views/Profile/components/UserAvatar.vue b/src/views/Profile/components/UserAvatar.vue new file mode 100644 index 0000000..63e1e16 --- /dev/null +++ b/src/views/Profile/components/UserAvatar.vue @@ -0,0 +1,45 @@ + + + + diff --git a/src/views/Profile/components/UserSocial.vue b/src/views/Profile/components/UserSocial.vue new file mode 100644 index 0000000..b7f955b --- /dev/null +++ b/src/views/Profile/components/UserSocial.vue @@ -0,0 +1,107 @@ + + diff --git a/src/views/Profile/components/index.ts b/src/views/Profile/components/index.ts new file mode 100644 index 0000000..9e1883c --- /dev/null +++ b/src/views/Profile/components/index.ts @@ -0,0 +1,7 @@ +import BasicInfo from './BasicInfo.vue' +import ProfileUser from './ProfileUser.vue' +import ResetPwd from './ResetPwd.vue' +import UserAvatarVue from './UserAvatar.vue' +import UserSocial from './UserSocial.vue' + +export { BasicInfo, ProfileUser, ResetPwd, UserAvatarVue, UserSocial } diff --git a/src/views/Redirect/Redirect.vue b/src/views/Redirect/Redirect.vue new file mode 100644 index 0000000..f7717ce --- /dev/null +++ b/src/views/Redirect/Redirect.vue @@ -0,0 +1,28 @@ + + diff --git a/src/views/ai/chat/index/components/conversation/ConversationList.vue b/src/views/ai/chat/index/components/conversation/ConversationList.vue new file mode 100644 index 0000000..54940f8 --- /dev/null +++ b/src/views/ai/chat/index/components/conversation/ConversationList.vue @@ -0,0 +1,472 @@ + + + + + + diff --git a/src/views/ai/chat/index/components/conversation/ConversationUpdateForm.vue b/src/views/ai/chat/index/components/conversation/ConversationUpdateForm.vue new file mode 100644 index 0000000..bff094f --- /dev/null +++ b/src/views/ai/chat/index/components/conversation/ConversationUpdateForm.vue @@ -0,0 +1,145 @@ + + diff --git a/src/views/ai/chat/index/components/message/MessageList.vue b/src/views/ai/chat/index/components/message/MessageList.vue new file mode 100644 index 0000000..b7402a9 --- /dev/null +++ b/src/views/ai/chat/index/components/message/MessageList.vue @@ -0,0 +1,282 @@ + + + + diff --git a/src/views/ai/chat/index/components/message/MessageListEmpty.vue b/src/views/ai/chat/index/components/message/MessageListEmpty.vue new file mode 100644 index 0000000..b042fd6 --- /dev/null +++ b/src/views/ai/chat/index/components/message/MessageListEmpty.vue @@ -0,0 +1,83 @@ + + + + diff --git a/src/views/ai/chat/index/components/message/MessageLoading.vue b/src/views/ai/chat/index/components/message/MessageLoading.vue new file mode 100644 index 0000000..f3198cb --- /dev/null +++ b/src/views/ai/chat/index/components/message/MessageLoading.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/ai/chat/index/components/message/MessageNewConversation.vue b/src/views/ai/chat/index/components/message/MessageNewConversation.vue new file mode 100644 index 0000000..40c3107 --- /dev/null +++ b/src/views/ai/chat/index/components/message/MessageNewConversation.vue @@ -0,0 +1,46 @@ + + + + diff --git a/src/views/ai/chat/index/components/role/RoleCategoryList.vue b/src/views/ai/chat/index/components/role/RoleCategoryList.vue new file mode 100644 index 0000000..c02126d --- /dev/null +++ b/src/views/ai/chat/index/components/role/RoleCategoryList.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/views/ai/chat/index/components/role/RoleHeader.vue b/src/views/ai/chat/index/components/role/RoleHeader.vue new file mode 100644 index 0000000..17b1693 --- /dev/null +++ b/src/views/ai/chat/index/components/role/RoleHeader.vue @@ -0,0 +1,48 @@ + + + + + + diff --git a/src/views/ai/chat/index/components/role/RoleList.vue b/src/views/ai/chat/index/components/role/RoleList.vue new file mode 100644 index 0000000..b148b22 --- /dev/null +++ b/src/views/ai/chat/index/components/role/RoleList.vue @@ -0,0 +1,174 @@ + + + + + + diff --git a/src/views/ai/chat/index/components/role/RoleRepository.vue b/src/views/ai/chat/index/components/role/RoleRepository.vue new file mode 100644 index 0000000..246dcb4 --- /dev/null +++ b/src/views/ai/chat/index/components/role/RoleRepository.vue @@ -0,0 +1,289 @@ + + + + + + + + diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue new file mode 100644 index 0000000..28f1d65 --- /dev/null +++ b/src/views/ai/chat/index/index.vue @@ -0,0 +1,772 @@ + + + + + diff --git a/src/views/ai/chat/manager/ChatConversationList.vue b/src/views/ai/chat/manager/ChatConversationList.vue new file mode 100644 index 0000000..23933f0 --- /dev/null +++ b/src/views/ai/chat/manager/ChatConversationList.vue @@ -0,0 +1,163 @@ + + + diff --git a/src/views/ai/chat/manager/ChatMessageList.vue b/src/views/ai/chat/manager/ChatMessageList.vue new file mode 100644 index 0000000..0d84184 --- /dev/null +++ b/src/views/ai/chat/manager/ChatMessageList.vue @@ -0,0 +1,175 @@ + + + diff --git a/src/views/ai/chat/manager/index.vue b/src/views/ai/chat/manager/index.vue new file mode 100644 index 0000000..ca2d092 --- /dev/null +++ b/src/views/ai/chat/manager/index.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/views/ai/image/index/components/ImageCard.vue b/src/views/ai/image/index/components/ImageCard.vue new file mode 100644 index 0000000..4ba78ca --- /dev/null +++ b/src/views/ai/image/index/components/ImageCard.vue @@ -0,0 +1,162 @@ + + + + diff --git a/src/views/ai/image/index/components/ImageDetail.vue b/src/views/ai/image/index/components/ImageDetail.vue new file mode 100644 index 0000000..ad15aa8 --- /dev/null +++ b/src/views/ai/image/index/components/ImageDetail.vue @@ -0,0 +1,224 @@ + + + + diff --git a/src/views/ai/image/index/components/ImageList.vue b/src/views/ai/image/index/components/ImageList.vue new file mode 100644 index 0000000..ced006f --- /dev/null +++ b/src/views/ai/image/index/components/ImageList.vue @@ -0,0 +1,245 @@ + + + diff --git a/src/views/ai/image/index/components/dall3/index.vue b/src/views/ai/image/index/components/dall3/index.vue new file mode 100644 index 0000000..5c891ab --- /dev/null +++ b/src/views/ai/image/index/components/dall3/index.vue @@ -0,0 +1,320 @@ + + + + diff --git a/src/views/ai/image/index/components/midjourney/index.vue b/src/views/ai/image/index/components/midjourney/index.vue new file mode 100644 index 0000000..1d7fda1 --- /dev/null +++ b/src/views/ai/image/index/components/midjourney/index.vue @@ -0,0 +1,326 @@ + + + + diff --git a/src/views/ai/image/index/components/other/index.vue b/src/views/ai/image/index/components/other/index.vue new file mode 100644 index 0000000..a688be1 --- /dev/null +++ b/src/views/ai/image/index/components/other/index.vue @@ -0,0 +1,216 @@ + + + + diff --git a/src/views/ai/image/index/components/stableDiffusion/index.vue b/src/views/ai/image/index/components/stableDiffusion/index.vue new file mode 100644 index 0000000..169938f --- /dev/null +++ b/src/views/ai/image/index/components/stableDiffusion/index.vue @@ -0,0 +1,272 @@ + + + + diff --git a/src/views/ai/image/index/index.vue b/src/views/ai/image/index/index.vue new file mode 100644 index 0000000..1217e79 --- /dev/null +++ b/src/views/ai/image/index/index.vue @@ -0,0 +1,141 @@ + + + + + + diff --git a/src/views/ai/image/manager/index.vue b/src/views/ai/image/manager/index.vue new file mode 100644 index 0000000..d2cefe6 --- /dev/null +++ b/src/views/ai/image/manager/index.vue @@ -0,0 +1,251 @@ + + + diff --git a/src/views/ai/image/square/index.vue b/src/views/ai/image/square/index.vue new file mode 100644 index 0000000..3da6cde --- /dev/null +++ b/src/views/ai/image/square/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/src/views/ai/mindmap/index/components/Left.vue b/src/views/ai/mindmap/index/components/Left.vue new file mode 100644 index 0000000..e684b88 --- /dev/null +++ b/src/views/ai/mindmap/index/components/Left.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/views/ai/mindmap/index/components/Right.vue b/src/views/ai/mindmap/index/components/Right.vue new file mode 100644 index 0000000..b1d04de --- /dev/null +++ b/src/views/ai/mindmap/index/components/Right.vue @@ -0,0 +1,167 @@ + + + + diff --git a/src/views/ai/mindmap/index/index.vue b/src/views/ai/mindmap/index/index.vue new file mode 100644 index 0000000..b85f20b --- /dev/null +++ b/src/views/ai/mindmap/index/index.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/views/ai/mindmap/manager/index.vue b/src/views/ai/mindmap/manager/index.vue new file mode 100644 index 0000000..9e873b9 --- /dev/null +++ b/src/views/ai/mindmap/manager/index.vue @@ -0,0 +1,189 @@ + + + diff --git a/src/views/ai/model/apiKey/ApiKeyForm.vue b/src/views/ai/model/apiKey/ApiKeyForm.vue new file mode 100644 index 0000000..2d3d4bf --- /dev/null +++ b/src/views/ai/model/apiKey/ApiKeyForm.vue @@ -0,0 +1,132 @@ + + diff --git a/src/views/ai/model/apiKey/index.vue b/src/views/ai/model/apiKey/index.vue new file mode 100644 index 0000000..6daf6a7 --- /dev/null +++ b/src/views/ai/model/apiKey/index.vue @@ -0,0 +1,180 @@ + + + diff --git a/src/views/ai/model/chatModel/ChatModelForm.vue b/src/views/ai/model/chatModel/ChatModelForm.vue new file mode 100644 index 0000000..ed9747a --- /dev/null +++ b/src/views/ai/model/chatModel/ChatModelForm.vue @@ -0,0 +1,181 @@ + + diff --git a/src/views/ai/model/chatModel/index.vue b/src/views/ai/model/chatModel/index.vue new file mode 100644 index 0000000..c550674 --- /dev/null +++ b/src/views/ai/model/chatModel/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/src/views/ai/model/chatRole/ChatRoleForm.vue b/src/views/ai/model/chatRole/ChatRoleForm.vue new file mode 100644 index 0000000..18d1a0d --- /dev/null +++ b/src/views/ai/model/chatRole/ChatRoleForm.vue @@ -0,0 +1,183 @@ + + diff --git a/src/views/ai/model/chatRole/index.vue b/src/views/ai/model/chatRole/index.vue new file mode 100644 index 0000000..e870a55 --- /dev/null +++ b/src/views/ai/model/chatRole/index.vue @@ -0,0 +1,187 @@ + + + diff --git a/src/views/ai/music/index/index.vue b/src/views/ai/music/index/index.vue new file mode 100644 index 0000000..413792a --- /dev/null +++ b/src/views/ai/music/index/index.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/views/ai/music/index/list/audioBar/index.vue b/src/views/ai/music/index/list/audioBar/index.vue new file mode 100644 index 0000000..db7f767 --- /dev/null +++ b/src/views/ai/music/index/list/audioBar/index.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/views/ai/music/index/list/index.vue b/src/views/ai/music/index/list/index.vue new file mode 100644 index 0000000..6c33f56 --- /dev/null +++ b/src/views/ai/music/index/list/index.vue @@ -0,0 +1,108 @@ + + + + + + diff --git a/src/views/ai/music/index/list/songCard/index.vue b/src/views/ai/music/index/list/songCard/index.vue new file mode 100644 index 0000000..0534251 --- /dev/null +++ b/src/views/ai/music/index/list/songCard/index.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/views/ai/music/index/list/songInfo/index.vue b/src/views/ai/music/index/list/songInfo/index.vue new file mode 100644 index 0000000..8d67c4d --- /dev/null +++ b/src/views/ai/music/index/list/songInfo/index.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/views/ai/music/index/mode/desc.vue b/src/views/ai/music/index/mode/desc.vue new file mode 100644 index 0000000..4488461 --- /dev/null +++ b/src/views/ai/music/index/mode/desc.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/views/ai/music/index/mode/index.vue b/src/views/ai/music/index/mode/index.vue new file mode 100644 index 0000000..32cad7e --- /dev/null +++ b/src/views/ai/music/index/mode/index.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/views/ai/music/index/mode/lyric.vue b/src/views/ai/music/index/mode/lyric.vue new file mode 100644 index 0000000..f774003 --- /dev/null +++ b/src/views/ai/music/index/mode/lyric.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/ai/music/index/title/index.vue b/src/views/ai/music/index/title/index.vue new file mode 100644 index 0000000..a065802 --- /dev/null +++ b/src/views/ai/music/index/title/index.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/views/ai/music/manager/index.vue b/src/views/ai/music/manager/index.vue new file mode 100644 index 0000000..e1b9411 --- /dev/null +++ b/src/views/ai/music/manager/index.vue @@ -0,0 +1,292 @@ + + + diff --git a/src/views/ai/utils/constants.ts b/src/views/ai/utils/constants.ts new file mode 100644 index 0000000..be4da7b --- /dev/null +++ b/src/views/ai/utils/constants.ts @@ -0,0 +1,481 @@ +/** + * Created by 芋道源码 + * + * AI 枚举类 + * + * 问题:为什么不放在 src/utils/constants.ts 呢? + * 回答:主要 AI 是可选模块,考虑到独立、解耦,所以放在了 /views/ai/utils/constants.ts + */ + +/** + * AI 平台的枚举 + */ +export const AiPlatformEnum = { + TONG_YI: 'TongYi', // 阿里 + YI_YAN: 'YiYan', // 百度 + DEEP_SEEK: 'DeepSeek', // DeepSeek + ZHI_PU: 'ZhiPu', // 智谱 AI + XING_HUO: 'XingHuo', // 讯飞 + OPENAI: 'OpenAI', + Ollama: 'Ollama', + STABLE_DIFFUSION: 'StableDiffusion', // Stability AI + MIDJOURNEY: 'Midjourney', // Midjourney + SUNO: 'Suno' // Suno AI +} + +export const OtherPlatformEnum: ImageModelVO[] = [ + { + key: AiPlatformEnum.TONG_YI, + name: '通义万相' + }, + { + key: AiPlatformEnum.YI_YAN, + name: '百度千帆' + }, + { + key: AiPlatformEnum.ZHI_PU, + name: '智谱 AI' + } +] + +/** + * AI 图像生成状态的枚举 + */ +export const AiImageStatusEnum = { + IN_PROGRESS: 10, // 进行中 + SUCCESS: 20, // 已完成 + FAIL: 30 // 已失败 +} + +/** + * AI 音乐生成状态的枚举 + */ +export const AiMusicStatusEnum = { + IN_PROGRESS: 10, // 进行中 + SUCCESS: 20, // 已完成 + FAIL: 30 // 已失败 +} + +/** + * AI 写作类型的枚举 + */ +export enum AiWriteTypeEnum { + WRITING = 1, // 撰写 + REPLY // 回复 +} + +// 表格展示对照map +export const AiWriteTypeTableRender = { + [AiWriteTypeEnum.WRITING]: '撰写', + [AiWriteTypeEnum.REPLY]: '回复' +} + +// ========== 【图片 UI】相关的枚举 ========== + +export const ImageHotWords = [ + '中国旗袍', + '古装美女', + '卡通头像', + '机甲战士', + '童话小屋', + '中国长城' +] // 图片热词 + +export const ImageHotEnglishWords = [ + 'Chinese Cheongsam', + 'Ancient Beauty', + 'Cartoon Avatar', + 'Mech Warrior', + 'Fairy Tale Cottage', + 'The Great Wall of China' +] // 图片热词(英文) + +export interface ImageModelVO { + key: string + name: string + image?: string +} + +export const StableDiffusionSamplers: ImageModelVO[] = [ + { + key: 'DDIM', + name: 'DDIM' + }, + { + key: 'DDPM', + name: 'DDPM' + }, + { + key: 'K_DPMPP_2M', + name: 'K_DPMPP_2M' + }, + { + key: 'K_DPMPP_2S_ANCESTRAL', + name: 'K_DPMPP_2S_ANCESTRAL' + }, + { + key: 'K_DPM_2', + name: 'K_DPM_2' + }, + { + key: 'K_DPM_2_ANCESTRAL', + name: 'K_DPM_2_ANCESTRAL' + }, + { + key: 'K_EULER', + name: 'K_EULER' + }, + { + key: 'K_EULER_ANCESTRAL', + name: 'K_EULER_ANCESTRAL' + }, + { + key: 'K_HEUN', + name: 'K_HEUN' + }, + { + key: 'K_LMS', + name: 'K_LMS' + } +] + +export const StableDiffusionStylePresets: ImageModelVO[] = [ + { + key: '3d-model', + name: '3d-model' + }, + { + key: 'analog-film', + name: 'analog-film' + }, + { + key: 'anime', + name: 'anime' + }, + { + key: 'cinematic', + name: 'cinematic' + }, + { + key: 'comic-book', + name: 'comic-book' + }, + { + key: 'digital-art', + name: 'digital-art' + }, + { + key: 'enhance', + name: 'enhance' + }, + { + key: 'fantasy-art', + name: 'fantasy-art' + }, + { + key: 'isometric', + name: 'isometric' + }, + { + key: 'line-art', + name: 'line-art' + }, + { + key: 'low-poly', + name: 'low-poly' + }, + { + key: 'modeling-compound', + name: 'modeling-compound' + }, + // neon-punk origami photographic pixel-art tile-texture + { + key: 'neon-punk', + name: 'neon-punk' + }, + { + key: 'origami', + name: 'origami' + }, + { + key: 'photographic', + name: 'photographic' + }, + { + key: 'pixel-art', + name: 'pixel-art' + }, + { + key: 'tile-texture', + name: 'tile-texture' + } +] + +export const TongYiWanXiangModels: ImageModelVO[] = [ + { + key: 'wanx-v1', + name: 'wanx-v1' + }, + { + key: 'wanx-sketch-to-image-v1', + name: 'wanx-sketch-to-image-v1' + } +] + +export const QianFanModels: ImageModelVO[] = [ + { + key: 'sd_xl', + name: 'sd_xl' + } +] + +export const ChatGlmModels: ImageModelVO[] = [ + { + key: 'cogview-3', + name: 'cogview-3' + } +] + +export const StableDiffusionClipGuidancePresets: ImageModelVO[] = [ + { + key: 'NONE', + name: 'NONE' + }, + { + key: 'FAST_BLUE', + name: 'FAST_BLUE' + }, + { + key: 'FAST_GREEN', + name: 'FAST_GREEN' + }, + { + key: 'SIMPLE', + name: 'SIMPLE' + }, + { + key: 'SLOW', + name: 'SLOW' + }, + { + key: 'SLOWER', + name: 'SLOWER' + }, + { + key: 'SLOWEST', + name: 'SLOWEST' + } +] + +export const Dall3Models: ImageModelVO[] = [ + { + key: 'dall-e-3', + name: 'DALL·E 3', + image: `/src/assets/ai/dall2.jpg` + }, + { + key: 'dall-e-2', + name: 'DALL·E 2', + image: `/src/assets/ai/dall3.jpg` + } +] + +export const Dall3StyleList: ImageModelVO[] = [ + { + key: 'vivid', + name: '清晰', + image: `/src/assets/ai/qingxi.jpg` + }, + { + key: 'natural', + name: '自然', + image: `/src/assets/ai/ziran.jpg` + } +] + +export interface ImageSizeVO { + key: string + name?: string + style: string + width: string + height: string +} + +export const Dall3SizeList: ImageSizeVO[] = [ + { + key: '1024x1024', + name: '1:1', + width: '1024', + height: '1024', + style: 'width: 30px; height: 30px;background-color: #dcdcdc;' + }, + { + key: '1024x1792', + name: '3:5', + width: '1024', + height: '1792', + style: 'width: 30px; height: 50px;background-color: #dcdcdc;' + }, + { + key: '1792x1024', + name: '5:3', + width: '1792', + height: '1024', + style: 'width: 50px; height: 30px;background-color: #dcdcdc;' + } +] + +export const MidjourneyModels: ImageModelVO[] = [ + { + key: 'midjourney', + name: 'MJ', + image: 'https://bigpt8.com/pc/_nuxt/mj.34a61377.png' + }, + { + key: 'niji', + name: 'NIJI', + image: 'https://bigpt8.com/pc/_nuxt/nj.ca79b143.png' + } +] + +export const MidjourneySizeList: ImageSizeVO[] = [ + { + key: '1:1', + width: '1', + height: '1', + style: 'width: 30px; height: 30px;background-color: #dcdcdc;' + }, + { + key: '3:4', + width: '3', + height: '4', + style: 'width: 30px; height: 40px;background-color: #dcdcdc;' + }, + { + key: '4:3', + width: '4', + height: '3', + style: 'width: 40px; height: 30px;background-color: #dcdcdc;' + }, + { + key: '9:16', + width: '9', + height: '16', + style: 'width: 30px; height: 50px;background-color: #dcdcdc;' + }, + { + key: '16:9', + width: '16', + height: '9', + style: 'width: 50px; height: 30px;background-color: #dcdcdc;' + } +] + +export const MidjourneyVersions = [ + { + value: '6.0', + label: 'v6.0' + }, + { + value: '5.2', + label: 'v5.2' + }, + { + value: '5.1', + label: 'v5.1' + }, + { + value: '5.0', + label: 'v5.0' + }, + { + value: '4.0', + label: 'v4.0' + } +] + +export const NijiVersionList = [ + { + value: '5', + label: 'v5' + } +] + +// ========== 【写作 UI】相关的枚举 ========== + +/** 写作点击示例时的数据 **/ +export const WriteExample = { + write: { + prompt: 'vue', + data: 'Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定:Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化:Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOM:Vue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex,以支持构建复杂的单页应用(SPA)。\n\n在开发过程中,开发者通常会使用 Vue CLI,这是一个强大的命令行工具,用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 Vuetify(UI 组件库)、Vue Test Utils(测试工具)等,这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说,Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。' + }, + reply: { + originalContent: '领导,我想请假', + prompt: '不批', + data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。' + } +} + +// ========== 【思维导图 UI】相关的枚举 ========== + +/** 思维导图已有内容生成示例 **/ +export const MindMapContentExample = `# Java 技术栈 + +## 核心技术 +### Java SE +### Java EE + +## 框架 +### Spring +#### Spring Boot +#### Spring MVC +#### Spring Data +### Hibernate +### MyBatis + +## 构建工具 +### Maven +### Gradle + +## 版本控制 +### Git +### SVN + +## 测试工具 +### JUnit +### Mockito +### Selenium + +## 应用服务器 +### Tomcat +### Jetty +### WildFly + +## 数据库 +### MySQL +### PostgreSQL +### Oracle +### MongoDB + +## 消息队列 +### Kafka +### RabbitMQ +### ActiveMQ + +## 微服务 +### Spring Cloud +### Dubbo + +## 容器化 +### Docker +### Kubernetes + +## 云服务 +### AWS +### Azure +### Google Cloud + +## 开发工具 +### IntelliJ IDEA +### Eclipse +### Visual Studio Code` diff --git a/src/views/ai/utils/utils.ts b/src/views/ai/utils/utils.ts new file mode 100644 index 0000000..ab45ae1 --- /dev/null +++ b/src/views/ai/utils/utils.ts @@ -0,0 +1,13 @@ +/** + * Created by 芋道源码 + * + * AI 枚举类 + * + * 问题:为什么不放在 src/utils/common-utils.ts 呢? + * 回答:主要 AI 是可选模块,考虑到独立、解耦,所以放在了 /views/ai/utils/common-utils.ts + */ + +/** 判断字符串是否包含中文 */ +export const hasChinese = (str: string) => { + return /[\u4e00-\u9fa5]/.test(str) +} diff --git a/src/views/ai/write/index/components/Left.vue b/src/views/ai/write/index/components/Left.vue new file mode 100644 index 0000000..74e5d58 --- /dev/null +++ b/src/views/ai/write/index/components/Left.vue @@ -0,0 +1,213 @@ + + + diff --git a/src/views/ai/write/index/components/Right.vue b/src/views/ai/write/index/components/Right.vue new file mode 100644 index 0000000..d0aada5 --- /dev/null +++ b/src/views/ai/write/index/components/Right.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/views/ai/write/index/components/Tag.vue b/src/views/ai/write/index/components/Tag.vue new file mode 100644 index 0000000..3d616be --- /dev/null +++ b/src/views/ai/write/index/components/Tag.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/views/ai/write/index/index.vue b/src/views/ai/write/index/index.vue new file mode 100644 index 0000000..0dfda74 --- /dev/null +++ b/src/views/ai/write/index/index.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/views/ai/write/manager/index.vue b/src/views/ai/write/manager/index.vue new file mode 100644 index 0000000..ddd1400 --- /dev/null +++ b/src/views/ai/write/manager/index.vue @@ -0,0 +1,256 @@ + + + diff --git a/src/views/bpm/category/CategoryForm.vue b/src/views/bpm/category/CategoryForm.vue new file mode 100644 index 0000000..9c24b3e --- /dev/null +++ b/src/views/bpm/category/CategoryForm.vue @@ -0,0 +1,125 @@ + + diff --git a/src/views/bpm/category/index.vue b/src/views/bpm/category/index.vue new file mode 100644 index 0000000..085b371 --- /dev/null +++ b/src/views/bpm/category/index.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/views/bpm/definition/index.vue b/src/views/bpm/definition/index.vue new file mode 100644 index 0000000..55da993 --- /dev/null +++ b/src/views/bpm/definition/index.vue @@ -0,0 +1,143 @@ + + + diff --git a/src/views/bpm/form/editor/index.vue b/src/views/bpm/form/editor/index.vue new file mode 100644 index 0000000..12945e0 --- /dev/null +++ b/src/views/bpm/form/editor/index.vue @@ -0,0 +1,164 @@ + + + + diff --git a/src/views/bpm/form/index.vue b/src/views/bpm/form/index.vue new file mode 100644 index 0000000..46edd8f --- /dev/null +++ b/src/views/bpm/form/index.vue @@ -0,0 +1,196 @@ + + + diff --git a/src/views/bpm/group/UserGroupForm.vue b/src/views/bpm/group/UserGroupForm.vue new file mode 100644 index 0000000..3c825eb --- /dev/null +++ b/src/views/bpm/group/UserGroupForm.vue @@ -0,0 +1,132 @@ + + diff --git a/src/views/bpm/group/index.vue b/src/views/bpm/group/index.vue new file mode 100644 index 0000000..62785a9 --- /dev/null +++ b/src/views/bpm/group/index.vue @@ -0,0 +1,191 @@ + + + diff --git a/src/views/bpm/model/CategoryDraggableModel.vue b/src/views/bpm/model/CategoryDraggableModel.vue new file mode 100644 index 0000000..f3b5a42 --- /dev/null +++ b/src/views/bpm/model/CategoryDraggableModel.vue @@ -0,0 +1,511 @@ + + + + + + diff --git a/src/views/bpm/model/ModelForm.vue b/src/views/bpm/model/ModelForm.vue new file mode 100644 index 0000000..2b4bcc6 --- /dev/null +++ b/src/views/bpm/model/ModelForm.vue @@ -0,0 +1,440 @@ + + + + diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue new file mode 100644 index 0000000..37eff73 --- /dev/null +++ b/src/views/bpm/model/editor/index.vue @@ -0,0 +1,279 @@ + + + + diff --git a/src/views/bpm/model/form/BasicInfo.vue b/src/views/bpm/model/form/BasicInfo.vue new file mode 100644 index 0000000..0359ea8 --- /dev/null +++ b/src/views/bpm/model/form/BasicInfo.vue @@ -0,0 +1,301 @@ + + + + + diff --git a/src/views/bpm/model/form/FormDesign.vue b/src/views/bpm/model/form/FormDesign.vue new file mode 100644 index 0000000..98aee6d --- /dev/null +++ b/src/views/bpm/model/form/FormDesign.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/views/bpm/model/form/ProcessDesign.vue b/src/views/bpm/model/form/ProcessDesign.vue new file mode 100644 index 0000000..40d35ab --- /dev/null +++ b/src/views/bpm/model/form/ProcessDesign.vue @@ -0,0 +1,235 @@ + + + diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue new file mode 100644 index 0000000..4585fc6 --- /dev/null +++ b/src/views/bpm/model/form/index.vue @@ -0,0 +1,439 @@ + + + + + diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue new file mode 100644 index 0000000..c7d9417 --- /dev/null +++ b/src/views/bpm/model/index.vue @@ -0,0 +1,229 @@ + + + + + diff --git a/src/views/bpm/oa/leave/create.vue b/src/views/bpm/oa/leave/create.vue new file mode 100644 index 0000000..28a15af --- /dev/null +++ b/src/views/bpm/oa/leave/create.vue @@ -0,0 +1,164 @@ + + diff --git a/src/views/bpm/oa/leave/detail.vue b/src/views/bpm/oa/leave/detail.vue new file mode 100644 index 0000000..87036d8 --- /dev/null +++ b/src/views/bpm/oa/leave/detail.vue @@ -0,0 +1,51 @@ + + diff --git a/src/views/bpm/oa/leave/index.vue b/src/views/bpm/oa/leave/index.vue new file mode 100644 index 0000000..27dbc19 --- /dev/null +++ b/src/views/bpm/oa/leave/index.vue @@ -0,0 +1,257 @@ + + diff --git a/src/views/bpm/processExpression/ProcessExpressionForm.vue b/src/views/bpm/processExpression/ProcessExpressionForm.vue new file mode 100644 index 0000000..2e5ed2e --- /dev/null +++ b/src/views/bpm/processExpression/ProcessExpressionForm.vue @@ -0,0 +1,114 @@ + + diff --git a/src/views/bpm/processExpression/index.vue b/src/views/bpm/processExpression/index.vue new file mode 100644 index 0000000..ec2de5a --- /dev/null +++ b/src/views/bpm/processExpression/index.vue @@ -0,0 +1,182 @@ + + + diff --git a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue new file mode 100644 index 0000000..64d072c --- /dev/null +++ b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue @@ -0,0 +1,298 @@ + + + + diff --git a/src/views/bpm/processInstance/create/index.vue b/src/views/bpm/processInstance/create/index.vue new file mode 100644 index 0000000..284cbdb --- /dev/null +++ b/src/views/bpm/processInstance/create/index.vue @@ -0,0 +1,299 @@ + + + + + diff --git a/src/views/bpm/processInstance/create/index_old.vue b/src/views/bpm/processInstance/create/index_old.vue new file mode 100644 index 0000000..83e1ff4 --- /dev/null +++ b/src/views/bpm/processInstance/create/index_old.vue @@ -0,0 +1,267 @@ + + diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue b/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue new file mode 100644 index 0000000..781263d --- /dev/null +++ b/src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue new file mode 100644 index 0000000..894a5d4 --- /dev/null +++ b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue @@ -0,0 +1,989 @@ + + + + diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue b/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue new file mode 100644 index 0000000..0808bec --- /dev/null +++ b/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue @@ -0,0 +1,168 @@ + + + + diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue new file mode 100644 index 0000000..8690e58 --- /dev/null +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue @@ -0,0 +1,103 @@ + + diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue new file mode 100644 index 0000000..e24316c --- /dev/null +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue @@ -0,0 +1,292 @@ + + + + diff --git a/src/views/bpm/processInstance/detail/index.vue b/src/views/bpm/processInstance/detail/index.vue new file mode 100644 index 0000000..9809f7a --- /dev/null +++ b/src/views/bpm/processInstance/detail/index.vue @@ -0,0 +1,354 @@ + + + + diff --git a/src/views/bpm/processInstance/index.vue b/src/views/bpm/processInstance/index.vue new file mode 100644 index 0000000..a47b8bf --- /dev/null +++ b/src/views/bpm/processInstance/index.vue @@ -0,0 +1,325 @@ + + + diff --git a/src/views/bpm/processInstance/manager/index.vue b/src/views/bpm/processInstance/manager/index.vue new file mode 100644 index 0000000..21e3a9e --- /dev/null +++ b/src/views/bpm/processInstance/manager/index.vue @@ -0,0 +1,259 @@ + + diff --git a/src/views/bpm/processListener/ProcessListenerForm.vue b/src/views/bpm/processListener/ProcessListenerForm.vue new file mode 100644 index 0000000..a9684df --- /dev/null +++ b/src/views/bpm/processListener/ProcessListenerForm.vue @@ -0,0 +1,162 @@ + + diff --git a/src/views/bpm/processListener/index.vue b/src/views/bpm/processListener/index.vue new file mode 100644 index 0000000..8b5c36e --- /dev/null +++ b/src/views/bpm/processListener/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/src/views/bpm/simple/SimpleModelDesign.vue b/src/views/bpm/simple/SimpleModelDesign.vue new file mode 100644 index 0000000..eed0099 --- /dev/null +++ b/src/views/bpm/simple/SimpleModelDesign.vue @@ -0,0 +1,155 @@ + + + diff --git a/src/views/bpm/task/copy/index.vue b/src/views/bpm/task/copy/index.vue new file mode 100644 index 0000000..f32a52a --- /dev/null +++ b/src/views/bpm/task/copy/index.vue @@ -0,0 +1,151 @@ + + + diff --git a/src/views/bpm/task/done/index.vue b/src/views/bpm/task/done/index.vue new file mode 100644 index 0000000..4d9cbd5 --- /dev/null +++ b/src/views/bpm/task/done/index.vue @@ -0,0 +1,246 @@ + + diff --git a/src/views/bpm/task/manager/index.vue b/src/views/bpm/task/manager/index.vue new file mode 100644 index 0000000..688e515 --- /dev/null +++ b/src/views/bpm/task/manager/index.vue @@ -0,0 +1,166 @@ + + diff --git a/src/views/bpm/task/todo/index.vue b/src/views/bpm/task/todo/index.vue new file mode 100644 index 0000000..3212937 --- /dev/null +++ b/src/views/bpm/task/todo/index.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/crm/backlog/components/ClueFollowList.vue b/src/views/crm/backlog/components/ClueFollowList.vue new file mode 100644 index 0000000..4ed37d4 --- /dev/null +++ b/src/views/crm/backlog/components/ClueFollowList.vue @@ -0,0 +1,153 @@ + + diff --git a/src/views/crm/backlog/components/ContractAuditList.vue b/src/views/crm/backlog/components/ContractAuditList.vue new file mode 100644 index 0000000..9c13237 --- /dev/null +++ b/src/views/crm/backlog/components/ContractAuditList.vue @@ -0,0 +1,247 @@ + + + + + + diff --git a/src/views/crm/backlog/components/ContractRemindList.vue b/src/views/crm/backlog/components/ContractRemindList.vue new file mode 100644 index 0000000..0cacf35 --- /dev/null +++ b/src/views/crm/backlog/components/ContractRemindList.vue @@ -0,0 +1,246 @@ + + + + diff --git a/src/views/crm/backlog/components/CustomerFollowList.vue b/src/views/crm/backlog/components/CustomerFollowList.vue new file mode 100644 index 0000000..0f367a3 --- /dev/null +++ b/src/views/crm/backlog/components/CustomerFollowList.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/src/views/crm/backlog/components/CustomerPutPoolRemindList.vue b/src/views/crm/backlog/components/CustomerPutPoolRemindList.vue new file mode 100644 index 0000000..17f8df6 --- /dev/null +++ b/src/views/crm/backlog/components/CustomerPutPoolRemindList.vue @@ -0,0 +1,169 @@ + + + + + + diff --git a/src/views/crm/backlog/components/CustomerTodayContactList.vue b/src/views/crm/backlog/components/CustomerTodayContactList.vue new file mode 100644 index 0000000..87aa31d --- /dev/null +++ b/src/views/crm/backlog/components/CustomerTodayContactList.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/views/crm/backlog/components/ReceivableAuditList.vue b/src/views/crm/backlog/components/ReceivableAuditList.vue new file mode 100644 index 0000000..2831d45 --- /dev/null +++ b/src/views/crm/backlog/components/ReceivableAuditList.vue @@ -0,0 +1,201 @@ + + + + diff --git a/src/views/crm/backlog/components/ReceivablePlanRemindList.vue b/src/views/crm/backlog/components/ReceivablePlanRemindList.vue new file mode 100644 index 0000000..9a3cf0c --- /dev/null +++ b/src/views/crm/backlog/components/ReceivablePlanRemindList.vue @@ -0,0 +1,220 @@ + + + + diff --git a/src/views/crm/backlog/components/common.ts b/src/views/crm/backlog/components/common.ts new file mode 100644 index 0000000..9ff6bfc --- /dev/null +++ b/src/views/crm/backlog/components/common.ts @@ -0,0 +1,39 @@ +/** 跟进状态 */ +export const FOLLOWUP_STATUS = [ + { label: '待跟进', value: false }, + { label: '已跟进', value: true } +] + +/** 归属范围 */ +export const SCENE_TYPES = [ + { label: '我负责的', value: 1 }, + { label: '我参与的', value: 2 }, + { label: '下属负责的', value: 3 } +] + +/** 联系状态 */ +export const CONTACT_STATUS = [ + { label: '今日需联系', value: 1 }, + { label: '已逾期', value: 2 }, + { label: '已联系', value: 3 } +] + +/** 审批状态 */ +export const AUDIT_STATUS = [ + { label: '待审批', value: 10 }, + { label: '审核通过', value: 20 }, + { label: '审核不通过', value: 30 } +] + +/** 回款提醒类型 */ +export const RECEIVABLE_REMIND_TYPE = [ + { label: '待回款', value: 1 }, + { label: '已逾期', value: 2 }, + { label: '已回款', value: 3 } +] + +/** 合同过期状态 */ +export const CONTRACT_EXPIRY_TYPE = [ + { label: '即将过期', value: 1 }, + { label: '已过期', value: 2 } +] diff --git a/src/views/crm/backlog/index.vue b/src/views/crm/backlog/index.vue new file mode 100644 index 0000000..49a1d4c --- /dev/null +++ b/src/views/crm/backlog/index.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/src/views/crm/business/BusinessForm.vue b/src/views/crm/business/BusinessForm.vue new file mode 100644 index 0000000..4af1abe --- /dev/null +++ b/src/views/crm/business/BusinessForm.vue @@ -0,0 +1,287 @@ + + diff --git a/src/views/crm/business/BusinessUpdateStatusForm.vue b/src/views/crm/business/BusinessUpdateStatusForm.vue new file mode 100644 index 0000000..4f2f761 --- /dev/null +++ b/src/views/crm/business/BusinessUpdateStatusForm.vue @@ -0,0 +1,108 @@ + + diff --git a/src/views/crm/business/components/BusinessList.vue b/src/views/crm/business/components/BusinessList.vue new file mode 100644 index 0000000..f990606 --- /dev/null +++ b/src/views/crm/business/components/BusinessList.vue @@ -0,0 +1,186 @@ + + diff --git a/src/views/crm/business/components/BusinessListModal.vue b/src/views/crm/business/components/BusinessListModal.vue new file mode 100644 index 0000000..3c21f06 --- /dev/null +++ b/src/views/crm/business/components/BusinessListModal.vue @@ -0,0 +1,156 @@ + + diff --git a/src/views/crm/business/components/BusinessProductForm.vue b/src/views/crm/business/components/BusinessProductForm.vue new file mode 100644 index 0000000..fbba065 --- /dev/null +++ b/src/views/crm/business/components/BusinessProductForm.vue @@ -0,0 +1,183 @@ + + diff --git a/src/views/crm/business/detail/BusinessDetailsHeader.vue b/src/views/crm/business/detail/BusinessDetailsHeader.vue new file mode 100644 index 0000000..50d1efe --- /dev/null +++ b/src/views/crm/business/detail/BusinessDetailsHeader.vue @@ -0,0 +1,37 @@ + + diff --git a/src/views/crm/business/detail/BusinessDetailsInfo.vue b/src/views/crm/business/detail/BusinessDetailsInfo.vue new file mode 100644 index 0000000..a2c9ce1 --- /dev/null +++ b/src/views/crm/business/detail/BusinessDetailsInfo.vue @@ -0,0 +1,61 @@ + + diff --git a/src/views/crm/business/detail/BusinessProductList.vue b/src/views/crm/business/detail/BusinessProductList.vue new file mode 100644 index 0000000..9a31665 --- /dev/null +++ b/src/views/crm/business/detail/BusinessProductList.vue @@ -0,0 +1,66 @@ + + diff --git a/src/views/crm/business/detail/index.vue b/src/views/crm/business/detail/index.vue new file mode 100644 index 0000000..dbab819 --- /dev/null +++ b/src/views/crm/business/detail/index.vue @@ -0,0 +1,146 @@ + + diff --git a/src/views/crm/business/index.vue b/src/views/crm/business/index.vue new file mode 100644 index 0000000..84e447c --- /dev/null +++ b/src/views/crm/business/index.vue @@ -0,0 +1,275 @@ + + + diff --git a/src/views/crm/business/status/BusinessStatusForm.vue b/src/views/crm/business/status/BusinessStatusForm.vue new file mode 100644 index 0000000..d6a4d6f --- /dev/null +++ b/src/views/crm/business/status/BusinessStatusForm.vue @@ -0,0 +1,194 @@ + + diff --git a/src/views/crm/business/status/index.vue b/src/views/crm/business/status/index.vue new file mode 100644 index 0000000..ef51488 --- /dev/null +++ b/src/views/crm/business/status/index.vue @@ -0,0 +1,150 @@ + + + diff --git a/src/views/crm/clue/ClueForm.vue b/src/views/crm/clue/ClueForm.vue new file mode 100644 index 0000000..3562c1c --- /dev/null +++ b/src/views/crm/clue/ClueForm.vue @@ -0,0 +1,260 @@ + + diff --git a/src/views/crm/clue/detail/ClueDetailsHeader.vue b/src/views/crm/clue/detail/ClueDetailsHeader.vue new file mode 100644 index 0000000..41552c7 --- /dev/null +++ b/src/views/crm/clue/detail/ClueDetailsHeader.vue @@ -0,0 +1,43 @@ + + diff --git a/src/views/crm/clue/detail/ClueDetailsInfo.vue b/src/views/crm/clue/detail/ClueDetailsInfo.vue new file mode 100644 index 0000000..5a1d01f --- /dev/null +++ b/src/views/crm/clue/detail/ClueDetailsInfo.vue @@ -0,0 +1,72 @@ + + + diff --git a/src/views/crm/clue/detail/index.vue b/src/views/crm/clue/detail/index.vue new file mode 100644 index 0000000..4c211e6 --- /dev/null +++ b/src/views/crm/clue/detail/index.vue @@ -0,0 +1,130 @@ + + diff --git a/src/views/crm/clue/index.vue b/src/views/crm/clue/index.vue new file mode 100644 index 0000000..f90d497 --- /dev/null +++ b/src/views/crm/clue/index.vue @@ -0,0 +1,270 @@ + + + diff --git a/src/views/crm/contact/ContactForm.vue b/src/views/crm/contact/ContactForm.vue new file mode 100644 index 0000000..81813e6 --- /dev/null +++ b/src/views/crm/contact/ContactForm.vue @@ -0,0 +1,311 @@ + + diff --git a/src/views/crm/contact/components/ContactList.vue b/src/views/crm/contact/components/ContactList.vue new file mode 100644 index 0000000..1c12ca8 --- /dev/null +++ b/src/views/crm/contact/components/ContactList.vue @@ -0,0 +1,185 @@ + + diff --git a/src/views/crm/contact/components/ContactListModal.vue b/src/views/crm/contact/components/ContactListModal.vue new file mode 100644 index 0000000..8b655c1 --- /dev/null +++ b/src/views/crm/contact/components/ContactListModal.vue @@ -0,0 +1,160 @@ + + diff --git a/src/views/crm/contact/detail/ContactDetailsHeader.vue b/src/views/crm/contact/detail/ContactDetailsHeader.vue new file mode 100644 index 0000000..12fb3bc --- /dev/null +++ b/src/views/crm/contact/detail/ContactDetailsHeader.vue @@ -0,0 +1,33 @@ + + diff --git a/src/views/crm/contact/detail/ContactDetailsInfo.vue b/src/views/crm/contact/detail/ContactDetailsInfo.vue new file mode 100644 index 0000000..9e8bfff --- /dev/null +++ b/src/views/crm/contact/detail/ContactDetailsInfo.vue @@ -0,0 +1,69 @@ + + diff --git a/src/views/crm/contact/detail/index.vue b/src/views/crm/contact/detail/index.vue new file mode 100644 index 0000000..7989d56 --- /dev/null +++ b/src/views/crm/contact/detail/index.vue @@ -0,0 +1,121 @@ + + diff --git a/src/views/crm/contact/index.vue b/src/views/crm/contact/index.vue new file mode 100644 index 0000000..ec26f1e --- /dev/null +++ b/src/views/crm/contact/index.vue @@ -0,0 +1,332 @@ + + + diff --git a/src/views/crm/contract/ContractForm.vue b/src/views/crm/contract/ContractForm.vue new file mode 100644 index 0000000..db2eec9 --- /dev/null +++ b/src/views/crm/contract/ContractForm.vue @@ -0,0 +1,369 @@ + + diff --git a/src/views/crm/contract/components/ContractList.vue b/src/views/crm/contract/components/ContractList.vue new file mode 100644 index 0000000..f693c9a --- /dev/null +++ b/src/views/crm/contract/components/ContractList.vue @@ -0,0 +1,136 @@ + + diff --git a/src/views/crm/contract/components/ContractProductForm.vue b/src/views/crm/contract/components/ContractProductForm.vue new file mode 100644 index 0000000..c33b996 --- /dev/null +++ b/src/views/crm/contract/components/ContractProductForm.vue @@ -0,0 +1,183 @@ + + diff --git a/src/views/crm/contract/config/index.vue b/src/views/crm/contract/config/index.vue new file mode 100644 index 0000000..c592123 --- /dev/null +++ b/src/views/crm/contract/config/index.vue @@ -0,0 +1,103 @@ + + diff --git a/src/views/crm/contract/detail/ContractDetailsHeader.vue b/src/views/crm/contract/detail/ContractDetailsHeader.vue new file mode 100644 index 0000000..9cfbfc7 --- /dev/null +++ b/src/views/crm/contract/detail/ContractDetailsHeader.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/views/crm/contract/detail/ContractDetailsInfo.vue b/src/views/crm/contract/detail/ContractDetailsInfo.vue new file mode 100644 index 0000000..73aa144 --- /dev/null +++ b/src/views/crm/contract/detail/ContractDetailsInfo.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/views/crm/contract/detail/ContractProductList.vue b/src/views/crm/contract/detail/ContractProductList.vue new file mode 100644 index 0000000..ea23d17 --- /dev/null +++ b/src/views/crm/contract/detail/ContractProductList.vue @@ -0,0 +1,66 @@ + + diff --git a/src/views/crm/contract/detail/index.vue b/src/views/crm/contract/detail/index.vue new file mode 100644 index 0000000..9d5e14c --- /dev/null +++ b/src/views/crm/contract/detail/index.vue @@ -0,0 +1,139 @@ + + + diff --git a/src/views/crm/contract/index.vue b/src/views/crm/contract/index.vue new file mode 100644 index 0000000..0c9d728 --- /dev/null +++ b/src/views/crm/contract/index.vue @@ -0,0 +1,398 @@ + + diff --git a/src/views/crm/customer/CustomerForm.vue b/src/views/crm/customer/CustomerForm.vue new file mode 100644 index 0000000..9a904d2 --- /dev/null +++ b/src/views/crm/customer/CustomerForm.vue @@ -0,0 +1,260 @@ + + diff --git a/src/views/crm/customer/CustomerImportForm.vue b/src/views/crm/customer/CustomerImportForm.vue new file mode 100644 index 0000000..17721a1 --- /dev/null +++ b/src/views/crm/customer/CustomerImportForm.vue @@ -0,0 +1,158 @@ + + + diff --git a/src/views/crm/customer/detail/CustomerDetailsHeader.vue b/src/views/crm/customer/detail/CustomerDetailsHeader.vue new file mode 100644 index 0000000..514ec61 --- /dev/null +++ b/src/views/crm/customer/detail/CustomerDetailsHeader.vue @@ -0,0 +1,43 @@ + + diff --git a/src/views/crm/customer/detail/CustomerDetailsInfo.vue b/src/views/crm/customer/detail/CustomerDetailsInfo.vue new file mode 100644 index 0000000..d9ea62a --- /dev/null +++ b/src/views/crm/customer/detail/CustomerDetailsInfo.vue @@ -0,0 +1,72 @@ + + + diff --git a/src/views/crm/customer/detail/index.vue b/src/views/crm/customer/detail/index.vue new file mode 100644 index 0000000..6818f69 --- /dev/null +++ b/src/views/crm/customer/detail/index.vue @@ -0,0 +1,222 @@ + + diff --git a/src/views/crm/customer/index.vue b/src/views/crm/customer/index.vue new file mode 100644 index 0000000..86bddc0 --- /dev/null +++ b/src/views/crm/customer/index.vue @@ -0,0 +1,343 @@ + + + diff --git a/src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue b/src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue new file mode 100644 index 0000000..c7338a4 --- /dev/null +++ b/src/views/crm/customer/limitConfig/CustomerLimitConfigForm.vue @@ -0,0 +1,150 @@ + + diff --git a/src/views/crm/customer/limitConfig/CustomerLimitConfigList.vue b/src/views/crm/customer/limitConfig/CustomerLimitConfigList.vue new file mode 100644 index 0000000..f5c488c --- /dev/null +++ b/src/views/crm/customer/limitConfig/CustomerLimitConfigList.vue @@ -0,0 +1,150 @@ + + diff --git a/src/views/crm/customer/limitConfig/index.vue b/src/views/crm/customer/limitConfig/index.vue new file mode 100644 index 0000000..01f3ef6 --- /dev/null +++ b/src/views/crm/customer/limitConfig/index.vue @@ -0,0 +1,22 @@ + + diff --git a/src/views/crm/customer/pool/CustomerDistributeForm.vue b/src/views/crm/customer/pool/CustomerDistributeForm.vue new file mode 100644 index 0000000..5fd80a1 --- /dev/null +++ b/src/views/crm/customer/pool/CustomerDistributeForm.vue @@ -0,0 +1,85 @@ + + diff --git a/src/views/crm/customer/pool/index.vue b/src/views/crm/customer/pool/index.vue new file mode 100644 index 0000000..eab90e0 --- /dev/null +++ b/src/views/crm/customer/pool/index.vue @@ -0,0 +1,270 @@ + + + diff --git a/src/views/crm/customer/poolConfig/index.vue b/src/views/crm/customer/poolConfig/index.vue new file mode 100644 index 0000000..28d58a6 --- /dev/null +++ b/src/views/crm/customer/poolConfig/index.vue @@ -0,0 +1,136 @@ + + diff --git a/src/views/crm/followup/FollowUpRecordForm.vue b/src/views/crm/followup/FollowUpRecordForm.vue new file mode 100644 index 0000000..eb626f0 --- /dev/null +++ b/src/views/crm/followup/FollowUpRecordForm.vue @@ -0,0 +1,188 @@ + + + diff --git a/src/views/crm/followup/components/FollowUpRecordBusinessForm.vue b/src/views/crm/followup/components/FollowUpRecordBusinessForm.vue new file mode 100644 index 0000000..620b5fb --- /dev/null +++ b/src/views/crm/followup/components/FollowUpRecordBusinessForm.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/views/crm/followup/components/FollowUpRecordContactForm.vue b/src/views/crm/followup/components/FollowUpRecordContactForm.vue new file mode 100644 index 0000000..b3b5d3a --- /dev/null +++ b/src/views/crm/followup/components/FollowUpRecordContactForm.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/crm/followup/index.vue b/src/views/crm/followup/index.vue new file mode 100644 index 0000000..d0b2271 --- /dev/null +++ b/src/views/crm/followup/index.vue @@ -0,0 +1,167 @@ + + + + diff --git a/src/views/crm/permission/components/PermissionForm.vue b/src/views/crm/permission/components/PermissionForm.vue new file mode 100644 index 0000000..632a347 --- /dev/null +++ b/src/views/crm/permission/components/PermissionForm.vue @@ -0,0 +1,137 @@ + + diff --git a/src/views/crm/permission/components/PermissionList.vue b/src/views/crm/permission/components/PermissionList.vue new file mode 100644 index 0000000..39c7aab --- /dev/null +++ b/src/views/crm/permission/components/PermissionList.vue @@ -0,0 +1,206 @@ + + diff --git a/src/views/crm/permission/components/TransferForm.vue b/src/views/crm/permission/components/TransferForm.vue new file mode 100644 index 0000000..43d5af7 --- /dev/null +++ b/src/views/crm/permission/components/TransferForm.vue @@ -0,0 +1,162 @@ + + + diff --git a/src/views/crm/product/ProductForm.vue b/src/views/crm/product/ProductForm.vue new file mode 100644 index 0000000..1bc5aac --- /dev/null +++ b/src/views/crm/product/ProductForm.vue @@ -0,0 +1,212 @@ + + diff --git a/src/views/crm/product/category/ProductCategoryForm.vue b/src/views/crm/product/category/ProductCategoryForm.vue new file mode 100644 index 0000000..0373fc3 --- /dev/null +++ b/src/views/crm/product/category/ProductCategoryForm.vue @@ -0,0 +1,110 @@ + + diff --git a/src/views/crm/product/category/index.vue b/src/views/crm/product/category/index.vue new file mode 100644 index 0000000..631c170 --- /dev/null +++ b/src/views/crm/product/category/index.vue @@ -0,0 +1,139 @@ + + + diff --git a/src/views/crm/product/detail/ProductDetailsHeader.vue b/src/views/crm/product/detail/ProductDetailsHeader.vue new file mode 100644 index 0000000..11286d6 --- /dev/null +++ b/src/views/crm/product/detail/ProductDetailsHeader.vue @@ -0,0 +1,46 @@ + + diff --git a/src/views/crm/product/detail/ProductDetailsInfo.vue b/src/views/crm/product/detail/ProductDetailsInfo.vue new file mode 100644 index 0000000..52a11e9 --- /dev/null +++ b/src/views/crm/product/detail/ProductDetailsInfo.vue @@ -0,0 +1,38 @@ + + diff --git a/src/views/crm/product/detail/index.vue b/src/views/crm/product/detail/index.vue new file mode 100644 index 0000000..65fdd0f --- /dev/null +++ b/src/views/crm/product/detail/index.vue @@ -0,0 +1,66 @@ + + diff --git a/src/views/crm/product/index.vue b/src/views/crm/product/index.vue new file mode 100644 index 0000000..5d656df --- /dev/null +++ b/src/views/crm/product/index.vue @@ -0,0 +1,230 @@ + + + diff --git a/src/views/crm/receivable/ReceivableForm.vue b/src/views/crm/receivable/ReceivableForm.vue new file mode 100644 index 0000000..61fac08 --- /dev/null +++ b/src/views/crm/receivable/ReceivableForm.vue @@ -0,0 +1,294 @@ + + diff --git a/src/views/crm/receivable/components/ReceivableList.vue b/src/views/crm/receivable/components/ReceivableList.vue new file mode 100644 index 0000000..67287ea --- /dev/null +++ b/src/views/crm/receivable/components/ReceivableList.vue @@ -0,0 +1,164 @@ + + diff --git a/src/views/crm/receivable/detail/ReceivableDetailsHeader.vue b/src/views/crm/receivable/detail/ReceivableDetailsHeader.vue new file mode 100644 index 0000000..62201de --- /dev/null +++ b/src/views/crm/receivable/detail/ReceivableDetailsHeader.vue @@ -0,0 +1,43 @@ + + diff --git a/src/views/crm/receivable/detail/ReceivableDetailsInfo.vue b/src/views/crm/receivable/detail/ReceivableDetailsInfo.vue new file mode 100644 index 0000000..003029f --- /dev/null +++ b/src/views/crm/receivable/detail/ReceivableDetailsInfo.vue @@ -0,0 +1,62 @@ + + diff --git a/src/views/crm/receivable/detail/index.vue b/src/views/crm/receivable/detail/index.vue new file mode 100644 index 0000000..3603572 --- /dev/null +++ b/src/views/crm/receivable/detail/index.vue @@ -0,0 +1,100 @@ + + diff --git a/src/views/crm/receivable/index.vue b/src/views/crm/receivable/index.vue new file mode 100644 index 0000000..6928942 --- /dev/null +++ b/src/views/crm/receivable/index.vue @@ -0,0 +1,335 @@ + + diff --git a/src/views/crm/receivable/plan/ReceivablePlanForm.vue b/src/views/crm/receivable/plan/ReceivablePlanForm.vue new file mode 100644 index 0000000..f321592 --- /dev/null +++ b/src/views/crm/receivable/plan/ReceivablePlanForm.vue @@ -0,0 +1,240 @@ + + diff --git a/src/views/crm/receivable/plan/components/ReceivablePlanList.vue b/src/views/crm/receivable/plan/components/ReceivablePlanList.vue new file mode 100644 index 0000000..3b80526 --- /dev/null +++ b/src/views/crm/receivable/plan/components/ReceivablePlanList.vue @@ -0,0 +1,173 @@ + + diff --git a/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue b/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue new file mode 100644 index 0000000..b0e0044 --- /dev/null +++ b/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue @@ -0,0 +1,44 @@ + + diff --git a/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue b/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue new file mode 100644 index 0000000..c25259b --- /dev/null +++ b/src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue @@ -0,0 +1,83 @@ + + diff --git a/src/views/crm/receivable/plan/detail/index.vue b/src/views/crm/receivable/plan/detail/index.vue new file mode 100644 index 0000000..fba8694 --- /dev/null +++ b/src/views/crm/receivable/plan/detail/index.vue @@ -0,0 +1,103 @@ + + diff --git a/src/views/crm/receivable/plan/index.vue b/src/views/crm/receivable/plan/index.vue new file mode 100644 index 0000000..43abe15 --- /dev/null +++ b/src/views/crm/receivable/plan/index.vue @@ -0,0 +1,335 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerConversionStat.vue b/src/views/crm/statistics/customer/components/CustomerConversionStat.vue new file mode 100644 index 0000000..4f5c50c --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerConversionStat.vue @@ -0,0 +1,170 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerDealCycleByArea.vue b/src/views/crm/statistics/customer/components/CustomerDealCycleByArea.vue new file mode 100644 index 0000000..9aa6d5e --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerDealCycleByArea.vue @@ -0,0 +1,153 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerDealCycleByProduct.vue b/src/views/crm/statistics/customer/components/CustomerDealCycleByProduct.vue new file mode 100644 index 0000000..74558d1 --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerDealCycleByProduct.vue @@ -0,0 +1,153 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerDealCycleByUser.vue b/src/views/crm/statistics/customer/components/CustomerDealCycleByUser.vue new file mode 100644 index 0000000..e3d877e --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerDealCycleByUser.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue b/src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue new file mode 100644 index 0000000..eeb0ff0 --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerFollowUpSummary.vue @@ -0,0 +1,156 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerFollowUpType.vue b/src/views/crm/statistics/customer/components/CustomerFollowUpType.vue new file mode 100644 index 0000000..3d8d873 --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerFollowUpType.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerPoolSummary.vue b/src/views/crm/statistics/customer/components/CustomerPoolSummary.vue new file mode 100644 index 0000000..5f0606a --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerPoolSummary.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/views/crm/statistics/customer/components/CustomerSummary.vue b/src/views/crm/statistics/customer/components/CustomerSummary.vue new file mode 100644 index 0000000..d1429c2 --- /dev/null +++ b/src/views/crm/statistics/customer/components/CustomerSummary.vue @@ -0,0 +1,183 @@ + + + diff --git a/src/views/crm/statistics/customer/index.vue b/src/views/crm/statistics/customer/index.vue new file mode 100644 index 0000000..207dc35 --- /dev/null +++ b/src/views/crm/statistics/customer/index.vue @@ -0,0 +1,214 @@ + + + + diff --git a/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue b/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue new file mode 100644 index 0000000..541d6fc --- /dev/null +++ b/src/views/crm/statistics/funnel/components/BusinessInversionRateSummary.vue @@ -0,0 +1,307 @@ + + + diff --git a/src/views/crm/statistics/funnel/components/BusinessSummary.vue b/src/views/crm/statistics/funnel/components/BusinessSummary.vue new file mode 100644 index 0000000..942a712 --- /dev/null +++ b/src/views/crm/statistics/funnel/components/BusinessSummary.vue @@ -0,0 +1,259 @@ + + + diff --git a/src/views/crm/statistics/funnel/components/FunnelBusiness.vue b/src/views/crm/statistics/funnel/components/FunnelBusiness.vue new file mode 100644 index 0000000..c4e4bf6 --- /dev/null +++ b/src/views/crm/statistics/funnel/components/FunnelBusiness.vue @@ -0,0 +1,149 @@ + + + diff --git a/src/views/crm/statistics/funnel/index.vue b/src/views/crm/statistics/funnel/index.vue new file mode 100644 index 0000000..804cb49 --- /dev/null +++ b/src/views/crm/statistics/funnel/index.vue @@ -0,0 +1,171 @@ + + + + diff --git a/src/views/crm/statistics/performance/components/ContractCountPerformance.vue b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue new file mode 100644 index 0000000..fa5a897 --- /dev/null +++ b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue new file mode 100644 index 0000000..dd52d9f --- /dev/null +++ b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue new file mode 100644 index 0000000..169f074 --- /dev/null +++ b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue @@ -0,0 +1,236 @@ + + + diff --git a/src/views/crm/statistics/performance/index.vue b/src/views/crm/statistics/performance/index.vue new file mode 100644 index 0000000..822afec --- /dev/null +++ b/src/views/crm/statistics/performance/index.vue @@ -0,0 +1,146 @@ + + + + diff --git a/src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue new file mode 100644 index 0000000..513936c --- /dev/null +++ b/src/views/crm/statistics/portrait/components/PortraitCustomerArea.vue @@ -0,0 +1,147 @@ + + + diff --git a/src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue new file mode 100644 index 0000000..d426993 --- /dev/null +++ b/src/views/crm/statistics/portrait/components/PortraitCustomerIndustry.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue new file mode 100644 index 0000000..653feef --- /dev/null +++ b/src/views/crm/statistics/portrait/components/PortraitCustomerLevel.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue new file mode 100644 index 0000000..ade6445 --- /dev/null +++ b/src/views/crm/statistics/portrait/components/PortraitCustomerSource.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/views/crm/statistics/portrait/index.vue b/src/views/crm/statistics/portrait/index.vue new file mode 100644 index 0000000..71807e1 --- /dev/null +++ b/src/views/crm/statistics/portrait/index.vue @@ -0,0 +1,156 @@ + + + + diff --git a/src/views/crm/statistics/rank/components/ContactCountRank.vue b/src/views/crm/statistics/rank/components/ContactCountRank.vue new file mode 100644 index 0000000..5edc118 --- /dev/null +++ b/src/views/crm/statistics/rank/components/ContactCountRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/ContractCountRank.vue b/src/views/crm/statistics/rank/components/ContractCountRank.vue new file mode 100644 index 0000000..fc50a6d --- /dev/null +++ b/src/views/crm/statistics/rank/components/ContractCountRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/ContractPriceRank.vue b/src/views/crm/statistics/rank/components/ContractPriceRank.vue new file mode 100644 index 0000000..b69ebd2 --- /dev/null +++ b/src/views/crm/statistics/rank/components/ContractPriceRank.vue @@ -0,0 +1,105 @@ + + + diff --git a/src/views/crm/statistics/rank/components/CustomerCountRank.vue b/src/views/crm/statistics/rank/components/CustomerCountRank.vue new file mode 100644 index 0000000..b66a681 --- /dev/null +++ b/src/views/crm/statistics/rank/components/CustomerCountRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/FollowCountRank.vue b/src/views/crm/statistics/rank/components/FollowCountRank.vue new file mode 100644 index 0000000..43352ab --- /dev/null +++ b/src/views/crm/statistics/rank/components/FollowCountRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/FollowCustomerCountRank.vue b/src/views/crm/statistics/rank/components/FollowCustomerCountRank.vue new file mode 100644 index 0000000..92a2205 --- /dev/null +++ b/src/views/crm/statistics/rank/components/FollowCustomerCountRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/ProductSalesRank.vue b/src/views/crm/statistics/rank/components/ProductSalesRank.vue new file mode 100644 index 0000000..e2a02b7 --- /dev/null +++ b/src/views/crm/statistics/rank/components/ProductSalesRank.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/views/crm/statistics/rank/components/ReceivablePriceRank.vue b/src/views/crm/statistics/rank/components/ReceivablePriceRank.vue new file mode 100644 index 0000000..06d7d9f --- /dev/null +++ b/src/views/crm/statistics/rank/components/ReceivablePriceRank.vue @@ -0,0 +1,106 @@ + + + diff --git a/src/views/crm/statistics/rank/index.vue b/src/views/crm/statistics/rank/index.vue new file mode 100644 index 0000000..98340cc --- /dev/null +++ b/src/views/crm/statistics/rank/index.vue @@ -0,0 +1,163 @@ + + + + diff --git a/src/views/erp/finance/account/AccountForm.vue b/src/views/erp/finance/account/AccountForm.vue new file mode 100644 index 0000000..bde4bd2 --- /dev/null +++ b/src/views/erp/finance/account/AccountForm.vue @@ -0,0 +1,124 @@ + + diff --git a/src/views/erp/finance/account/index.vue b/src/views/erp/finance/account/index.vue new file mode 100644 index 0000000..8d85ef3 --- /dev/null +++ b/src/views/erp/finance/account/index.vue @@ -0,0 +1,235 @@ + + + diff --git a/src/views/erp/finance/payment/FinancePaymentForm.vue b/src/views/erp/finance/payment/FinancePaymentForm.vue new file mode 100644 index 0000000..3da2e6e --- /dev/null +++ b/src/views/erp/finance/payment/FinancePaymentForm.vue @@ -0,0 +1,278 @@ + + diff --git a/src/views/erp/finance/payment/components/FinancePaymentItemForm.vue b/src/views/erp/finance/payment/components/FinancePaymentItemForm.vue new file mode 100644 index 0000000..ea0e085 --- /dev/null +++ b/src/views/erp/finance/payment/components/FinancePaymentItemForm.vue @@ -0,0 +1,182 @@ + + diff --git a/src/views/erp/finance/payment/index.vue b/src/views/erp/finance/payment/index.vue new file mode 100644 index 0000000..a449ca5 --- /dev/null +++ b/src/views/erp/finance/payment/index.vue @@ -0,0 +1,394 @@ + + + diff --git a/src/views/erp/finance/receipt/FinanceReceiptForm.vue b/src/views/erp/finance/receipt/FinanceReceiptForm.vue new file mode 100644 index 0000000..96826eb --- /dev/null +++ b/src/views/erp/finance/receipt/FinanceReceiptForm.vue @@ -0,0 +1,278 @@ + + diff --git a/src/views/erp/finance/receipt/components/FinanceReceiptItemForm.vue b/src/views/erp/finance/receipt/components/FinanceReceiptItemForm.vue new file mode 100644 index 0000000..1a48b41 --- /dev/null +++ b/src/views/erp/finance/receipt/components/FinanceReceiptItemForm.vue @@ -0,0 +1,176 @@ + + diff --git a/src/views/erp/finance/receipt/index.vue b/src/views/erp/finance/receipt/index.vue new file mode 100644 index 0000000..b96a33d --- /dev/null +++ b/src/views/erp/finance/receipt/index.vue @@ -0,0 +1,394 @@ + + + diff --git a/src/views/erp/home/components/SummaryCard.vue b/src/views/erp/home/components/SummaryCard.vue new file mode 100644 index 0000000..21a02e2 --- /dev/null +++ b/src/views/erp/home/components/SummaryCard.vue @@ -0,0 +1,21 @@ + + diff --git a/src/views/erp/home/components/TimeSummaryChart.vue b/src/views/erp/home/components/TimeSummaryChart.vue new file mode 100644 index 0000000..127fa87 --- /dev/null +++ b/src/views/erp/home/components/TimeSummaryChart.vue @@ -0,0 +1,86 @@ + + diff --git a/src/views/erp/home/index.vue b/src/views/erp/home/index.vue new file mode 100644 index 0000000..e399f9a --- /dev/null +++ b/src/views/erp/home/index.vue @@ -0,0 +1,93 @@ + + + diff --git a/src/views/erp/product/category/ProductCategoryForm.vue b/src/views/erp/product/category/ProductCategoryForm.vue new file mode 100644 index 0000000..488b31e --- /dev/null +++ b/src/views/erp/product/category/ProductCategoryForm.vue @@ -0,0 +1,145 @@ + + diff --git a/src/views/erp/product/category/index.vue b/src/views/erp/product/category/index.vue new file mode 100644 index 0000000..281835d --- /dev/null +++ b/src/views/erp/product/category/index.vue @@ -0,0 +1,218 @@ + + + diff --git a/src/views/erp/product/product/ProductForm.vue b/src/views/erp/product/product/ProductForm.vue new file mode 100644 index 0000000..75be903 --- /dev/null +++ b/src/views/erp/product/product/ProductForm.vue @@ -0,0 +1,242 @@ + + + diff --git a/src/views/erp/product/product/index.vue b/src/views/erp/product/product/index.vue new file mode 100644 index 0000000..4eeba1e --- /dev/null +++ b/src/views/erp/product/product/index.vue @@ -0,0 +1,224 @@ + + + + diff --git a/src/views/erp/product/unit/ProductUnitForm.vue b/src/views/erp/product/unit/ProductUnitForm.vue new file mode 100644 index 0000000..bced5db --- /dev/null +++ b/src/views/erp/product/unit/ProductUnitForm.vue @@ -0,0 +1,108 @@ + + diff --git a/src/views/erp/product/unit/index.vue b/src/views/erp/product/unit/index.vue new file mode 100644 index 0000000..04259ac --- /dev/null +++ b/src/views/erp/product/unit/index.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/views/erp/purchase/in/PurchaseInForm.vue b/src/views/erp/purchase/in/PurchaseInForm.vue new file mode 100644 index 0000000..c59d7df --- /dev/null +++ b/src/views/erp/purchase/in/PurchaseInForm.vue @@ -0,0 +1,325 @@ + + diff --git a/src/views/erp/purchase/in/components/PurchaseInItemForm.vue b/src/views/erp/purchase/in/components/PurchaseInItemForm.vue new file mode 100644 index 0000000..64377bc --- /dev/null +++ b/src/views/erp/purchase/in/components/PurchaseInItemForm.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue b/src/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue new file mode 100644 index 0000000..afaa644 --- /dev/null +++ b/src/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/views/erp/purchase/in/index.vue b/src/views/erp/purchase/in/index.vue new file mode 100644 index 0000000..b1277d4 --- /dev/null +++ b/src/views/erp/purchase/in/index.vue @@ -0,0 +1,443 @@ + + + diff --git a/src/views/erp/purchase/order/PurchaseOrderForm.vue b/src/views/erp/purchase/order/PurchaseOrderForm.vue new file mode 100644 index 0000000..a7a6eec --- /dev/null +++ b/src/views/erp/purchase/order/PurchaseOrderForm.vue @@ -0,0 +1,269 @@ + + diff --git a/src/views/erp/purchase/order/components/PurchaseOrderInEnableList.vue b/src/views/erp/purchase/order/components/PurchaseOrderInEnableList.vue new file mode 100644 index 0000000..f3df953 --- /dev/null +++ b/src/views/erp/purchase/order/components/PurchaseOrderInEnableList.vue @@ -0,0 +1,205 @@ + + + diff --git a/src/views/erp/purchase/order/components/PurchaseOrderItemForm.vue b/src/views/erp/purchase/order/components/PurchaseOrderItemForm.vue new file mode 100644 index 0000000..70a2433 --- /dev/null +++ b/src/views/erp/purchase/order/components/PurchaseOrderItemForm.vue @@ -0,0 +1,276 @@ + + diff --git a/src/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue b/src/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue new file mode 100644 index 0000000..17e59db --- /dev/null +++ b/src/views/erp/purchase/order/components/PurchaseOrderReturnEnableList.vue @@ -0,0 +1,212 @@ + + + + diff --git a/src/views/erp/purchase/order/index.vue b/src/views/erp/purchase/order/index.vue new file mode 100644 index 0000000..1417761 --- /dev/null +++ b/src/views/erp/purchase/order/index.vue @@ -0,0 +1,407 @@ + + + diff --git a/src/views/erp/purchase/return/PurchaseReturnForm.vue b/src/views/erp/purchase/return/PurchaseReturnForm.vue new file mode 100644 index 0000000..e37fa09 --- /dev/null +++ b/src/views/erp/purchase/return/PurchaseReturnForm.vue @@ -0,0 +1,328 @@ + + diff --git a/src/views/erp/purchase/return/components/PurchaseReturnItemForm.vue b/src/views/erp/purchase/return/components/PurchaseReturnItemForm.vue new file mode 100644 index 0000000..2d3e8c5 --- /dev/null +++ b/src/views/erp/purchase/return/components/PurchaseReturnItemForm.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/erp/purchase/return/components/PurchaseReturnRefundEnableList.vue b/src/views/erp/purchase/return/components/PurchaseReturnRefundEnableList.vue new file mode 100644 index 0000000..a95749e --- /dev/null +++ b/src/views/erp/purchase/return/components/PurchaseReturnRefundEnableList.vue @@ -0,0 +1,200 @@ + + + diff --git a/src/views/erp/purchase/return/index.vue b/src/views/erp/purchase/return/index.vue new file mode 100644 index 0000000..cdf8411 --- /dev/null +++ b/src/views/erp/purchase/return/index.vue @@ -0,0 +1,443 @@ + + + diff --git a/src/views/erp/purchase/supplier/SupplierForm.vue b/src/views/erp/purchase/supplier/SupplierForm.vue new file mode 100644 index 0000000..3225df7 --- /dev/null +++ b/src/views/erp/purchase/supplier/SupplierForm.vue @@ -0,0 +1,210 @@ + + diff --git a/src/views/erp/purchase/supplier/index.vue b/src/views/erp/purchase/supplier/index.vue new file mode 100644 index 0000000..4d3a405 --- /dev/null +++ b/src/views/erp/purchase/supplier/index.vue @@ -0,0 +1,201 @@ + + + diff --git a/src/views/erp/sale/customer/CustomerForm.vue b/src/views/erp/sale/customer/CustomerForm.vue new file mode 100644 index 0000000..ce63cbb --- /dev/null +++ b/src/views/erp/sale/customer/CustomerForm.vue @@ -0,0 +1,210 @@ + + diff --git a/src/views/erp/sale/customer/index.vue b/src/views/erp/sale/customer/index.vue new file mode 100644 index 0000000..c79bbe8 --- /dev/null +++ b/src/views/erp/sale/customer/index.vue @@ -0,0 +1,201 @@ + + + diff --git a/src/views/erp/sale/order/SaleOrderForm.vue b/src/views/erp/sale/order/SaleOrderForm.vue new file mode 100644 index 0000000..30b2b30 --- /dev/null +++ b/src/views/erp/sale/order/SaleOrderForm.vue @@ -0,0 +1,289 @@ + + diff --git a/src/views/erp/sale/order/components/SaleOrderItemForm.vue b/src/views/erp/sale/order/components/SaleOrderItemForm.vue new file mode 100644 index 0000000..3a579d5 --- /dev/null +++ b/src/views/erp/sale/order/components/SaleOrderItemForm.vue @@ -0,0 +1,271 @@ + + diff --git a/src/views/erp/sale/order/components/SaleOrderOutEnableList.vue b/src/views/erp/sale/order/components/SaleOrderOutEnableList.vue new file mode 100644 index 0000000..38dcac4 --- /dev/null +++ b/src/views/erp/sale/order/components/SaleOrderOutEnableList.vue @@ -0,0 +1,206 @@ + + + + diff --git a/src/views/erp/sale/order/components/SaleOrderReturnEnableList.vue b/src/views/erp/sale/order/components/SaleOrderReturnEnableList.vue new file mode 100644 index 0000000..75d925d --- /dev/null +++ b/src/views/erp/sale/order/components/SaleOrderReturnEnableList.vue @@ -0,0 +1,212 @@ + + + + diff --git a/src/views/erp/sale/order/index.vue b/src/views/erp/sale/order/index.vue new file mode 100644 index 0000000..4d151b7 --- /dev/null +++ b/src/views/erp/sale/order/index.vue @@ -0,0 +1,407 @@ + + + diff --git a/src/views/erp/sale/out/SaleOutForm.vue b/src/views/erp/sale/out/SaleOutForm.vue new file mode 100644 index 0000000..7d47713 --- /dev/null +++ b/src/views/erp/sale/out/SaleOutForm.vue @@ -0,0 +1,343 @@ + + diff --git a/src/views/erp/sale/out/components/SaleOutItemForm.vue b/src/views/erp/sale/out/components/SaleOutItemForm.vue new file mode 100644 index 0000000..15cbef0 --- /dev/null +++ b/src/views/erp/sale/out/components/SaleOutItemForm.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/erp/sale/out/components/SaleOutReceiptEnableList.vue b/src/views/erp/sale/out/components/SaleOutReceiptEnableList.vue new file mode 100644 index 0000000..0c4a21d --- /dev/null +++ b/src/views/erp/sale/out/components/SaleOutReceiptEnableList.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/views/erp/sale/out/index.vue b/src/views/erp/sale/out/index.vue new file mode 100644 index 0000000..fdc7f71 --- /dev/null +++ b/src/views/erp/sale/out/index.vue @@ -0,0 +1,438 @@ + + + diff --git a/src/views/erp/sale/return/SaleReturnForm.vue b/src/views/erp/sale/return/SaleReturnForm.vue new file mode 100644 index 0000000..b10403b --- /dev/null +++ b/src/views/erp/sale/return/SaleReturnForm.vue @@ -0,0 +1,341 @@ + + diff --git a/src/views/erp/sale/return/components/SaleReturnItemForm.vue b/src/views/erp/sale/return/components/SaleReturnItemForm.vue new file mode 100644 index 0000000..adb9fd4 --- /dev/null +++ b/src/views/erp/sale/return/components/SaleReturnItemForm.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/erp/sale/return/components/SaleReturnRefundEnableList.vue b/src/views/erp/sale/return/components/SaleReturnRefundEnableList.vue new file mode 100644 index 0000000..dc875e6 --- /dev/null +++ b/src/views/erp/sale/return/components/SaleReturnRefundEnableList.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/views/erp/sale/return/index.vue b/src/views/erp/sale/return/index.vue new file mode 100644 index 0000000..be0b174 --- /dev/null +++ b/src/views/erp/sale/return/index.vue @@ -0,0 +1,443 @@ + + + diff --git a/src/views/erp/stock/check/StockCheckForm.vue b/src/views/erp/stock/check/StockCheckForm.vue new file mode 100644 index 0000000..9e7f673 --- /dev/null +++ b/src/views/erp/stock/check/StockCheckForm.vue @@ -0,0 +1,148 @@ + + diff --git a/src/views/erp/stock/check/components/StockCheckItemForm.vue b/src/views/erp/stock/check/components/StockCheckItemForm.vue new file mode 100644 index 0000000..6036311 --- /dev/null +++ b/src/views/erp/stock/check/components/StockCheckItemForm.vue @@ -0,0 +1,289 @@ + + diff --git a/src/views/erp/stock/check/index.vue b/src/views/erp/stock/check/index.vue new file mode 100644 index 0000000..f661ab7 --- /dev/null +++ b/src/views/erp/stock/check/index.vue @@ -0,0 +1,359 @@ + + + diff --git a/src/views/erp/stock/in/StockInForm.vue b/src/views/erp/stock/in/StockInForm.vue new file mode 100644 index 0000000..f36bbb6 --- /dev/null +++ b/src/views/erp/stock/in/StockInForm.vue @@ -0,0 +1,170 @@ + + diff --git a/src/views/erp/stock/in/components/StockInItemForm.vue b/src/views/erp/stock/in/components/StockInItemForm.vue new file mode 100644 index 0000000..53a2fd2 --- /dev/null +++ b/src/views/erp/stock/in/components/StockInItemForm.vue @@ -0,0 +1,267 @@ + + diff --git a/src/views/erp/stock/in/index.vue b/src/views/erp/stock/in/index.vue new file mode 100644 index 0000000..ca697e9 --- /dev/null +++ b/src/views/erp/stock/in/index.vue @@ -0,0 +1,376 @@ + + + diff --git a/src/views/erp/stock/move/StockMoveForm.vue b/src/views/erp/stock/move/StockMoveForm.vue new file mode 100644 index 0000000..df942c6 --- /dev/null +++ b/src/views/erp/stock/move/StockMoveForm.vue @@ -0,0 +1,148 @@ + + diff --git a/src/views/erp/stock/move/components/StockMoveItemForm.vue b/src/views/erp/stock/move/components/StockMoveItemForm.vue new file mode 100644 index 0000000..8971956 --- /dev/null +++ b/src/views/erp/stock/move/components/StockMoveItemForm.vue @@ -0,0 +1,292 @@ + + diff --git a/src/views/erp/stock/move/index.vue b/src/views/erp/stock/move/index.vue new file mode 100644 index 0000000..76ea653 --- /dev/null +++ b/src/views/erp/stock/move/index.vue @@ -0,0 +1,359 @@ + + + diff --git a/src/views/erp/stock/out/StockOutForm.vue b/src/views/erp/stock/out/StockOutForm.vue new file mode 100644 index 0000000..8ae8d63 --- /dev/null +++ b/src/views/erp/stock/out/StockOutForm.vue @@ -0,0 +1,170 @@ + + diff --git a/src/views/erp/stock/out/components/StockOutItemForm.vue b/src/views/erp/stock/out/components/StockOutItemForm.vue new file mode 100644 index 0000000..b09a569 --- /dev/null +++ b/src/views/erp/stock/out/components/StockOutItemForm.vue @@ -0,0 +1,267 @@ + + diff --git a/src/views/erp/stock/out/index.vue b/src/views/erp/stock/out/index.vue new file mode 100644 index 0000000..555b985 --- /dev/null +++ b/src/views/erp/stock/out/index.vue @@ -0,0 +1,378 @@ + + + diff --git a/src/views/erp/stock/record/index.vue b/src/views/erp/stock/record/index.vue new file mode 100644 index 0000000..35b58ca --- /dev/null +++ b/src/views/erp/stock/record/index.vue @@ -0,0 +1,250 @@ + + + + diff --git a/src/views/erp/stock/stock/index.vue b/src/views/erp/stock/stock/index.vue new file mode 100644 index 0000000..4d80117 --- /dev/null +++ b/src/views/erp/stock/stock/index.vue @@ -0,0 +1,186 @@ + + + + diff --git a/src/views/erp/stock/warehouse/WarehouseForm.vue b/src/views/erp/stock/warehouse/WarehouseForm.vue new file mode 100644 index 0000000..f65cea6 --- /dev/null +++ b/src/views/erp/stock/warehouse/WarehouseForm.vue @@ -0,0 +1,157 @@ + + + diff --git a/src/views/erp/stock/warehouse/index.vue b/src/views/erp/stock/warehouse/index.vue new file mode 100644 index 0000000..40bdebe --- /dev/null +++ b/src/views/erp/stock/warehouse/index.vue @@ -0,0 +1,242 @@ + + + + diff --git a/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue new file mode 100644 index 0000000..314fd26 --- /dev/null +++ b/src/views/infra/apiAccessLog/ApiAccessLogDetail.vue @@ -0,0 +1,79 @@ + + + diff --git a/src/views/infra/apiAccessLog/index.vue b/src/views/infra/apiAccessLog/index.vue new file mode 100644 index 0000000..570f579 --- /dev/null +++ b/src/views/infra/apiAccessLog/index.vue @@ -0,0 +1,226 @@ + + diff --git a/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue new file mode 100644 index 0000000..41153a2 --- /dev/null +++ b/src/views/infra/apiErrorLog/ApiErrorLogDetail.vue @@ -0,0 +1,81 @@ + + diff --git a/src/views/infra/apiErrorLog/index.vue b/src/views/infra/apiErrorLog/index.vue new file mode 100644 index 0000000..ca145a7 --- /dev/null +++ b/src/views/infra/apiErrorLog/index.vue @@ -0,0 +1,252 @@ + + + diff --git a/src/views/infra/build/index.vue b/src/views/infra/build/index.vue new file mode 100644 index 0000000..260b8b7 --- /dev/null +++ b/src/views/infra/build/index.vue @@ -0,0 +1,184 @@ + + + + diff --git a/src/views/infra/codegen/EditTable.vue b/src/views/infra/codegen/EditTable.vue new file mode 100644 index 0000000..f8473e3 --- /dev/null +++ b/src/views/infra/codegen/EditTable.vue @@ -0,0 +1,87 @@ + + diff --git a/src/views/infra/codegen/ImportTable.vue b/src/views/infra/codegen/ImportTable.vue new file mode 100644 index 0000000..6cd4610 --- /dev/null +++ b/src/views/infra/codegen/ImportTable.vue @@ -0,0 +1,151 @@ + + diff --git a/src/views/infra/codegen/PreviewCode.vue b/src/views/infra/codegen/PreviewCode.vue new file mode 100644 index 0000000..b6a307d --- /dev/null +++ b/src/views/infra/codegen/PreviewCode.vue @@ -0,0 +1,222 @@ + + + diff --git a/src/views/infra/codegen/components/BasicInfoForm.vue b/src/views/infra/codegen/components/BasicInfoForm.vue new file mode 100644 index 0000000..1859300 --- /dev/null +++ b/src/views/infra/codegen/components/BasicInfoForm.vue @@ -0,0 +1,87 @@ + + diff --git a/src/views/infra/codegen/components/ColumInfoForm.vue b/src/views/infra/codegen/components/ColumInfoForm.vue new file mode 100644 index 0000000..f526022 --- /dev/null +++ b/src/views/infra/codegen/components/ColumInfoForm.vue @@ -0,0 +1,153 @@ + + diff --git a/src/views/infra/codegen/components/GenerateInfoForm.vue b/src/views/infra/codegen/components/GenerateInfoForm.vue new file mode 100644 index 0000000..aaf176f --- /dev/null +++ b/src/views/infra/codegen/components/GenerateInfoForm.vue @@ -0,0 +1,385 @@ + + diff --git a/src/views/infra/codegen/components/index.ts b/src/views/infra/codegen/components/index.ts new file mode 100644 index 0000000..1634a76 --- /dev/null +++ b/src/views/infra/codegen/components/index.ts @@ -0,0 +1,4 @@ +import BasicInfoForm from './BasicInfoForm.vue' +import ColumInfoForm from './ColumInfoForm.vue' +import GenerateInfoForm from './GenerateInfoForm.vue' +export { BasicInfoForm, ColumInfoForm, GenerateInfoForm } diff --git a/src/views/infra/codegen/index.vue b/src/views/infra/codegen/index.vue new file mode 100644 index 0000000..69c3d12 --- /dev/null +++ b/src/views/infra/codegen/index.vue @@ -0,0 +1,258 @@ + + diff --git a/src/views/infra/config/ConfigForm.vue b/src/views/infra/config/ConfigForm.vue new file mode 100644 index 0000000..4f7333a --- /dev/null +++ b/src/views/infra/config/ConfigForm.vue @@ -0,0 +1,131 @@ + + diff --git a/src/views/infra/config/index.vue b/src/views/infra/config/index.vue new file mode 100644 index 0000000..c7838c2 --- /dev/null +++ b/src/views/infra/config/index.vue @@ -0,0 +1,228 @@ + + diff --git a/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue b/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue new file mode 100644 index 0000000..e2a4eaa --- /dev/null +++ b/src/views/infra/dataSourceConfig/DataSourceConfigForm.vue @@ -0,0 +1,111 @@ + + diff --git a/src/views/infra/dataSourceConfig/index.vue b/src/views/infra/dataSourceConfig/index.vue new file mode 100644 index 0000000..92bd301 --- /dev/null +++ b/src/views/infra/dataSourceConfig/index.vue @@ -0,0 +1,106 @@ + + diff --git a/src/views/infra/demo/demo01/Demo01ContactForm.vue b/src/views/infra/demo/demo01/Demo01ContactForm.vue new file mode 100644 index 0000000..f317fe7 --- /dev/null +++ b/src/views/infra/demo/demo01/Demo01ContactForm.vue @@ -0,0 +1,126 @@ + + diff --git a/src/views/infra/demo/demo01/index.vue b/src/views/infra/demo/demo01/index.vue new file mode 100644 index 0000000..e111ab6 --- /dev/null +++ b/src/views/infra/demo/demo01/index.vue @@ -0,0 +1,214 @@ + + + diff --git a/src/views/infra/demo/demo02/Demo02CategoryForm.vue b/src/views/infra/demo/demo02/Demo02CategoryForm.vue new file mode 100644 index 0000000..f4c5f8e --- /dev/null +++ b/src/views/infra/demo/demo02/Demo02CategoryForm.vue @@ -0,0 +1,114 @@ + + diff --git a/src/views/infra/demo/demo02/index.vue b/src/views/infra/demo/demo02/index.vue new file mode 100644 index 0000000..9faa8c9 --- /dev/null +++ b/src/views/infra/demo/demo02/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/views/infra/demo/demo03/erp/Demo03StudentForm.vue b/src/views/infra/demo/demo03/erp/Demo03StudentForm.vue new file mode 100644 index 0000000..b73f423 --- /dev/null +++ b/src/views/infra/demo/demo03/erp/Demo03StudentForm.vue @@ -0,0 +1,121 @@ + + diff --git a/src/views/infra/demo/demo03/erp/components/Demo03CourseForm.vue b/src/views/infra/demo/demo03/erp/components/Demo03CourseForm.vue new file mode 100644 index 0000000..9d3888d --- /dev/null +++ b/src/views/infra/demo/demo03/erp/components/Demo03CourseForm.vue @@ -0,0 +1,99 @@ + + diff --git a/src/views/infra/demo/demo03/erp/components/Demo03CourseList.vue b/src/views/infra/demo/demo03/erp/components/Demo03CourseList.vue new file mode 100644 index 0000000..3dce77e --- /dev/null +++ b/src/views/infra/demo/demo03/erp/components/Demo03CourseList.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/views/infra/demo/demo03/erp/components/Demo03GradeForm.vue b/src/views/infra/demo/demo03/erp/components/Demo03GradeForm.vue new file mode 100644 index 0000000..5687294 --- /dev/null +++ b/src/views/infra/demo/demo03/erp/components/Demo03GradeForm.vue @@ -0,0 +1,99 @@ + + diff --git a/src/views/infra/demo/demo03/erp/components/Demo03GradeList.vue b/src/views/infra/demo/demo03/erp/components/Demo03GradeList.vue new file mode 100644 index 0000000..635f321 --- /dev/null +++ b/src/views/infra/demo/demo03/erp/components/Demo03GradeList.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/views/infra/demo/demo03/erp/index.vue b/src/views/infra/demo/demo03/erp/index.vue new file mode 100644 index 0000000..e0f1cf4 --- /dev/null +++ b/src/views/infra/demo/demo03/erp/index.vue @@ -0,0 +1,248 @@ + + + diff --git a/src/views/infra/demo/demo03/inner/Demo03StudentForm.vue b/src/views/infra/demo/demo03/inner/Demo03StudentForm.vue new file mode 100644 index 0000000..8621593 --- /dev/null +++ b/src/views/infra/demo/demo03/inner/Demo03StudentForm.vue @@ -0,0 +1,153 @@ + + diff --git a/src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue b/src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue new file mode 100644 index 0000000..77da45f --- /dev/null +++ b/src/views/infra/demo/demo03/inner/components/Demo03CourseForm.vue @@ -0,0 +1,100 @@ + + diff --git a/src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue b/src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue new file mode 100644 index 0000000..965b473 --- /dev/null +++ b/src/views/infra/demo/demo03/inner/components/Demo03CourseList.vue @@ -0,0 +1,51 @@ + + diff --git a/src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue b/src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue new file mode 100644 index 0000000..e14bac4 --- /dev/null +++ b/src/views/infra/demo/demo03/inner/components/Demo03GradeForm.vue @@ -0,0 +1,72 @@ + + diff --git a/src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue b/src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue new file mode 100644 index 0000000..e631384 --- /dev/null +++ b/src/views/infra/demo/demo03/inner/components/Demo03GradeList.vue @@ -0,0 +1,55 @@ + + diff --git a/src/views/infra/demo/demo03/inner/index.vue b/src/views/infra/demo/demo03/inner/index.vue new file mode 100644 index 0000000..9b32460 --- /dev/null +++ b/src/views/infra/demo/demo03/inner/index.vue @@ -0,0 +1,229 @@ + + + diff --git a/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue b/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue new file mode 100644 index 0000000..42613c4 --- /dev/null +++ b/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue @@ -0,0 +1,153 @@ + + diff --git a/src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue b/src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue new file mode 100644 index 0000000..f439c3f --- /dev/null +++ b/src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue @@ -0,0 +1,100 @@ + + diff --git a/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue b/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue new file mode 100644 index 0000000..c711954 --- /dev/null +++ b/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue @@ -0,0 +1,72 @@ + + diff --git a/src/views/infra/demo/demo03/normal/index.vue b/src/views/infra/demo/demo03/normal/index.vue new file mode 100644 index 0000000..8a5dc1a --- /dev/null +++ b/src/views/infra/demo/demo03/normal/index.vue @@ -0,0 +1,214 @@ + + + diff --git a/src/views/infra/druid/index.vue b/src/views/infra/druid/index.vue new file mode 100644 index 0000000..2ac99d2 --- /dev/null +++ b/src/views/infra/druid/index.vue @@ -0,0 +1,28 @@ +