From ce9f7b73e4252f58ec9b6ee85f736bca3f1dc68d Mon Sep 17 00:00:00 2001 From: Your Name <123456> Date: 星期一, 27 六月 2022 19:51:37 +0800 Subject: [PATCH] 'lct' --- src/layout/component/aside.vue | 163 src/stores/keepAliveNames.ts | 37 src/layout/main/columns.vue | 41 src/theme/media/login.scss | 63 src/components/auth/auth.vue | 30 source.d.ts | 6 src/utils/toolsValidate.ts | 370 src/layout/index.vue | 54 src/utils/authFunction.ts | 38 src/views/system/department/index.vue | 121 src/layout/routerView/parent.vue | 88 src/theme/media/chart.scss | 94 src/theme/media/error.scss | 45 src/components/cropper/index.vue | 149 src/router/route.ts | 77 src/utils/authDirective.ts | 40 src/api/department/index.ts | 26 src/views/login/component/account.vue | 196 src/layout/lockScreen/index.vue | 372 src/layout/navBars/breadcrumb/user.vue | 298 src/utils/customDirective.ts | 178 src/i18n/pages/formI18n/zh-tw.ts | 13 src/theme/element.scss | 282 src/theme/waves.scss | 101 src/views/error/404.vue | 115 src/views/system/role/component/editRole.vue | 242 src/theme/iconSelector.scss | 70 src/layout/navBars/breadcrumb/search.vue | 138 src/views/system/user/component/editUser.vue | 202 .env.development | 7 src/i18n/pages/formI18n/zh-cn.ts | 13 src/views/home/index.vue | 191 src/layout/navBars/index.vue | 40 src/stores/interface/index.ts | 92 yarn.lock | 2236 +++++ src/components/editor/toolbar.ts | 60 src/theme/media/home.scss | 23 src/views/system/menu/component/menuDialog.vue | 271 src/i18n/lang/en.ts | 180 src/views/system/role/index.vue | 167 package-lock.json | 7716 ++++++++++++++++++ src/theme/dark.scss | 236 src/theme/media/dialog.scss | 12 src/views/login/index.vue | 190 src/stores/routesList.ts | 28 src/i18n/pages/login/zh-cn.ts | 28 src/views/system/menu/index.vue | 128 vite.config.ts | 79 src/views/error/401.vue | 117 src/layout/component/main.vue | 101 src/i18n/pages/formI18n/en.ts | 13 plugins.d.ts | 4 src/layout/routerView/iframes.vue | 66 src/components/editor/index.vue | 115 src/utils/arrayOperation.ts | 66 src/layout/navMenu/vertical.vue | 101 src/theme/media/layout.scss | 55 src/theme/mixins/index.scss | 56 src/theme/media/personal.scss | 16 src/theme/media/form.scss | 16 src/router/backEnd.ts | 110 src/theme/media/media.scss | 13 src/utils/storage.ts | 59 src/i18n/index.ts | 67 src/main.ts | 22 src/components/auth/auths.vue | 36 src/layout/navBars/tagsView/tagsView.vue | 734 + src/layout/footer/index.vue | 47 src/theme/common/transition.scss | 94 src/utils/commonFunction.ts | 65 src/utils/theme.ts | 59 src/views/system/role/component/addRole.vue | 240 src/api/menu/index.ts | 39 .eslintignore | 18 src/views/system/department/component/editDept.vue | 179 src/layout/navMenu/subItem.vue | 48 src/i18n/pages/login/zh-tw.ts | 28 src/layout/navBars/breadcrumb/setings.vue | 816 ++ src/components/auth/authAll.vue | 31 src/theme/media/cityLinkage.scss | 10 shim.d.ts | 13 src/layout/main/transverse.vue | 17 src/api/role/index.ts | 12 src/theme/index.scss | 8 src/router/frontEnd.ts | 97 src/stores/themeConfig.ts | 146 src/assets/login-icon-two.svg | 1 src/theme/media/index.scss | 15 src/components/iconSelector/index.vue | 252 src/layout/navBars/breadcrumb/index.vue | 119 .eslintrc.js | 63 src/theme/loading.scss | 51 src/utils/wartermark.ts | 47 src/theme/media/scrollbar.scss | 56 index.html | 31 src/views/system/dic/component/editDic.vue | 162 src/views/system/dic/index.vue | 159 public/favicon.ico | 0 src/router/index.ts | 108 src/api/login/index.ts | 25 src/assets/logo-mini.svg | 9 src/theme/media/pagination.scss | 15 LICENSE | 21 src/i18n/pages/login/en.ts | 29 src/utils/formatTime.ts | 137 src/layout/main/defaults.vue | 47 src/utils/request.ts | 72 src/views/system/department/component/deptDialog.vue | 161 src/theme/other.scss | 36 CHANGELOG.md | 356 src/stores/tagsViewRoutes.ts | 24 src/layout/component/header.vue | 34 src/layout/logo/index.vue | 85 src/views/system/user/component/addUser.vue | 200 src/components/svgIcon/index.vue | 73 tsconfig.json | 72 src/layout/navBars/breadcrumb/userNews.vue | 115 src/theme/media/date.scss | 25 .env.production | 5 src/layout/navBars/breadcrumb/breadcrumb.vue | 163 src/layout/navMenu/horizontal.vue | 157 src/theme/media/tagsView.scss | 11 src/utils/getStyleSheets.ts | 101 src/i18n/lang/zh-tw.ts | 180 src/utils/loading.ts | 42 src/utils/directive.ts | 18 src/layout/main/classic.vue | 35 src/layout/routerView/link.vue | 61 src/i18n/lang/zh-cn.ts | 180 src/stores/userInfo.ts | 65 src/layout/component/columnsAside.vue | 292 src/layout/navBars/tagsView/contextmenu.vue | 138 src/utils/setIconfont.ts | 48 src/stores/index.ts | 8 src/views/system/dic/component/addDic.vue | 129 .env | 8 src/components/noticeBar/index.vue | 195 src/stores/requestOldRoutes.ts | 17 src/theme/app.scss | 281 src/views/system/user/index.vue | 177 src/utils/other.ts | 200 package.json | 81 src/App.vue | 100 src/layout/navBars/breadcrumb/closeFull.vue | 61 .prettierrc.js | 39 145 files changed, 24,472 insertions(+), 0 deletions(-) diff --git a/.env b/.env new file mode 100644 index 0000000..dacb1a5 --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +# port 端口号 +VITE_PORT = 8888 + +# open 运行 npm run dev 时自动打开浏览器 +VITE_OPEN = false + +# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可 +VITE_PUBLIC_PATH = /vue-next-admin-preview/ \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..0c99294 --- /dev/null +++ b/.env.development @@ -0,0 +1,7 @@ +# 本地环境 +ENV = 'development' + +# 本地环境接口地址 +VITE_API_URL = 'http://192.168.0.35:8008' + +# VITE_API_URL = 'http://192.168.0.8:8008' diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..0336f50 --- /dev/null +++ b/.env.production @@ -0,0 +1,5 @@ +# 线上环境 +ENV = 'production' + +# 线上环境接口地址 +VITE_API_URL = 'https://lyt-top.gitee.io/vue-next-admin-preview/' \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..cfc877d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,18 @@ + +*.sh +node_modules +lib +*.md +*.scss +*.woff +*.ttf +.vscode +.idea +dist +mock +public +bin +build +config +index.html +src/assets \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..732bfbe --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,63 @@ +module.exports = { + root: true, + env: { + browser: true, + es2021: true, + node: true, + }, + parser: 'vue-eslint-parser', + parserOptions: { + ecmaVersion: 12, + parser: '@typescript-eslint/parser', + sourceType: 'module', + }, + extends: ['plugin:vue/vue3-essential', 'plugin:vue/essential', 'eslint:recommended'], + plugins: ['vue', '@typescript-eslint'], + rules: { + // http://eslint.cn/docs/rules/ + // https://eslint.vuejs.org/rules/ + '@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', + '@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', + 'vue/custom-event-name-casing': '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/html-self-closing': 'off', + 'vue/no-multiple-template-root': 'off', + 'vue/require-default-prop': 'off', + 'vue/no-v-model-argument': 'off', + 'vue/no-arrow-functions-in-watch': 'off', + 'vue/no-template-key': 'off', + 'vue/no-v-html': 'off', + 'vue/comment-directive': 'off', + 'vue/no-parsing-error': 'off', + 'vue/no-deprecated-v-on-native-modifier': 'off', + 'vue/multi-word-component-names': 'off', + 'no-useless-escape': 'off', + 'no-sparse-arrays': 'off', + 'no-prototype-builtins': 'off', + 'no-constant-condition': 'off', + 'no-use-before-define': 'off', + 'no-restricted-globals': 'off', + 'no-restricted-syntax': 'off', + 'generator-star-spacing': 'off', + 'no-unreachable': 'off', + 'no-multiple-template-root': 'off', + 'no-unused-vars': 'error', + 'no-v-model-argument': 'off', + 'no-case-declarations': 'off', + 'no-console': 'error', + }, +}; diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..cff490a --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,39 @@ +module.exports = { + // 一行最多多少个字符 + printWidth: 150, + // 指定每个缩进级别的空格数 + tabWidth: 2, + // 使用制表符而不是空格缩进行 + useTabs: true, + // 在语句末尾打印分号 + semi: true, + // 使用单引号而不是双引号 + singleQuote: true, + // 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>" + quoteProps: 'as-needed', + // 在JSX中使用单引号而不是双引号 + jsxSingleQuote: false, + // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none + trailingComma: 'es5', + // 在对象文字中的括号之间打印空格 + bracketSpacing: true, + // jsx 标签的反尖括号需要换行 + jsxBracketSameLine: false, + // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x + arrowParens: 'always', + // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码 + rangeStart: 0, + rangeEnd: Infinity, + // 指定要使用的解析器,不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 always\never\preserve + proseWrap: 'preserve', + // 指定HTML文件的全局空格敏感度 css\strict\ignore + htmlWhitespaceSensitivity: 'css', + // Vue文件脚本和样式标签缩进 + vueIndentScriptAndStyle: false, + // 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>" + endOfLine: 'lf', +}; diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..34eedbe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,356 @@ +# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin 更新日志</a> + +🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支) + +## 2.1.1 + +`2022.05.27` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 深色模式下,`<el-button text></el-button>` 时,`:active` 样式 +- 🎯 优化 [页面缓存在刷新之后失效 #I58U75](https://gitee.com/lyt-top/vue-next-admin/issues/I58U75)),感谢[@ls0428](https://gitee.com/ls0428) +- 🎯 优化 [SvgIcon 对下载的 Svg 图像设置颜色无效 #I59ND0](https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0)),感谢[@elus_z](https://gitee.com/elus_z) +- 🎯 优化 `/src/utils/toolsValidate.ts` 工具类 +- 🐞 修复 [布局切换,TagsView 显示的 tab 会多一个出来 #I58WGM](https://gitee.com/lyt-top/vue-next-admin/issues/I58WGM),感谢[@lg_boy](https://gitee.com/lg_boy) +- 🐞 修复 [如果设置顶部面包屑导航开启图标 isBreadcrumbIcon=true 后,样式有点问题 如果不开启就是正常的 #I58VB8](https://gitee.com/lyt-top/vue-next-admin/issues/I58VB8) +- 🐞 修复 地址栏路由地址输入错误时,返回首页后,再次输入路由地址错误时,不跳转 404 问题 +- 🐞 修复 [2.1.0 版本的图标选择组件多次点击后功能失效 #I590TH](https://gitee.com/lyt-top/vue-next-admin/issues/I590TH),感谢[@quber](https://gitee.com/quber) + +## 2.1.0 + +`2022.04.18` + +⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。因为 `vuex` 替换成 `pinia` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 部分界面图片不显示问题(更换 gitee 在线图片地址源) +- 🎯 优化 各界面方法引入与逻辑之间添加一行空行,方便区分内容 +- 🎯 优化 图标选择器 [#I4YAHB](https://gitee.com/lyt-top/vue-next-admin/issues/I4YAHB),感谢[@真有你的](https://gitee.com/sunliusen) +- 🎯 优化 图标选择器 icon type 类型为 all 时,类型 ali、ele、awe 回显问题 +- 🎯 优化 去掉开发环境 i18n 控制台警告,页面代码:[i18n/index.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/i18n/index.ts) +- 🎯 优化 `NextLoading.start()` 方法,防止第一次进入界面时出现短暂空白 +- 🎯 优化 地址栏有参数退出登录,再次登录不跳之前界面问题 `src/layout/navBars/breadcrumb/user.vue` +- 🎯 优化 `SvgIcon` 组件,防止 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题,工作流不可连线、全屏时关闭按钮消失问题 +- 🎯 优化 [如果 url 中有中文等特殊字符,第一次切换该 tab 时 keep-alive 失效#I55JS7](https://gitee.com/lyt-top/vue-next-admin/issues/I55JS7),感谢[yuyong1566](https://gitee.com/yuyong1566) +- 🎯 优化 [wangEditor](https://www.wangeditor.com/) 更新到 v5,[vue3 版本线上示例中 wangeditor 富文本编辑器 demo 实例,无法换行#I5565B](https://gitee.com/lyt-top/vue-next-admin/issues/I5565B),感谢@[jenchih](https://gitee.com/jenchih) +- 🎯 优化 [在关闭 tagview 时,高度刷新时会会变化,出现滚动条](https://gitee.com/lyt-top/vue-next-admin/issues/I55FHM),感谢[张松](https://gitee.com/zs310071113) +- 🎯 优化 [路由参数](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)演示 +- 🎉 新增 [vuex](https://vuex.vuejs.org/) 替换成 [pinia](https://pinia.vuejs.org/getting-started.html) +- 🎉 新增 tagsView 支持自定义 tagsView 名称(文章详情时有用),前往体验:[路由参数/普通路由](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)。新增 tagsView 支持自定义名称国际化,感谢[@q7but](https://gitee.com/q7but)、[!22 add 添加自定义 tagVIewName 拓展,支持国际化](https://gitee.com/lyt-top/vue-next-admin/pulls/22/files)、感谢[@tony_tong_xin](https://gitee.com/tony_tong_xin) +- 🐞 修复 适配 `"element-plus": "^2.1.9",2.2.0` 版本 +- 🐞 修复 [导航栏横向布局后,一级菜单显示问题#I4Z3M3](https://gitee.com/lyt-top/vue-next-admin/issues/I4Z3M3) +- 🐞 修复 横向布局三级及以上导航菜单高亮、导航高度不统一问题 +- 🐞 修复 分栏模式下,选中的菜单是 primary 样式,鼠标移入字也变成 primary 色了,感谢群友@孤夜-流殇 +- 🐞 修复 [vuex 里面改了颜色 但是不生效 #I4WFMA](https://gitee.com/lyt-top/vue-next-admin/issues/I4WFMA) +- 🐞 修复 全局主题 primary 清空颜色后报错,[#I4X0LG](https://gitee.com/lyt-top/vue-next-admin/issues/I4X0LG),感谢[面向 BUG 编程](https://gitee.com/fhtfy) +- 🐞 修复 [.eslintrc.js 文件 rules 标签名错误 #I53IPK](https://gitee.com/lyt-top/vue-next-admin/issues/I53IPK),感谢[yuyong1566](https://gitee.com/yuyong1566) +- 🐞 修复 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题 +- 🐞 修复 `router.push` 路径找不到时报错问题,`404、401 界面` 已移入到 `main` 主布局里(之前全屏) +- 🐞 修复 [全局修改组件大小失效了](https://gitee.com/lyt-top/vue-next-admin/issues/I551RP),感谢[lg_boy](https://gitee.com/lg_boy) +- 🐞 修复 [修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效,问题解决#I567R1](https://gitee.com/lyt-top/vue-next-admin/issues/I567R1),感谢[@lanbao123](https://gitee.com/lanbao123) +- 🐞 修复 [标记为需要缓存的 tab 页后,再次从左侧菜单打开,还是显示被缓存的页面内容#I4UY3G](https://gitee.com/lyt-top/vue-next-admin/issues/I4UY3G),感谢@axcc1234、特别感谢群友@华仔 +- 🌈 重构 路由(`/src/router/index.ts`)解决 No match found for location with path "xxx"(前端控制,后端控制未解决) 问题 + +## 2.0.2 + +`2022.03.04` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 Alert 提示添加边框 +- 🎯 优化 功能 / 数字滚动 演示界面 +- 🐞 修复 全局主题按钮颜色 :active 问题 +- 🐞 修复 Dropdown 下拉菜单样式问题 +- 🐞 修复 SvgIcon 图标组件动态切换时报警告问题,[SvgIcon 改变 name 时可能导致图像不显示](https://gitee.com/lyt-top/vue-next-admin/issues/I4VGE0),感谢@axcc1234 + +## 2.0.1 + +`2022.02.25` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 svgIcon 图标组件 +- 🎯 优化 vite.config.ts 打包,感谢群友@YourObjec +- 🐞 修复 tagViews 开启图标不显示问题(风格 5),感谢群友@坏人 +- 🐞 修复 [Element Plus 1.2.0-beta.6 以后的版本 el-table 在移动端无法左右滑动](https://gitee.com/lyt-top/vue-next-admin/issues/I4UPTP),感谢@YGDada + +## 2.0.0 + +`2022.02.21` + +⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。演示界面建议直接覆盖文件。如需使用之前版本,请前往[gitee 发行版](https://gitee.com/lyt-top/vue-next-admin/releases) 进行对应版本下载。基础版会基于 `master` 分支进行修改 + +- 🌟 更新 依赖更新最新版本 +- 🌟 更新 登录页、首页 +- 💔 移除 vue-web-screen-shot +- 💔 移除 城市多级联动,完整 json 数据请去 [vue-next-admin-images/menu](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 仓库查看 +- 💔 移除 功能/echartsTree 树图 +- 💔 移除 其它设置/Tagsview 风格 2、Tagsview 风格 3 +- 💔 移除 功能/验证器 +- 🚧 调整 src/api 编写方式 +- 🚧 调整 自定义封装公用组件演示,更好的维护 +- 🎉 新增 Volar 支持,vs code 配置参考 [Vue Language Features (Volar)](https://lyt-top.gitee.io/vue-next-admin-doc-preview/home/vscode/) +- 🎉 新增 `SvgIcon` 支持本地 svg 图标使用 +- 🎉 新增 表单表格验证演示 +- 🎯 优化 全局主题(移除 success、info、warning、danger) +- 🎯 优化 工作流(开源) +- 🎯 优化 element plus svg 图标,`elementXXX` 改成 `ele-XXX` +- 🌈 重构 深色模式 +- 🌹 合并 [处理 parent 的 h100 由于外层有 min-height 导致失效的问题](https://gitee.com/lyt-top/vue-next-admin/pulls/20),感谢@MaxNull、@21030442-mao +- 🐞 修复 element plus 升级 `^1.3.0-beta.5` 后 组件 size 大小问题(大改:涉及布局、演示界面) +- 🐞 修复 vs code 使用 Vue Language Features (Volar) 插件 代码报红问题(可以把公用的 ts 类型定义封装起来公用) + +## 1.2.2 + +`2021.12.21` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 iframes 滚动条问题 +- 🎯 优化 部署后每次都要强制刷新清浏览器缓存问题 +- 🎉 新增 工具类百分比验证演示 +- 🐞 修复 [tag-view 标签右键会超出浏览器 #I4KN78](https://gitee.com/lyt-top/vue-next-admin/issues/I4KN78) + +## 1.2.1 + +`2021.12.12` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 cropper 裁剪时卡顿问题 [#I4M2VQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4M2VQ) +- 🎯 优化 Wangeditor 富文本编辑器的问题 [#I4LPC1](https://gitee.com/lyt-top/vue-next-admin/issues/I4LPC1)、[#I4LM7I](https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I) +- 🐞 修复 浏览器标题问题 +- 🐞 修复 element plus svg 图标引入 +- 🐞 修复 工作流不可以拖线连接问题 + +## 1.2.0 + +`2021.11.28` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 深色模式 +- 🎯 优化 `/@/utils` 文件夹,合并删除单一内容 +- 🎯 优化 系统设置:菜单管理(新增、修改)、角色管理(新增菜单权限)、用户管理、部门管理、字典管理 +- 🎯 优化 登录界面逻辑、权限管理逻辑 +- 🎯 优化 同步 [vue-next-admin-images](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 后端控制菜单模拟数据 +- 🎉 新增 适配 Font Icon 向 SVG Icon 迁移(改动大,"element-plus": "^1.2.0-beta.4" 谨慎更新) +- 🐞 修复 热更新问题,感谢@甜蜜蜜 +- 🐞 修复 页面/element 字体图标演示 +- 🐞 修复 功能/图标选择器演示,新增高级功能 [issues #I4GJXQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4GJXQ) + +## 1.1.2 + +`2021.10.17` + +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 开启全屏时,刷新界面被还原成未全屏的状态 +- 🎯 优化 tagsView 右键菜单关闭逻辑 +- 🎯 优化 wangeditor 富文本编辑器(增加双向绑定) +- 🎉 新增 工作流(暂不开源) +- 🎉 新增 基础版 ts(不带国际化),切换 `vue-next-admin-template` 分支 + +## 1.1.1 + +`2021.09.25` + +- 🌟 更新 依赖更新最新版本(`"element-plus": "^1.1.0-beta.13"` 版本运行错误,`^1.1.0-beta.16`修复横向菜单卡死问题) +- 🐞 修复 Dialog 弹窗位置错误、Drawer 抽屉内边距、el-menu 菜单收起时背景色问题 +- 🎯 优化 锁屏界面自动锁屏(s/秒)必须设置至少 1 秒 +- 🎉 新增 分栏布局,鼠标移入当前项时,显示当前项菜单内容 +- 🎉 新增 工作流(未完成) + +## 1.1.0 + +`2021.09.10` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 小屏模式下登录页二维码遮挡标题问题 +- 🎉 新增 图片验证器 +- 🎉 新增 动态复杂表单 +- 🎉 新增 工作流(未完成) +- 🎉 新增 深色主题(伪深色,样式变动大,谨慎更新) + +## 1.0.18 + +`2021.08.29` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 权限组件去掉顶级 div(`/src/components/auth`) +- 🎉 新增 布局配置添加恢复默认按钮 +- 🐞 修复 升级 <a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">element plus 1.1.0-beta.7</a>后项目无法启动、el-menu 菜单 +- 🐞 修复 表格固定列时的层级、设置了相对定位时,遮挡左侧导航菜单问题 + +## 1.0.17 + +`2021.08.22` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 去除设置布局切换,重置主题样式(initSetLayoutChange),切换布局需手动设置样式,设置的样式自动同步各布局 +- 🎯 优化 Dropdown 下拉菜单用户账号靠边时换行问题 +- 🎯 优化 左侧导航菜单,共用菜单树,防止 `布局配置` 设置 `菜单 / 顶栏` 时,样式丢失等问题 +- 🐞 修复 固定 header 后没有回到顶部的 bug,拉取项目后运行不起来的 bug。<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/14" target="_blank">!14</a>,感谢<a href="https://gitee.com/wjs0509" target="_blank">@wjs0509</a> +- 🐞 修复 tagView 右键全屏后,浏览器窗口大小发生任何变化都会导致左边菜单显示出来,并且可点击打开对应页面。<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I46E6T" target="_blank">I46E6T</a> +- 🐞 修复 默认设置 `菜单 / 顶栏` 样式不生效问题(/@/src/store/modules/themeConfig.ts) + +## 1.0.16 + +`2021.08.14` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 菜单高亮(详情且详情设置了 meta.isHide 时,顶级菜单高亮),感谢群友@YourObject +- 🎯 优化 详情路径写法:如父级(/pages/filtering),那么详情为(/pages/filtering/details?id=1)。这样写可实现(详情时,父级菜单高亮),否则写成(/pages/filteringDetails?id=1)顶级菜单将不会高亮。可参考:`页面/过滤筛选组件`,点击当前图片进行测试 +- 🎯 优化 tagsView 右键菜单全屏时,打开的界面高度问题 +- 🎯 优化 图表批量 resize 问题 +- 🐞 修复 菜单收起时(设置全局主题:primary 且有二级菜单时),文字高亮颜色不对 +- 🐞 修复 国际化 <a href="https://gitee.com/lyt-top/vue-next-admin/issues/I43NPE" target="_blank">#I43NPE</a>。可参考:`页面/过滤筛选组件`,点击顶部语言切换,进行底部分页国际化查看 + +## 1.0.15 + +`2021.08.06` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 tagsView 右键菜单点击时的字段名(id 已修改成 contextMenuClickId)与路由中返回的 id 名冲突问题,感谢群友@伯牙已遇钟子期 +- 🎉 新增 多个 form 表单验证界面演示 + +## 1.0.14 + +`2021.07.29` + +- 🌟 更新 依赖更新最新版本(vue、vuex、vue-router),出现问题,请手动降级。版本查看:<a href="https://www.npmjs.com/" target="_blank">vnpm</a> +- 🎯 优化 数据可视化图表演示加载卡顿问题、优化有图表的演示界面 +- 🎯 优化 路由参数演示界面 +- 🎯 优化 tagsView 操作演示界面,由于存在相同路由多标签,必须要传全部参数值(query 或者 params) +- 🎉 新增 开启 TagsView 共用,开启时:(多个路由菜单共用一个详情组件(参数为后点击的覆盖前面点击的),tagsView 中只会出现一个(不支持同时出现多个 tagsView 标签))。关闭时:(多个路由菜单共用一个详情组件,参数不同,会同时出现多个 tagsView 标签) +- 🐞 修复 tagsView 共用(单标签)时,右键菜单功能点击,参数不对的问题(第 2n+个参数未覆盖第一个参数值) +- 🐞 修复 多 tagsView 标签(参数不同)、单个 tagsView 标签公用(参数不同)所带来的刷新功能、横向自动滚动等问题 +- 🐞 修复 处理全屏若干问题,<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/12" target="_blank">pr!12</a>,感谢群友@另一个前端 + +## 1.0.13 + +`2021.07.25` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 数据可视化演示界面(/visualizingDemo1、/visualizingDemo2) +- 🎉 新增 登录页扫码登录 + +## 1.0.12 + +`2021.07.16` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 数据可视化演示空界面(待完善) +- 🎯 优化 tagsView 动态路由(xxx/:id/:name)时的右键菜单刷新、关闭其它时参数丢失问题(2021.07.15 优化) +- 🐞 修复 路由带参数时,复制路径到登录页,跳转后参数消失的问题 +- 🐞 修复 设置多个外链,点击后,页面内容停留在上一个内容(内容未改变)、国际化处理、打开新窗口 sessionStorage 共享等 + +## 1.0.11 + +`2021.07.14` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 路由参数、图片懒加载界面演示 +- ⚠️ 警告 Form 表单 `binding value must be a string or number`,解决:加上 `label-position="top"` 不报警告(等待官方修复) +- 🎯 优化 锁屏界面动画效果、首页图表显示 +- 🎯 优化 tagsView 右键菜单 `关闭` 功能逻辑 +- 🐞 修复 开启 TagsView 拖拽报错及小于 `1000px` 时自动设置禁止拖拽(<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI" target="_blank">#I3ZRRI</a>) +- 🐞 修复 `iframe 内嵌、外链` 高度问题,使用 computed 进行计算 +- 🐞 修复 默认布局开启 `侧边栏 Logo` 与关闭 `菜单水平折叠`,切换到横向布局时,菜单看不见的问题 +- 🐞 修复 切换不同布局时,再去开启 `经典布局分割菜单` 功能不生效问题 +- 🐞 修复 浏览器窗口标题中/英文切换不实时生效的问题 +- 🐞 修复 切换布局时,某些功能不可以使用。部分界面不需要取消事件监听(proxy.mittBus.off('xxx')) +- 🐞 修复 动态路由带参数,router-link 跳转问题(<a href="hhttps://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G" target="_blank">#I3YX6G</a>) +- 🐞 修复 横向菜单有二级菜单时,点击子级菜单不高亮问题 +- 🐞 修复 功能 tagsView 操作演示不生效 + +## 1.0.10 + +`2021.07.07` + +- 🌟 更新 依赖更新最新版本(字体图标无问题) +- 🎯 优化 内嵌 iframe、外链,解决 tagsView 刷新问题 + +## 1.0.9 + +`2021.07.02` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 图标选择器设置宽度、v-model 等问题 +- 🎯 优化 滚动通知栏在手机上的体验 +- 🎯 优化 系统管理/新增菜单(编辑菜单),使用 `图标选择器` 进行模拟 +- 🎯 优化 字体图标(自动载入) 逻辑 +- 🐞 修复 screenfull 全屏时,按键盘 esc 键图标不改变问题,感谢群友@伯牙已遇钟子期 + +## 1.0.8 + +`2021.06.29` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 表单中英文切换演示 +- 🎯 优化 登录页查看密码 icon 图标 +- 🎯 优化 图标选择器 +- 🎯 优化 拖动指令 +- 🐞 修复 form 表单在页面小于 576px 时的排版问题 + +## 1.0.7 + +`2021.06.24` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 拖动指令及其演示界面 +- 🎯 优化 锁屏界面,解锁提示 +- 🎯 优化 登录页在手机上显示的效果 + +## 1.0.6 + +`2021.06.23` + +- 🎯 优化 去掉内嵌 iframe 内边距(padding) +- 🎯 优化 城市多级联动组件 +- 🎯 优化 Tree 树形控件改成表格组件 +- 🐞 修复 Cascader 级联选择器高度问题 + +## 1.0.5 + +`2021.06.22` + +- 🌟 更新 vite 降级为@vite2.3.7,降级方法 `cnpm install vite@2.3.7`,防止 element plus 字体图标消失 +- 🐞 修复 开启后端控制路由(isRequestRoutes = true)时,内嵌 iframe、外链不可使用的问题 + +## 1.0.4 + +`2021.06.19` + +- 🌟 更新 依赖更新最新版本("vite": "^2.3.7")热更新无问题 +- 🎉 新增 深克隆工具,方便开发,感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/6" target="_blank">#6</a>) +- 🎯 优化 vuex 模块自动导入。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/4" target="_blank">#4</a>),感谢群友@web 小学生-第五君 +- 🎯 优化 类型定义提高编码体验,修复不能将类型“string | undefined”分配给类型“string”的问题。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/5" target="_blank">#5</a>) +- 🎯 优化 `layout` 文件夹移动到与 `views` 文件夹同级(改动较大,`/@/views/layout` 变成 `/@/layout`) +- 🎯 优化 页面有 `console.log` 时 `eslint` 不生效问题 +- 🎯 优化 页面、ts 中 `any` 类型问题(改动较大) +- 🎯 优化 登录页在手机上显示的效果 +- 🎯 优化 多行注释信息,鼠标放到方法名即可查看,更加直观的知道方法参数等。引入方法时需去掉以 `.ts` 结尾的后缀(改动较大) +- 🎯 优化 移除 `utils/storage.ts` 下的旧写法(改动较大) +- 🎯 优化 拆分 `router` 下内容,路由、前端、后端控制分开写,方便理解 +- 🐞 修复 鼠标移入顶部用户信息栏 `开/关全屏` 文字反向问题 +- 🐞 修复 热更新时,NextLoading(界面 loading) 不消失问题 `window.nextLoading === undefined` +- 🐞 修复 vuex 中不可以使用 `/@/api/xxx` 下的接口调用问题 + +## 1.0.3 + +`2021.06.02` + +- ❄️ 删除 G6 思维导图界面 +- 🌟 更新 手动更新 vue、vue-router、vuex 到最近最多人使用的版本,出现不可预测的问题请降低版本。版本查看:<a href="https://www.npmjs.com/package/vue" target="_blank">vue 版本查看</a> +- 🐞 修复 开启后端控制路由 `isRequestRoutes` 在非首页刷新页面后,回到首页的问题,感谢群友@伯牙已遇钟子期 + +## 1.0.2 + +`2021.06.01` + +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 菜单搜索中文不可以搜索的问题,感谢群友@逍遥天意 + +## 1.0.1 + +`2021.05.31` + +- 🎉 新增 更新日志文件 `CHANGELOG.md`,以后每次更新都会在这里显示对应内容 +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 分栏、经典布局路由设置 `meta.isHide` 为 `true` 时报错问题,感谢群友@29、@芭芭拉 +- 🐞 修复 经典布局点击 `tagsView` 左侧菜单数据不变问题 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6f6a7ea --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 lyt-Top + +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. \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..a550d07 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta + name="keywords" + content="vue-next-admin,vue-prev-admin,vue-admin-wonderful,后台管理系统一站式平台模板,希望可以帮你完成快速开发。vue2.x,vue2.0,vue2,vue3,vue3.x,vue3.0,CompositionAPI,typescript,element plus,element,plus,admin,wonderful,wonderful-next,vue-next-admin,vite,vite-admin,快速,高效,后台模板,后台系统,管理系统" + /> + <meta + name="description" + content="vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,适配手机、平板、pc 的后台开源免费管理系统模板!vue-prev-admin,基于 vue2 + element ui,适配手机、平板、pc 的后台开源免费管理系统模板!" + /> + <title>vue-next-admin</title> + </head> + <body> + <div id="app"></div> + <script type="text/javascript"> + var _hmt = _hmt || []; + (function () { + var hm = document.createElement('script'); + hm.src = 'https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4'; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(hm, s); + })(); + </script> + <script type="module" src="/src/main.ts"></script> + <script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=wsijQt8sLXrCW71YesmispvYHitfG9gv&s=1"></script> + </body> +</html> diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1c0d853 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7716 @@ +{ + "name": "vue-next-admin", + "version": "2.1.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "vue-next-admin", + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "@element-plus/icons-vue": "^2.0.3", + "@wangeditor/editor": "^5.1.1", + "axios": "^0.27.2", + "countup.js": "^2.2.0", + "cropperjs": "^1.5.12", + "echarts": "^5.3.2", + "echarts-gl": "^2.0.9", + "echarts-wordcloud": "^2.0.0", + "element-plus": "^2.2.2", + "js-cookie": "^3.0.1", + "jsplumb": "^2.15.6", + "mitt": "^3.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.0.14", + "print-js": "^1.6.0", + "qrcodejs2-fixes": "^0.0.2", + "screenfull": "^6.0.1", + "sortablejs": "^1.15.0", + "splitpanes": "^3.1.1", + "vue": "^3.2.36", + "vue-clipboard3": "^2.0.0", + "vue-grid-layout": "^3.0.0-beta1", + "vue-i18n": "^9.1.10", + "vue-router": "^4.0.15" + }, + "devDependencies": { + "@types/node": "^17.0.39", + "@types/nprogress": "^0.2.0", + "@types/sortablejs": "^1.13.0", + "@typescript-eslint/eslint-plugin": "^5.27.0", + "@typescript-eslint/parser": "^5.27.0", + "@vitejs/plugin-vue": "^2.3.3", + "@vue/compiler-sfc": "^3.2.36", + "dotenv": "^16.0.1", + "eslint": "^8.17.0", + "eslint-plugin-vue": "^9.1.0", + "prettier": "^2.6.2", + "sass": "^1.52.2", + "sass-loader": "^13.0.0", + "typescript": "^4.7.3", + "vite": "^2.9.9", + "vue-eslint-parser": "^9.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">= 6.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-AqDccGC+m5O/iUStSJy3DGRIUFu7WbY/CppZYwrEUB4N0tZlnI8CSTsgL7v5fHVFmUbRv2sd+yy27o8Ydt4MGg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz", + "integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.0.3.tgz", + "integrity": "sha512-dI9hazWIJF5AXsFDWLsdGqVIQMJ5Kq70fw1RScuMW6+UNqfJpRYFOqhya8RHpjajIZZnQx260Ll9AjTcu2HSOA==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.1.tgz", + "integrity": "sha512-grcqEmI8DTIolufpxhJagVeJmvloxBXE6xxSrVnSXz/Wz1uUIsC85ad+UNBqAoBOvzLxE42wvDj3YkmSGqWRxA==" + }, + "node_modules/@floating-ui/dom": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.1.tgz", + "integrity": "sha512-dkPSy5JPiQEtljc3VpG9lauYctxfLlqj/8N9f+lmsR92gQaSVMAWuBbFBH2keY5DmdQn3p4Dv1dQd+e8osH+/g==", + "dependencies": { + "@floating-ui/core": "^0.7.1" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@interactjs/actions": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.11.tgz", + "integrity": "sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/auto-scroll": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz", + "integrity": "sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/auto-start": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.11.tgz", + "integrity": "sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/core": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.11.tgz", + "integrity": "sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw==", + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/dev-tools": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz", + "integrity": "sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/modifiers": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/inertia": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.11.tgz", + "integrity": "sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw==", + "dependencies": { + "@interactjs/offset": "1.10.11" + }, + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/interact": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.11.tgz", + "integrity": "sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA==", + "dependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/types": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/interactjs": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.11.tgz", + "integrity": "sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg==", + "dependencies": { + "@interactjs/actions": "1.10.11", + "@interactjs/auto-scroll": "1.10.11", + "@interactjs/auto-start": "1.10.11", + "@interactjs/core": "1.10.11", + "@interactjs/dev-tools": "1.10.11", + "@interactjs/inertia": "1.10.11", + "@interactjs/interact": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/offset": "1.10.11", + "@interactjs/pointer-events": "1.10.11", + "@interactjs/reflow": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/modifiers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.11.tgz", + "integrity": "sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g==", + "dependencies": { + "@interactjs/snappers": "1.10.11" + }, + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/offset": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.11.tgz", + "integrity": "sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/pointer-events": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz", + "integrity": "sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/reflow": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.11.tgz", + "integrity": "sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/snappers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.11.tgz", + "integrity": "sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/types": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.11.tgz", + "integrity": "sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==" + }, + "node_modules/@interactjs/utils": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.11.tgz", + "integrity": "sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw==" + }, + "node_modules/@intlify/core-base": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", + "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", + "dependencies": { + "@intlify/devtools-if": "9.1.10", + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/devtools-if": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", + "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", + "dependencies": { + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", + "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", + "dependencies": { + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10", + "source-map": "0.6.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/message-resolver": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz", + "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/runtime": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz", + "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==", + "dependencies": { + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/shared": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", + "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/vue-devtools": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", + "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", + "dependencies": { + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" + }, + "node_modules/@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/event-emitter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz", + "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.39.tgz", + "integrity": "sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw==", + "dev": true + }, + "node_modules/@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==", + "dev": true + }, + "node_modules/@types/sortablejs": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz", + "integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@uppy/companion-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.1.0.tgz", + "integrity": "sha512-1Zsag2z9kygXuVbUxqHhkTJUmEHwbejjyf7vmm+P/AiVgK3O37JINYBGOpdTJNgbC9UydLBjleXo8peDVgpg8Q==", + "dependencies": { + "@uppy/utils": "^4.0.7", + "namespace-emitter": "^2.0.1" + } + }, + "node_modules/@uppy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", + "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", + "dependencies": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.0.3", + "@uppy/utils": "^4.0.7", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/store-default": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", + "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==" + }, + "node_modules/@uppy/utils": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", + "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", + "dependencies": { + "lodash.throttle": "^4.1.1" + } + }, + "node_modules/@uppy/xhr-upload": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.0.tgz", + "integrity": "sha512-io1uNu7lGkhIkMnt13bu3FYSAdRbBRWl8n/6njYi+727Jyr0XhKfmBYV9OiruFSxLz5Bfxkw2gTs6e0qUb63nA==", + "dependencies": { + "@uppy/companion-client": "^2.1.0", + "@uppy/utils": "^4.0.7", + "nanoid": "^3.1.25" + }, + "peerDependencies": { + "@uppy/core": "^2.2.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", + "dependencies": { + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", + "dependencies": { + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "node_modules/@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", + "dependencies": { + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", + "dependencies": { + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", + "dependencies": { + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "dependencies": { + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" + }, + "peerDependencies": { + "vue": "3.2.36" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" + }, + "node_modules/@vueuse/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-8.5.0.tgz", + "integrity": "sha512-VEJ6sGNsPlUp0o9BGda2YISvDZbhWJSOJu5zlp2TufRGVrLcYUKr31jyFEOj6RXzG3k/H4aCYeZyjpItfU8glw==", + "dependencies": { + "@vueuse/metadata": "8.5.0", + "@vueuse/shared": "8.5.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/@vueuse/shared": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-8.5.0.tgz", + "integrity": "sha512-qKG+SZb44VvGD4dU5cQ63z4JE2Yk39hQUecR0a9sEdJA01cx+XrxAvFKJfPooxwoiqalAVw/ktWK6xbyc/jS3g==", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.5.0.tgz", + "integrity": "sha512-WxsD+Cd+bn+HcjpY6Dl9FJ8ywTRTT9pTwk3bCQpzEhXVYAyNczKDSahk50fCfIJKeWHhyI4B2+/ZEOxQAkUr0g==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@wangeditor/basic-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.1.tgz", + "integrity": "sha512-tQl2Pw8M2g3CM+ESx2phzr9zSKeuFCM1AMBoPdnlbatU7Dnae0CsEB/b3C+gI0dIQzM2jh34yTmqgbbhrwuRLg==", + "dependencies": { + "is-url": "^1.2.4" + }, + "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" + } + }, + "node_modules/@wangeditor/code-highlight": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz", + "integrity": "sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ==", + "dependencies": { + "prismjs": "^1.23.0" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.1.tgz", + "integrity": "sha512-SrbvOGlONMNMOeFIJI7fC9x0/6T6LvQHTITPCqjgbCm2QF+POcrHzRKGQOqKCsyKi9UJz9hLsjsvJnvP10rxjQ==", + "dependencies": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + }, + "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" + } + }, + "node_modules/@wangeditor/editor": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.1.tgz", + "integrity": "sha512-BtccuHFm0QvYunIhIu7tllQWkwppkmEkD3OJ5Mn+F0REPQ/Z3HiEXbtlss2t9c/kHO4CtiFwv2XD/k/VEg7taA==", + "dependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.1", + "@wangeditor/code-highlight": "^1.0.2", + "@wangeditor/core": "^1.1.1", + "@wangeditor/list-module": "^1.0.2", + "@wangeditor/table-module": "^1.1.0", + "@wangeditor/upload-image-module": "^1.0.1", + "@wangeditor/video-module": "^1.1.0", + "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" + } + }, + "node_modules/@wangeditor/list-module": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.2.tgz", + "integrity": "sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg==", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/table-module": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.0.tgz", + "integrity": "sha512-QpjCXSzsXcsR0pEI5Pu28e8aYh9+lHcVV4TTmGV6lRGE/etQF3PHUZNGUlfhkCgmGPq+E7n/Whb4RpAM3PJVhw==", + "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" + } + }, + "node_modules/@wangeditor/upload-image-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz", + "integrity": "sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w==", + "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" + } + }, + "node_modules/@wangeditor/video-module": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.0.tgz", + "integrity": "sha512-VR6x7Vk9ebvXtxCPwobiNiTGZGgqEzCVc6ViWlNH3v4jlDIeo/s7N7OCgpvELR7X/X7GHecBu7wySDkHIskB5w==", + "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" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-validator": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.1.1.tgz", + "integrity": "sha512-p4DO/JXwjs8klJyJL8Q2oM4ks5fUTze/h5k10oPPKMiLe1fj3G1QMzPHNmN1Py4ycOk7WlO2DcGXv1qiESJCZA==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001342", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz", + "integrity": "sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ], + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/claygl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", + "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" + }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/countup.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.2.0.tgz", + "integrity": "sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g==" + }, + "node_modules/cropperjs": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz", + "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dayjs": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", + "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "dependencies": { + "ssr-window": "^3.0.0-alpha.1" + } + }, + "node_modules/dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/echarts": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.2.tgz", + "integrity": "sha512-LWCt7ohOKdJqyiBJ0OGBmE9szLdfA9sGcsMEi+GGoc6+Xo75C+BkcT/6NNGRHAWtnQl2fNow05AQjznpap28TQ==", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.3.1" + } + }, + "node_modules/echarts-gl": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz", + "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==", + "dependencies": { + "claygl": "^1.2.1", + "zrender": "^5.1.1" + }, + "peerDependencies": { + "echarts": "^5.1.2" + } + }, + "node_modules/echarts-wordcloud": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz", + "integrity": "sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==", + "peerDependencies": { + "echarts": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", + "dev": true, + "peer": true + }, + "node_modules/element-plus": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.2.2.tgz", + "integrity": "sha512-yGcj2Ayb0jZO1WbI51tHJ4efhlfWKlBqqGtWbzhq+tcpfaKzJZN+IHRouuFasqn0ZV3tWCDu1jggDR1+9y7XfQ==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^1.1.4", + "@floating-ui/dom": "^0.5.0", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^8.5.0", + "async-validator": "^4.1.1", + "dayjs": "^1.11.2", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.1.2" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-plus/node_modules/@element-plus/icons-vue": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz", + "integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dependencies": { + "batch-processor": "1.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "node_modules/es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/esbuild": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", + "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.39", + "esbuild-android-arm64": "0.14.39", + "esbuild-darwin-64": "0.14.39", + "esbuild-darwin-arm64": "0.14.39", + "esbuild-freebsd-64": "0.14.39", + "esbuild-freebsd-arm64": "0.14.39", + "esbuild-linux-32": "0.14.39", + "esbuild-linux-64": "0.14.39", + "esbuild-linux-arm": "0.14.39", + "esbuild-linux-arm64": "0.14.39", + "esbuild-linux-mips64le": "0.14.39", + "esbuild-linux-ppc64le": "0.14.39", + "esbuild-linux-riscv64": "0.14.39", + "esbuild-linux-s390x": "0.14.39", + "esbuild-netbsd-64": "0.14.39", + "esbuild-openbsd-64": "0.14.39", + "esbuild-sunos-64": "0.14.39", + "esbuild-windows-32": "0.14.39", + "esbuild-windows-64": "0.14.39", + "esbuild-windows-arm64": "0.14.39" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", + "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", + "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", + "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", + "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", + "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", + "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", + "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", + "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", + "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", + "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", + "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", + "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", + "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", + "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", + "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", + "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", + "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", + "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", + "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", + "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", + "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "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.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz", + "integrity": "sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "dependencies": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "dependencies": { + "delegate": "^3.1.2" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz", + "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/jsplumb": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz", + "integrity": "sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg==" + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash-unified": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.2.tgz", + "integrity": "sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true, + "peer": true + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", + "dependencies": { + "wildcard": "^1.1.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", + "dev": true, + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz", + "integrity": "sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png==" + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "dependencies": { + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/preact": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.2.tgz", + "integrity": "sha512-GLjn0I3r6ka+NvxJUppsVFqb4V0qDTEHT/QxHlidPuClGaxF/4AI2Qti4a0cv3XMh5n1+D3hLScW10LRIm5msQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/print-js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz", + "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==" + }, + "node_modules/prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcodejs2-fixes": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz", + "integrity": "sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.74.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz", + "integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/sass": { + "version": "1.52.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz", + "integrity": "sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.0.tgz", + "integrity": "sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/screenfull": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.1.tgz", + "integrity": "sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew==", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "dependencies": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slate": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "dependencies": { + "is-plain-object": "^5.0.0" + }, + "peerDependencies": { + "slate": ">=0.65.3" + } + }, + "node_modules/snabbdom": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz", + "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==", + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "node_modules/splitpanes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-3.1.1.tgz", + "integrity": "sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA==" + }, + "node_modules/ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "peer": true, + "dependencies": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "peer": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vite": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", + "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.27", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", + "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", + "dependencies": { + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-sfc": "3.2.36", + "@vue/runtime-dom": "3.2.36", + "@vue/server-renderer": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/vue-clipboard3": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz", + "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==", + "dependencies": { + "clipboard": "^2.0.6" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", + "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-grid-layout": { + "version": "3.0.0-beta1", + "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", + "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "dependencies": { + "@interactjs/actions": "^1.10.2", + "@interactjs/auto-start": "^1.10.2", + "@interactjs/dev-tools": "^1.10.2", + "@interactjs/interactjs": "^1.10.2", + "@interactjs/modifiers": "^1.10.2", + "element-resize-detector": "^1.2.1", + "mitt": "^2.1.0" + } + }, + "node_modules/vue-grid-layout/node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" + }, + "node_modules/vue-i18n": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", + "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", + "dependencies": { + "@intlify/core-base": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10", + "@vue/devtools-api": "^6.0.0-beta.7" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", + "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", + "dependencies": { + "@vue/devtools-api": "^6.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "peer": true + }, + "node_modules/webpack": { + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "peer": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/zrender": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.1.tgz", + "integrity": "sha512-7olqIjy0gWfznKr6vgfnGBk7y4UtdMvdwFmK92vVQsQeDPyzkHW1OlrLEKg6GHz1W5ePf0FeN1q2vkl/HFqhXw==", + "dependencies": { + "tslib": "2.3.0" + } + } + }, + "dependencies": { + "@babel/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-AqDccGC+m5O/iUStSJy3DGRIUFu7WbY/CppZYwrEUB4N0tZlnI8CSTsgL7v5fHVFmUbRv2sd+yy27o8Ydt4MGg==" + }, + "@babel/runtime": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz", + "integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" + }, + "@element-plus/icons-vue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.0.3.tgz", + "integrity": "sha512-dI9hazWIJF5AXsFDWLsdGqVIQMJ5Kq70fw1RScuMW6+UNqfJpRYFOqhya8RHpjajIZZnQx260Ll9AjTcu2HSOA==", + "requires": {} + }, + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@floating-ui/core": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.1.tgz", + "integrity": "sha512-grcqEmI8DTIolufpxhJagVeJmvloxBXE6xxSrVnSXz/Wz1uUIsC85ad+UNBqAoBOvzLxE42wvDj3YkmSGqWRxA==" + }, + "@floating-ui/dom": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.1.tgz", + "integrity": "sha512-dkPSy5JPiQEtljc3VpG9lauYctxfLlqj/8N9f+lmsR92gQaSVMAWuBbFBH2keY5DmdQn3p4Dv1dQd+e8osH+/g==", + "requires": { + "@floating-ui/core": "^0.7.1" + } + }, + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@interactjs/actions": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.11.tgz", + "integrity": "sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/auto-scroll": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz", + "integrity": "sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/auto-start": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.11.tgz", + "integrity": "sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/core": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.11.tgz", + "integrity": "sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw==", + "requires": {} + }, + "@interactjs/dev-tools": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz", + "integrity": "sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/inertia": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.11.tgz", + "integrity": "sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw==", + "requires": { + "@interactjs/interact": "1.10.11", + "@interactjs/offset": "1.10.11" + } + }, + "@interactjs/interact": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.11.tgz", + "integrity": "sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA==", + "requires": { + "@interactjs/core": "1.10.11", + "@interactjs/types": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "@interactjs/interactjs": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.11.tgz", + "integrity": "sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg==", + "requires": { + "@interactjs/actions": "1.10.11", + "@interactjs/auto-scroll": "1.10.11", + "@interactjs/auto-start": "1.10.11", + "@interactjs/core": "1.10.11", + "@interactjs/dev-tools": "1.10.11", + "@interactjs/inertia": "1.10.11", + "@interactjs/interact": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/offset": "1.10.11", + "@interactjs/pointer-events": "1.10.11", + "@interactjs/reflow": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "@interactjs/modifiers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.11.tgz", + "integrity": "sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g==", + "requires": { + "@interactjs/interact": "1.10.11", + "@interactjs/snappers": "1.10.11" + } + }, + "@interactjs/offset": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.11.tgz", + "integrity": "sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/pointer-events": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz", + "integrity": "sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/reflow": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.11.tgz", + "integrity": "sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/snappers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.11.tgz", + "integrity": "sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/types": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.11.tgz", + "integrity": "sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==" + }, + "@interactjs/utils": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.11.tgz", + "integrity": "sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw==" + }, + "@intlify/core-base": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", + "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", + "requires": { + "@intlify/devtools-if": "9.1.10", + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10" + } + }, + "@intlify/devtools-if": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", + "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", + "requires": { + "@intlify/shared": "9.1.10" + } + }, + "@intlify/message-compiler": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", + "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", + "requires": { + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10", + "source-map": "0.6.1" + } + }, + "@intlify/message-resolver": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz", + "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==" + }, + "@intlify/runtime": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz", + "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==", + "requires": { + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10" + } + }, + "@intlify/shared": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", + "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==" + }, + "@intlify/vue-devtools": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", + "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", + "requires": { + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@popperjs/core": { + "version": "npm:@sxzz/popperjs-es@2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" + }, + "@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": true + }, + "@types/event-emitter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz", + "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==" + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.39.tgz", + "integrity": "sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw==", + "dev": true + }, + "@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==", + "dev": true + }, + "@types/sortablejs": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz", + "integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@uppy/companion-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.1.0.tgz", + "integrity": "sha512-1Zsag2z9kygXuVbUxqHhkTJUmEHwbejjyf7vmm+P/AiVgK3O37JINYBGOpdTJNgbC9UydLBjleXo8peDVgpg8Q==", + "requires": { + "@uppy/utils": "^4.0.7", + "namespace-emitter": "^2.0.1" + } + }, + "@uppy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", + "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", + "requires": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.0.3", + "@uppy/utils": "^4.0.7", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "@uppy/store-default": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", + "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==" + }, + "@uppy/utils": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", + "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", + "requires": { + "lodash.throttle": "^4.1.1" + } + }, + "@uppy/xhr-upload": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.0.tgz", + "integrity": "sha512-io1uNu7lGkhIkMnt13bu3FYSAdRbBRWl8n/6njYi+727Jyr0XhKfmBYV9OiruFSxLz5Bfxkw2gTs6e0qUb63nA==", + "requires": { + "@uppy/companion-client": "^2.1.0", + "@uppy/utils": "^4.0.7", + "nanoid": "^3.1.25" + } + }, + "@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", + "dev": true, + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", + "requires": { + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", + "requires": { + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", + "requires": { + "@vue/shared": "3.2.36" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", + "requires": { + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", + "requires": { + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" + } + }, + "@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "requires": { + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" + }, + "@vueuse/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-8.5.0.tgz", + "integrity": "sha512-VEJ6sGNsPlUp0o9BGda2YISvDZbhWJSOJu5zlp2TufRGVrLcYUKr31jyFEOj6RXzG3k/H4aCYeZyjpItfU8glw==", + "requires": { + "@vueuse/metadata": "8.5.0", + "@vueuse/shared": "8.5.0", + "vue-demi": "*" + }, + "dependencies": { + "@vueuse/shared": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-8.5.0.tgz", + "integrity": "sha512-qKG+SZb44VvGD4dU5cQ63z4JE2Yk39hQUecR0a9sEdJA01cx+XrxAvFKJfPooxwoiqalAVw/ktWK6xbyc/jS3g==", + "requires": { + "vue-demi": "*" + } + }, + "vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "requires": {} + } + } + }, + "@vueuse/metadata": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.5.0.tgz", + "integrity": "sha512-WxsD+Cd+bn+HcjpY6Dl9FJ8ywTRTT9pTwk3bCQpzEhXVYAyNczKDSahk50fCfIJKeWHhyI4B2+/ZEOxQAkUr0g==" + }, + "@wangeditor/basic-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.1.tgz", + "integrity": "sha512-tQl2Pw8M2g3CM+ESx2phzr9zSKeuFCM1AMBoPdnlbatU7Dnae0CsEB/b3C+gI0dIQzM2jh34yTmqgbbhrwuRLg==", + "requires": { + "is-url": "^1.2.4" + } + }, + "@wangeditor/code-highlight": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz", + "integrity": "sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ==", + "requires": { + "prismjs": "^1.23.0" + } + }, + "@wangeditor/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.1.tgz", + "integrity": "sha512-SrbvOGlONMNMOeFIJI7fC9x0/6T6LvQHTITPCqjgbCm2QF+POcrHzRKGQOqKCsyKi9UJz9hLsjsvJnvP10rxjQ==", + "requires": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + } + }, + "@wangeditor/editor": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.1.tgz", + "integrity": "sha512-BtccuHFm0QvYunIhIu7tllQWkwppkmEkD3OJ5Mn+F0REPQ/Z3HiEXbtlss2t9c/kHO4CtiFwv2XD/k/VEg7taA==", + "requires": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.1", + "@wangeditor/code-highlight": "^1.0.2", + "@wangeditor/core": "^1.1.1", + "@wangeditor/list-module": "^1.0.2", + "@wangeditor/table-module": "^1.1.0", + "@wangeditor/upload-image-module": "^1.0.1", + "@wangeditor/video-module": "^1.1.0", + "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" + } + }, + "@wangeditor/list-module": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.2.tgz", + "integrity": "sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg==", + "requires": {} + }, + "@wangeditor/table-module": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.0.tgz", + "integrity": "sha512-QpjCXSzsXcsR0pEI5Pu28e8aYh9+lHcVV4TTmGV6lRGE/etQF3PHUZNGUlfhkCgmGPq+E7n/Whb4RpAM3PJVhw==", + "requires": {} + }, + "@wangeditor/upload-image-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz", + "integrity": "sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w==", + "requires": {} + }, + "@wangeditor/video-module": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.0.tgz", + "integrity": "sha512-VR6x7Vk9ebvXtxCPwobiNiTGZGgqEzCVc6ViWlNH3v4jlDIeo/s7N7OCgpvELR7X/X7GHecBu7wySDkHIskB5w==", + "requires": {} + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peer": true, + "requires": {} + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "async-validator": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.1.1.tgz", + "integrity": "sha512-p4DO/JXwjs8klJyJL8Q2oM4ks5fUTze/h5k10oPPKMiLe1fj3G1QMzPHNmN1Py4ycOk7WlO2DcGXv1qiESJCZA==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001342", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz", + "integrity": "sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==", + "dev": true, + "peer": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true + }, + "claygl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", + "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" + }, + "clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "countup.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.2.0.tgz", + "integrity": "sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g==" + }, + "cropperjs": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz", + "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dayjs": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", + "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "requires": { + "ssr-window": "^3.0.0-alpha.1" + } + }, + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true + }, + "echarts": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.2.tgz", + "integrity": "sha512-LWCt7ohOKdJqyiBJ0OGBmE9szLdfA9sGcsMEi+GGoc6+Xo75C+BkcT/6NNGRHAWtnQl2fNow05AQjznpap28TQ==", + "requires": { + "tslib": "2.3.0", + "zrender": "5.3.1" + } + }, + "echarts-gl": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz", + "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==", + "requires": { + "claygl": "^1.2.1", + "zrender": "^5.1.1" + } + }, + "echarts-wordcloud": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz", + "integrity": "sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==", + "requires": {} + }, + "electron-to-chromium": { + "version": "1.4.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", + "dev": true, + "peer": true + }, + "element-plus": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.2.2.tgz", + "integrity": "sha512-yGcj2Ayb0jZO1WbI51tHJ4efhlfWKlBqqGtWbzhq+tcpfaKzJZN+IHRouuFasqn0ZV3tWCDu1jggDR1+9y7XfQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^1.1.4", + "@floating-ui/dom": "^0.5.0", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^8.5.0", + "async-validator": "^4.1.1", + "dayjs": "^1.11.2", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.1.2" + }, + "dependencies": { + "@element-plus/icons-vue": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz", + "integrity": "sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==", + "requires": {} + } + } + }, + "element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "requires": { + "batch-processor": "1.0.0" + } + }, + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "esbuild": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", + "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.39", + "esbuild-android-arm64": "0.14.39", + "esbuild-darwin-64": "0.14.39", + "esbuild-darwin-arm64": "0.14.39", + "esbuild-freebsd-64": "0.14.39", + "esbuild-freebsd-arm64": "0.14.39", + "esbuild-linux-32": "0.14.39", + "esbuild-linux-64": "0.14.39", + "esbuild-linux-arm": "0.14.39", + "esbuild-linux-arm64": "0.14.39", + "esbuild-linux-mips64le": "0.14.39", + "esbuild-linux-ppc64le": "0.14.39", + "esbuild-linux-riscv64": "0.14.39", + "esbuild-linux-s390x": "0.14.39", + "esbuild-netbsd-64": "0.14.39", + "esbuild-openbsd-64": "0.14.39", + "esbuild-sunos-64": "0.14.39", + "esbuild-windows-32": "0.14.39", + "esbuild-windows-64": "0.14.39", + "esbuild-windows-arm64": "0.14.39" + } + }, + "esbuild-android-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", + "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", + "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", + "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", + "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", + "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", + "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", + "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", + "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", + "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", + "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", + "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", + "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", + "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", + "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", + "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", + "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", + "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", + "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", + "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", + "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", + "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "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.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-plugin-vue": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz", + "integrity": "sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g==", + "dev": true, + "requires": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "requires": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==" + }, + "i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "immer": { + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz", + "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==" + }, + "immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "peer": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsplumb": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz", + "integrity": "sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg==" + }, + "klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash-unified": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.2.tgz", + "integrity": "sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==", + "requires": {} + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true, + "peer": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", + "requires": { + "wildcard": "^1.1.0" + } + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==" + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", + "dev": true, + "peer": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-wheel-es": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz", + "integrity": "sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png==" + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "requires": { + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "requires": {} + } + } + }, + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "preact": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.2.tgz", + "integrity": "sha512-GLjn0I3r6ka+NvxJUppsVFqb4V0qDTEHT/QxHlidPuClGaxF/4AI2Qti4a0cv3XMh5n1+D3hLScW10LRIm5msQ==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true + }, + "print-js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz", + "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==" + }, + "prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qrcodejs2-fixes": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz", + "integrity": "sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "2.74.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz", + "integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "peer": true + }, + "sass": { + "version": "1.52.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz", + "integrity": "sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.0.tgz", + "integrity": "sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "peer": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "screenfull": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.1.tgz", + "integrity": "sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew==" + }, + "scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "requires": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "peer": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slate": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "requires": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "requires": { + "is-plain-object": "^5.0.0" + } + }, + "snabbdom": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz", + "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==" + }, + "sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "splitpanes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-3.1.1.tgz", + "integrity": "sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA==" + }, + "ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true + }, + "terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "dev": true, + "peer": true, + "requires": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "peer": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "peer": true, + "requires": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "peer": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "devOptional": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vite": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", + "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", + "dev": true, + "requires": { + "esbuild": "^0.14.27", + "fsevents": "~2.3.2", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + } + }, + "vue": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", + "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", + "requires": { + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-sfc": "3.2.36", + "@vue/runtime-dom": "3.2.36", + "@vue/server-renderer": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "vue-clipboard3": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz", + "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==", + "requires": { + "clipboard": "^2.0.6" + } + }, + "vue-eslint-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", + "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "vue-grid-layout": { + "version": "3.0.0-beta1", + "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", + "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "requires": { + "@interactjs/actions": "^1.10.2", + "@interactjs/auto-start": "^1.10.2", + "@interactjs/dev-tools": "^1.10.2", + "@interactjs/interactjs": "^1.10.2", + "@interactjs/modifiers": "^1.10.2", + "element-resize-detector": "^1.2.1", + "mitt": "^2.1.0" + }, + "dependencies": { + "mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" + } + } + }, + "vue-i18n": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", + "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", + "requires": { + "@intlify/core-base": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10", + "@vue/devtools-api": "^6.0.0-beta.7" + } + }, + "vue-router": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", + "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", + "requires": { + "@vue/devtools-api": "^6.0.0" + } + }, + "watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "peer": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "peer": true + }, + "webpack": { + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "peer": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "zrender": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.3.1.tgz", + "integrity": "sha512-7olqIjy0gWfznKr6vgfnGBk7y4UtdMvdwFmK92vVQsQeDPyzkHW1OlrLEKg6GHz1W5ePf0FeN1q2vkl/HFqhXw==", + "requires": { + "tslib": "2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fbe32d7 --- /dev/null +++ b/package.json @@ -0,0 +1,81 @@ +{ + "name": "vue-next-admin", + "version": "2.1.1", + "description": "vue3 vite next admin template", + "author": "lyt_20201208", + "license": "MIT", + "scripts": { + "dev": "vite --force", + "build": "vite build", + "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.0.3", + "@wangeditor/editor": "^5.1.1", + "axios": "^0.27.2", + "countup.js": "^2.2.0", + "cropperjs": "^1.5.12", + "echarts": "^5.3.2", + "echarts-gl": "^2.0.9", + "echarts-wordcloud": "^2.0.0", + "element-plus": "^2.2.2", + "js-cookie": "^3.0.1", + "jsplumb": "^2.15.6", + "mitt": "^3.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.0.14", + "print-js": "^1.6.0", + "qrcodejs2-fixes": "^0.0.2", + "screenfull": "^6.0.1", + "sortablejs": "^1.15.0", + "splitpanes": "^3.1.1", + "vue": "^3.2.36", + "vue-clipboard3": "^2.0.0", + "vue-grid-layout": "^3.0.0-beta1", + "vue-i18n": "^9.1.10", + "vue-router": "^4.0.15" + }, + "devDependencies": { + "@types/node": "^17.0.39", + "@types/nprogress": "^0.2.0", + "@types/sortablejs": "^1.13.0", + "@typescript-eslint/eslint-plugin": "^5.27.0", + "@typescript-eslint/parser": "^5.27.0", + "@vitejs/plugin-vue": "^2.3.3", + "@vue/compiler-sfc": "^3.2.36", + "dotenv": "^16.0.1", + "eslint": "^8.17.0", + "eslint-plugin-vue": "^9.1.0", + "prettier": "^2.6.2", + "sass": "^1.52.2", + "sass-loader": "^13.0.0", + "typescript": "^4.7.3", + "vite": "^2.9.9", + "vue-eslint-parser": "^9.0.2" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead" + ], + "bugs": { + "url": "https://gitee.com/lyt-top/vue-next-admin/issues" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">= 6.0.0" + }, + "keywords": [ + "vue", + "vue3", + "vuejs/vue-next", + "element-ui", + "element-plus", + "vue-next-admin", + "next-admin" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/lyt-top/vue-next-admin.git" + } +} diff --git a/plugins.d.ts b/plugins.d.ts new file mode 100644 index 0000000..be0457a --- /dev/null +++ b/plugins.d.ts @@ -0,0 +1,4 @@ +declare module 'vue-grid-layout'; +declare module 'qrcodejs2-fixes'; +declare module 'splitpanes'; +declare module 'js-cookie'; diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..9da231b --- /dev/null +++ b/public/favicon.ico Binary files differ diff --git a/shim.d.ts b/shim.d.ts new file mode 100644 index 0000000..3e9bfd0 --- /dev/null +++ b/shim.d.ts @@ -0,0 +1,13 @@ +/* eslint-disable */ + +// 声明文件,*.vue 后缀的文件交给 vue 模块来处理 +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} + +// 声明文件,定义全局变量。其它 app.config.globalProperties.xxx,使用 getCurrentInstance() 来获取 +interface Window { + nextLoading: boolean; +} diff --git a/source.d.ts b/source.d.ts new file mode 100644 index 0000000..2f9c768 --- /dev/null +++ b/source.d.ts @@ -0,0 +1,6 @@ +declare module '*.json'; +declare module '*.png'; +declare module '*.jpg'; +declare module '*.scss'; +declare module '*.ts'; +declare module '*.js'; diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..e69c74b --- /dev/null +++ b/src/App.vue @@ -0,0 +1,100 @@ +<template> + <el-config-provider :size="getGlobalComponentSize" :locale="i18nLocale"> + <router-view v-show="themeConfig.lockScreenTime > 1" /> + <LockScreen v-if="themeConfig.isLockScreen" /> + <Setings ref="setingsRef" v-show="themeConfig.lockScreenTime > 1" /> + <CloseFull v-if="!themeConfig.isLockScreen" /> + </el-config-provider> +</template> + +<script lang="ts"> +import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent, watch, reactive, toRefs } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import other from '/@/utils/other'; +import { Local, Session } from '/@/utils/storage'; +import setIntroduction from '/@/utils/setIconfont'; +import LockScreen from '/@/layout/lockScreen/index.vue'; +import Setings from '/@/layout/navBars/breadcrumb/setings.vue'; +import CloseFull from '/@/layout/navBars/breadcrumb/closeFull.vue'; +import { initBackEndControlRoutes } from './router/backEnd'; + +export default ({ + name: 'app', + components: { LockScreen, Setings, CloseFull }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const setingsRef = ref(); + const route = useRoute(); + const stores = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive({ + i18nLocale: null, + }); + + // 获取全局组件大小 + const getGlobalComponentSize = computed(() => { + return other.globalComponentSize(); + }); + // 布局配置弹窗打开 + const openSetingsDrawer = () => { + setingsRef.value.openDrawer(); + }; + // 设置初始化,防止刷新时恢复默认 + onBeforeMount(() => { + // 设置批量第三方 icon 图标 + setIntroduction.cssCdn(); + // 设置批量第三方 js + setIntroduction.jsCdn(); + }); + // 页面加载时 + onMounted( () => { + nextTick(() => { + // 监听布局配置弹窗点击打开 + proxy.mittBus.on('openSetingsDrawer', () => { + openSetingsDrawer(); + }); + // 设置 i18n,App.vue 中的 el-config-provider + proxy.mittBus.on('getI18nConfig', (locale: string) => { + (state.i18nLocale as string | null) = locale; + }); + // 获取缓存中的布局配置 + if (Local.get('themeConfig')) { + storesThemeConfig.setThemeConfig(Local.get('themeConfig')); + document.documentElement.style.cssText = Local.get('themeConfigStyle'); + } + // 获取缓存中的全屏配置 + if (Session.get('isTagsViewCurrenFull')) { + stores.setCurrenFullscreen(Session.get('isTagsViewCurrenFull')); + } + }); + // if(!Session.get('token')) return + // initBackEndControlRoutes() + }); + // 页面销毁时,关闭监听布局配置/i18n监听 + onUnmounted(() => { + proxy.mittBus.off('openSetingsDrawer', () => {}); + proxy.mittBus.off('getI18nConfig', () => {}); + }); + // 监听路由的变化,设置网站标题 + watch( + () => route.path, + () => { + other.useTitle(); + }, + { + deep: true, + } + ); + return { + themeConfig, + setingsRef, + getGlobalComponentSize, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/api/department/index.ts b/src/api/department/index.ts new file mode 100644 index 0000000..0ed427c --- /dev/null +++ b/src/api/department/index.ts @@ -0,0 +1,26 @@ +import request from '/@/utils/request'; + +export function departmentApi() { + return { + getDepartmentList: () => { + return request({ + url: `/department/list`, + method: 'post', + }); + }, + addDepartment: (data: object) => { + return request({ + url: `/department/add`, + method: 'post', + data:data + }); + }, + modDepartment: (data: object) => { + return request({ + url: `/department/mod`, + method: 'post', + data:data + }); + }, + }; +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 0000000..ca48515 --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,25 @@ +import request from '/@/utils/request'; + +/** + * 登录api接口集合 + * @method signIn 用户登录 + * @method signOut 用户退出登录 + */ +export function useLoginApi() { + return { + signIn: (params: object) => { + return request({ + url: '/auth/login', + method: 'post', + data: params, + }); + }, + signOut: (params: object) => { + return request({ + url: '/user/signOut', + method: 'post', + data: params, + }); + }, + }; +} diff --git a/src/api/menu/index.ts b/src/api/menu/index.ts new file mode 100644 index 0000000..2af998a --- /dev/null +++ b/src/api/menu/index.ts @@ -0,0 +1,39 @@ +import request from '/@/utils/request'; + +/** + * 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu + * 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 + * @method getMenuAdmin 获取后端动态路由菜单(admin) + * @method getMenuTest 获取后端动态路由菜单(test) + */ +export function useMenuApi() { + return { + getMenuAdmin: (value?: string) => { + return request({ + url: `/auth/menu?projectId= ${value}`, + method: 'post', + }); + }, + addMenu: (value?: object) => { + return request({ + url: `/menu/add`, + method: 'post', + data:value + }); + }, + modMenu: (value?: object) => { + return request({ + url: `/menu/mod`, + method: 'post', + data:value + }); + }, + // getMenuTest: (params?: string) => { + // return request({ + // url: '/gitee/lyt-top/vue-next-admin-images/raw/master/menu/testMenu.json', + // method: 'get', + // params, + // }); + // }, + }; +} diff --git a/src/api/role/index.ts b/src/api/role/index.ts new file mode 100644 index 0000000..137195d --- /dev/null +++ b/src/api/role/index.ts @@ -0,0 +1,12 @@ +import request from '/@/utils/request'; + +export function useRoleApi() { + return { + getRoleList: () => { + return request({ + url: `/role/list`, + method: 'post', + }); + }, + }; +} diff --git a/src/assets/login-icon-two.svg b/src/assets/login-icon-two.svg new file mode 100644 index 0000000..b930211 --- /dev/null +++ b/src/assets/login-icon-two.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="1151.5635" height="842.24197" viewBox="0 0 1151.5635 842.24197" xmlns:xlink="http://www.w3.org/1999/xlink"><title>sunlight</title><path d="M1080.33549,309.07821h-.00006c-22.0216,0-39.87364,19.81184-39.87364,44.251v31.0502h9.54961l5.52868-11.50435-1.38218,11.50435h61.38126l5.02608-10.4585-1.25651,10.4585h6.91087v-24.38C1126.2196,331.87644,1105.67658,309.07821,1080.33549,309.07821Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1042.88322,452.6347l-6.62276,25.38724,61.81242-2.20758-1.1038-20.97207S1050.60977,442.70056,1042.88322,452.6347Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><polygon points="959.06 525.305 978.928 569.456 997.693 546.277 982.24 515.371 959.06 525.305" fill="#ffb9b9"/><polygon points="1008.731 687.562 1010.938 738.337 1035.222 738.337 1031.91 687.562 1008.731 687.562" fill="#ffb9b9"/><path d="M1004.25045,507.82436l11.03794,36.42517,16.55689,176.60691s15.45311,4.41518,26.491-1.10379l2.20759-24.28345,4.41517-139.07794s20.97207-11.03793,18.76448-26.491-7.72655-36.42517-7.72655-36.42517Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1038.468,755.074h-6.62276s-18.76448,19.86828-25.38724,22.07587-40.84035,20.97207-13.24552,24.28345,45.25552-11.03794,45.25552-11.03794,8.83035,5.519,20.97207,1.1038,5.519-17.66069,5.519-17.66069-6.16367-20.18749-6.39321-20.02789S1051.71356,763.90438,1038.468,755.074Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><circle cx="1048.46738" cy="323.31051" r="25.38724" fill="#ffb9b9"/><path d="M1110.2146,385.30331l-11.67815,9.73547-1.56737,1.30247-1.10379,13.24551h-43.04794s5.87219-5.08847,11.32493-10.35358c.11036-.1214.23176-.25385.36427-.37532.73953-.71743,1.40178-1.37974,1.99787-1.97577.32007-.33112.6291-.64021.90505-.92721.45259-.47462.89414-.92715,1.33561-1.37974a.03829.03829,0,0,0,.01105-.022,43.07955,43.07955,0,0,0,3.17893-3.73083l.01105-.011a12.81791,12.81791,0,0,0,.73952-1.09274c3.31138-5.519-4.41517-16.5569-4.41517-16.5569l24.28345-12.14173c.84994,11.96508,10.97171,19.95654,15.49723,22.95889C1109.37571,384.85072,1110.2146,385.30331,1110.2146,385.30331Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1169.81943,570.74057c-16.5569,4.41517-17.66069-28.69862-17.66069-28.69862l-22.59765-45.1953a104.51533,104.51533,0,0,1-9.73594-30.31979l-5.19538-32.65665-1.57841,1.88745v.01105l-2.83676,1.41288-17.24124-27.59483-4.83462-7.72655v-8.83034l16.55689-7.72656h6.62276s.1435-.02209.39735-.04419c3.04648-.32008,22.87063-1.64464,23.8861,17.70489.39969,7.59413.36519,13.88569.15854,18.82226a145.76191,145.76191,0,0,0,3.84972,40.63177c1.16857,4.79412,2.44343,8.95772,3.7183,11.18873,4.41517,7.72655,19.86827,68.43518,19.86827,68.43518S1186.37633,566.3254,1169.81943,570.74057Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1068.27046,397.445l-4.18335,7.62718-2.47256,4.51454L1049.506,431.66263s-3.43278,2.80361-8.99594,6.42408c-9.24979,6.01562-24.4159,14.272-39.571,15.65178-24.28345,2.20759-1.10379-76.16173-1.10379-76.16173s7.72655-30.90621,18.76449-27.59483,2.20758,14.34931-5.519,35.32138S1011.977,429.455,1011.977,429.455s23.17965-14.34931,35.32138-25.38724c6.32471-5.75079,11.75542-7.30711,15.49723-7.4727h.011a14.05473,14.05473,0,0,1,3.69775.287A8.35071,8.35071,0,0,1,1068.27046,397.445Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1071.93506,390.82228c-.04413.1214-.56294,1.10379-4.52559,5.1326A53.271,53.271,0,0,0,1071.93506,390.82228Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M1114.07788,434.42211l-1.02652,1.3466-16.08228,27.90392s-20.97207-7.72655-36.42517-9.93414a21.64727,21.64727,0,0,0-22.06482,9.901l4.40413-17.62754-2.37319-7.92523c-.27594-.92721-.596-1.95373-.93819-3.1127-3.31138-11.03793,8.83034-23.17966,8.83034-23.17966l14.39344-15.19925h.011a14.05473,14.05473,0,0,1,3.69775.287c-.59609.596-1.25834,1.25834-1.99787,1.97577-.13251.12147-.25391.25392-.36427.37532-4.22754,4.3158-2.031,5.519-.05517,5.839a9.71986,9.71986,0,0,0,1.97576.09937c4.6028.66225,14.68044-3.3776,22.07587-6.75521,5.03329-2.29591,8.83034-4.28272,8.83034-4.28272l9.63609-8.83035,1.446-1.32456c1.32457.872,2.16346,1.32456,2.16346,1.32456h1.10379s.1435-.02209.39735-.04419l-5.02587,3.72943a18.68469,18.68469,0,0,0-7.5132,16.183h0Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M1053.92115,465.88022l-16.1372,6.30165s-87.61936-33.89648-100.86488-6.30165,46.35931,93.82242,46.35931,93.82242l26.491-12.14173-11.03793-33.11379s64.02,54.08586,90.511,24.28345,8.83035-71.94211,8.83035-71.94211S1081.516,453.73849,1053.92115,465.88022Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1007.56183,586.19367l-9.93413,7.72656s8.83034,35.32138,5.519,40.84034-9.93414,20.97208,2.20759,19.86828,25.38724-19.86828,26.491-26.491,8.83035-26.491,8.83035-26.491,13.24552-30.90621,3.31138-32.01-25.75662-1.84256-25.75662-1.84256Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1091.67085,321.26789a20.91185,20.91185,0,0,0-16.50006-8.4201h-.78284c-15.09365,0-27.32941,13.658-27.32941,30.50606v.00006h5.05749l.81677-6.217,1.19755,6.217H1084.126l2.51307-5.25968-.62828,5.25968h5.901q4.13043,20.51274-11.86947,41.02548h10.05221l5.02608-10.51935-1.2565,10.51935h19.162l3.76958-24.19458C1116.79567,342.06532,1106.26771,326.70034,1091.67085,321.26789Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><circle cx="971.03374" cy="113.59071" r="91" fill="#ff6584"/><path d="M771.29477,567.032c-1.6806,13.391-3.05862,26.28082-4.18757,38.571h36.55924q1.99625-19.38064,5.00548-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M801.19676,703.21105q-1.17629-19.19032-.9509-38.571H763.184c-.60171,14.7787-.83742,27.751-.88075,38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M864.4142,361.58256C894.89157,280.388,924.75032,225.797,924.75032,225.797L893.6574,207.29872c-32.37571,48.82045-56.84558,101.59229-75.3218,154.28384Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M766.21242,615.836c-1.14212,13.751-1.97242,26.66388-2.56481,38.571h36.792q.53185-19.28516,2.25137-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M778.50126,518.22788c-2.24695,13.1965-4.19314,26.08124-5.8747,38.571h37.70491q3.28452-19.4853,7.41146-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M814.82354,371.81567q-6.5049,19.34635-11.981,38.571h44.39012c4.3882-13.35371,8.88306-26.24037,13.39195-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M787.981,469.42381q-4.29519,19.6076-7.68675,38.571H820.004q4.44783-19.61091,9.56837-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M762.3185,713.44417c.12069,16.62136.66994,25.97636.66994,25.97636l-.39358,7.478h43.29393q-2.59815-16.58382-3.96368-33.4544Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M799.97844,420.61974q-5.32646,19.46534-9.69876,38.571H832.379q5.53043-19.7784,11.542-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M1110.252,261.1651c-15.40963-32.21182-30.90977-56.23791-46.0196-73.94267l-7.89046,12.123.671-20.13755a158.22113,158.22113,0,0,0-16.6583-15.2789L1029.57149,180.496l.78947-23.69016a99.14041,99.14041,0,0,0-20.48314-10.11247l-7.97482,12.25252.48352-14.50965c-27.51475-6.905-50.1228,2.55337-63.22081,10.629l-7.86615-1.17354,13.49035-5.63347a99.1429,99.1429,0,0,0-6.25118-21.97146l-23.44384-3.4975L933.3355,115.172a158.21342,158.21342,0,0,0-12.02277-19.14149l-19.92822-2.973,13.34774-5.574c-14.68838-18.056-35.52378-37.63644-64.42682-58.60454,0,0-2.13827,18.67657-3.3293,44.71673l19.575,20.025-20.111-5.20116c-.21044,7.9976-.30047,16.41755-.20141,25.00812l14.43606,14.76794-14.20045-3.67257c.20688,6.56884.54118,13.17147,1.02835,19.7a77.7484,77.7484,0,0,0-37.38522.21323l.48352,14.50965-7.97482-12.25252A99.14066,99.14066,0,0,0,782.143,156.80588l.78947,23.69016L772.14939,163.929a158.22118,158.22118,0,0,0-16.65831,15.2789l.671,20.13755-7.89046-12.123c-15.10983,17.70476-30.61,41.73085-46.0195,73.94267,0,0,18.75584-1.2664,44.58355-4.79292l16.16488-22.86653L761.513,254.225c7.90429-1.2359,16.20236-2.66638,24.63409-4.31364l11.92111-16.86355-1.05035,14.63006c11.76-2.54214,23.55587-5.52,34.6978-8.989l8.00048,7.44239-14.31143-2.98448a99.14327,99.14327,0,0,0-7.27222,21.65494l17.35524,16.14443-19.35091-4.03541a158.216,158.216,0,0,0-.91179,22.58566l14.75256,13.72341-14.16008-2.95292c1.90026,23.19813,8.00769,51.13034,19.98347,84.7701,0,0,12.327-14.19261,28.03786-34.99356l-4.81657-27.58585,13.64313,15.66426c4.697-6.47636,9.53377-13.36913,14.311-20.50951l-3.55213-20.344L893.0578,318.329c9.67465-15.1043,18.722-30.948,25.38657-46.03838A385.08247,385.08247,0,0,0,946.086,304.50881l7.38-12.67579.33948,20.64894c6.03555,6.11391,12.08293,11.97343,17.91467,17.45027l10.45191-17.95172.46027,27.99943c19.34428,17.473,34.12174,29.09258,34.12174,29.09258,5.43182-35.29231,6.17421-63.8748,3.67531-87.01609l-13.35149,5.56466,11.9067-16.25425a158.22134,158.22134,0,0,0-5.14539-22.01061l-18.246,7.60454,8.67646-11.84438q5.59182,1.34816,11.21649,2.56145l-1.05035-14.63006,11.92111,16.86355c8.43173,1.64726,16.7298,3.07774,24.63409,4.31364l-1.48755-20.71932,16.16488,22.86653C1091.49615,259.8987,1110.252,261.1651,1110.252,261.1651Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M706.516,543.343c1.1863,9.45251,2.159,18.55119,2.95593,27.2266H683.6654q-1.40913-13.68048-3.53328-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M685.40871,639.4695q.83031-13.54614.67122-27.2266h26.16136c.42474,10.432.59112,19.589.62171,27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M640.78457,398.31967c-21.51346-57.31385-42.59025-95.84872-42.59025-95.84872l21.948-13.05765c22.85347,34.46154,40.12634,71.71229,53.16839,108.90637Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M710.10356,577.79293c.8062,9.70662,1.3923,18.82158,1.81046,27.22659H685.94319q-.37542-13.61307-1.5892-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M701.42907,508.893c1.58609,9.31519,2.95987,18.41031,4.14686,27.22659H678.96066q-2.31847-13.75434-5.23162-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M675.78979,405.54305q4.59169,13.65627,8.45716,27.2266H652.91271c-3.09755-9.42616-6.2704-18.52264-9.45315-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M694.73746,474.443q3.0319,13.84068,5.42595,27.2266H672.133q-3.13965-13.843-6.75415-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M712.85221,646.69288c-.08519,11.73274-.47289,18.33627-.47289,18.33627l.27782,5.27863H682.09668q1.834-11.70624,2.79789-23.6149Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M686.26869,439.993q3.75987,13.74026,6.8462,27.22659H663.39766q-3.90382-13.96124-8.14726-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M467.25181,327.43668c10.87739-22.73779,21.81868-39.6974,32.48446-52.1949l5.56974,8.55742-.47364-14.21476a111.68489,111.68489,0,0,1,11.75882-10.78512l7.61163,11.69442-.55728-16.72249a69.98142,69.98142,0,0,1,14.4587-7.13822l5.6293,8.64885-.34131-10.24212c19.4222-4.8741,35.38084,1.80238,44.62651,7.50279l5.55258-.82838-9.52261-3.97657a69.98374,69.98374,0,0,1,4.4126-15.50928l16.54861-2.46883-12.87573-5.37687a111.68,111.68,0,0,1,8.48667-13.51166l14.067-2.09862-9.422-3.93455c10.36829-12.74544,25.07564-26.56694,45.47782-41.368,0,0,1.50937,13.18347,2.35009,31.56478l-13.81766,14.1353,14.196-3.67141c.14854,5.64537.21209,11.58887.14216,17.65281l-10.19016,10.42444,10.02385-2.59241c-.146,4.63684-.382,9.29752-.72589,13.90591a54.88123,54.88123,0,0,1,26.3896.15051l-.34131,10.24212,5.62929-8.64885a69.98117,69.98117,0,0,1,14.4587,7.13822l-.55727,16.72249,7.61163-11.69442a111.68687,111.68687,0,0,1,11.75882,10.78512l-.47364,14.21476,5.56974-8.55742c10.66577,12.4975,21.60706,29.45711,32.48439,52.1949,0,0-13.23943-.89394-31.47078-3.38325l-11.41052-16.1411,1.05,14.62542c-5.57951-.8724-11.437-1.88215-17.38879-3.04492l-8.41491-11.9037.74142,10.32711c-8.30116-1.79445-16.62769-3.8965-24.49259-6.34518l-5.6474,5.25346,10.10219-2.10669a69.98325,69.98325,0,0,1,5.13334,15.28586L661.2033,341.39976l13.65948-2.84853a111.68285,111.68285,0,0,1,.64362,15.94284l-10.41359,9.68713,9.99537-2.08442c-1.34137,16.37518-5.6525,36.092-14.106,59.83779,0,0-8.70142-10.01832-19.79145-24.70136l3.39993-19.47239L634.96021,388.818c-3.31556-4.57156-6.72974-9.437-10.10193-14.47732l2.50739-14.36046-6.80014,7.80752A247.60106,247.60106,0,0,1,602.64558,335.29a271.82334,271.82334,0,0,1-19.51173,22.74229l-5.20944-8.94763-.23963,14.57574c-4.2604,4.31571-8.52914,8.45185-12.64567,12.31786l-7.37783-12.67182-.32489,19.76432c-13.65481,12.33393-24.086,20.536-24.086,20.536-3.83423-24.91224-4.35827-45.08815-2.59434-61.4232l9.4246,3.928-8.40474-11.47361a111.68612,111.68612,0,0,1,3.632-15.53692l12.87953,5.36792-6.12457-8.36075q-3.94716.95164-7.91753,1.80808l.74143-10.32711-8.41492,11.9037c-5.95181,1.16277-11.80928,2.17252-17.38879,3.04492l1.05-14.62542-11.41052,16.1411C480.49124,326.54274,467.25181,327.43668,467.25181,327.43668Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><ellipse cx="379.53374" cy="720.59071" rx="147.5" ry="14" fill="#3f3d56"/><ellipse cx="734.53374" cy="720.59071" rx="147.5" ry="14" fill="#3f3d56"/><path d="M870.752,606.96972s10.65,73.95-40.48,117.67c-33.09,28.29-80.27,32.92-118.99,13.01-14.38-7.39-29.72-18.62-44.37006-35.57a191.08437,191.08437,0,0,1-15.26-20.3,242.48469,242.48469,0,0,1-17.73-32.37q-4.8-10.485-9.17-22.44c-.56-1.53-1.08-3.03-1.58-4.52-26.55-78.91,25.09-101.93,72.49-107.45a243.44911,243.44911,0,0,1,29.96-1.51,268.64314,268.64314,0,0,1,35.13,2.48s.97.01,2.72.08a210.98673,210.98673,0,0,1,26.93005,2.99C827.022,525.46972,883.072,545.38971,870.752,606.96972Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M544.752,626.96972c-23.34,64.07-56.95,95.47-86.53,110.68-38.72,19.91-85.9,15.28-118.99-13.01a104.52345,104.52345,0,0,1-9-8.67,108.90024,108.90024,0,0,1-15.01-20.66,128.65459,128.65459,0,0,1-12.09-30.09,161.53735,161.53735,0,0,1-5.17-35.23,140.93566,140.93566,0,0,1,.79-23.02c-11.53-57.65,36.85-78.78,73.12-86.52a215.32462,215.32462,0,0,1,31.83-4.29c3.21-.18,5.05-.19,5.05-.19a276.07877,276.07877,0,0,1,57.57-1.71C516.412,518.29968,576.402,540.09973,544.752,626.96972Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M403.702,516.15973l-100.57,149.06a161.53735,161.53735,0,0,1-5.17-35.23l73.91-109.54A215.32462,215.32462,0,0,1,403.702,516.15973Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M466.322,514.2597l-136.09,201.71a108.90024,108.90024,0,0,1-15.01-20.66l122.6-181.71A262.51415,262.51415,0,0,1,466.322,514.2597Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M725.622,513.48968l-91.7,135.92q-4.8-10.485-9.17-22.44c-.56-1.53-1.08-3.03-1.58-4.52l72.49-107.45A243.44911,243.44911,0,0,1,725.622,513.48968Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M790.402,519.03973l-123.49,183.04a191.08437,191.08437,0,0,1-15.26-20.3l111.81995-165.73A210.98673,210.98673,0,0,1,790.402,519.03973Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M894.752,599.96972H871.86472c10.12915-83.03949-111.11273-84-111.11273-84a276.47448,276.47448,0,0,0-58-1.67132v-.32868h-237v.24872a276.75793,276.75793,0,0,0-57,1.75128s-121.24188.96051-111.11273,84H275.752v22H297.8389c-.22119,23.90107,4.52283,71.14319,41.39307,102.67,33.09,28.29,80.27,32.92,118.99,13.01,29.58-15.21,63.19-46.61,86.53-110.68,7.996-21.94982,10.13965-39.74377,8.07287-54.14819a635.39219,635.39219,0,0,1,63.85425,0c-2.06677,14.40442.07684,32.19837,8.07288,54.14819,23.34,64.07,56.95,95.47,86.53,110.68,38.72,19.91,85.9,15.28,118.99-13.01,36.87024-31.5268,41.61425-78.76892,41.39306-102.67H894.752Zm-360.54,27.41c-22.21,60.97-54.61,89.49-82.4,102.65-33.81,16.01-74.1,11.56-103.12-12.03-35.08-28.52-39.75-72.35-39.62-94.69.06-8.88-.34-17.74-.69-26.61-2.77-69.71,101.83-70.53,101.83-70.53S580.722,499.72973,534.212,627.3797Zm83.38928-59.56537a424.54686,424.54686,0,0,0-65.69861,0c-5.48632-24.48639-23.97729-38.28705-45.937-45.84461H663.53824C641.57859,529.52728,623.08762,543.32794,617.60129,567.81433ZM862.202,596.3797c-.36,8.95-.76,17.9-.7,26.85.14,22.55-4.58,66.79-39.98,95.56-29.28,23.81-69.92005,28.31-104.03,12.17-28.06-13.27-60.78-42.05-83.21-103.62-46.93006-128.83,125.15-102.14,125.15-102.14S864.992,526.01971,862.202,596.3797Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M428.14356,741.71275c-.11325-.18506-2.78356-4.64376-3.70932-13.90237-.84914-8.49429-.30313-22.81207,7.12226-42.7842,14.06719-37.83586-3.24186-68.36391-3.41872-68.668l.854-.49541a75.78134,75.78134,0,0,1,7.14973,20.25453,88.3638,88.3638,0,0,1-3.65968,49.253c-14.04309,37.77129-3.60282,55.65189-3.49584,55.82827Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><circle cx="398.4247" cy="578.84223" r="6.41529" fill="#3f3d56"/><circle cx="418.65754" cy="602.52946" r="6.41529" fill="#3f3d56"/><circle cx="404.83999" cy="618.32095" r="6.41529" fill="#fff"/><circle cx="421.61845" cy="631.64502" r="6.41529" fill="#fff"/><circle cx="399.90515" cy="652.37134" r="6.41529" fill="#3f3d56"/><path d="M432.01914,741.94889s-6.41529-15.79149,12.83059-27.63511Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M424.12933,741.66244s-2.91966-16.79294-25.51732-16.649Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M363.072,370.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92005,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C358.782,360.96972,363.072,365.78973,363.072,370.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M561.072,447.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92005,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C556.782,437.96972,561.072,442.78973,561.072,447.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M606.072,137.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C601.782,127.96972,606.072,132.78973,606.072,137.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M53.17754,652.8835l9.13713,28.28159s-8.26692,26.54118-4.351,56.12807,1.7404,30.4571,1.7404,30.4571-39.12624-2.25247-35.21033,9.49526,42.172,4.86308,42.172,4.86308,7.34723-1.97821,10.828-22.86308S89.72606,698.134,89.72606,698.134l-8.22935-37.97489Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M56.22325,595.015S39.6894,601.10644,39.6894,617.64029s6.09142,39.15912,10.00733,40.46443,30.022,19.14446,34.80811,6.52652S56.22325,595.015,56.22325,595.015Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><polygon points="170.367 761.932 205.175 760.626 231.717 756.71 223.885 782.816 159.49 784.557 170.367 761.932" fill="#ffb8b8"/><path d="M244.62214,794.29144s-.43511-9.57223-4.351-9.13713-1.3053-3.48081,2.17551-4.351,13.48814-5.22122,13.48814-5.22122l39.59422,2.61061S321.2,800.818,310.75754,813.0008s-37.41872,1.3053-37.41872,1.3053l-29.15179.4351S234.6148,799.07755,244.62214,794.29144Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><polygon points="236.068 731.91 248.685 791.083 274.792 785.862 259.998 711.895 244.334 703.628 236.068 731.91" fill="#ffb8b8"/><path d="M110.17582,753.39191s-73.097,33.0677-42.20483,66.57051c0,0,0,15.66365,32.6326,12.61794s95.7223-8.702,98.768-6.96162,12.61793-34.373,4.351-36.11342-18.27426-3.91591-18.27426-3.91591,8.702-1.3053,8.702-8.702c0,0,24.80078-1.7404,32.1975-17.404S240.70622,732.072,240.70622,732.072l16.969,43.51013s19.57956-36.11341,34.373-20.01466c0,0-16.53385-103.98922-29.15179-113.56145s-21.32-12.61794-33.0677-3.91591-22.62527,30.89219-22.62527,30.89219Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M284.65146,802.12326a98.03577,98.03577,0,0,0-8.702,7.39673c-3.48081,3.48081-8.26692,1.7404-8.702,0s-8.26692,1.3053-9.13712,13.92324-6.09142,23.93057,7.83182,27.84648,13.48814,15.22855,13.48814,15.22855a46.93427,46.93427,0,0,0,35.24321,2.17551c19.57956-6.52652,12.61794-13.48814,12.61794-13.48814l-26.10608-43.075S294.22369,799.07755,284.65146,802.12326Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M212.42464,586.313s41.76972,14.35834,46.12074,17.404,23.93057,17.404,14.35834,24.80078-17.40405,12.18283-36.11341,6.52652S197.19609,611.984,197.19609,611.984Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M170.65491,567.16854s16.53385-3.04571,28.28158,3.48081,21.75507,19.57956,21.75507,19.57956S209.814,613.28928,201.9822,616.77009,179.792,602.84685,179.792,602.84685Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M94.51217,554.5506s.4351,16.96895-1.3053,18.70936,20.88486,53.08236,45.68564,30.45709,5.65632-31.7624,5.65632-31.7624-9.13713-16.969-8.702-18.70936-40.46443,0-40.46443,0Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M94.51217,554.5506s.4351,16.96895-1.3053,18.70936,20.88486,53.08236,45.68564,30.45709,5.65632-31.7624,5.65632-31.7624-9.13713-16.969-8.702-18.70936-40.46443,0-40.46443,0Z" transform="translate(-24.21825 -28.87901)" opacity="0.1"/><path d="M101.47379,587.1832s16.53385,11.31263,23.49548,8.702,15.66364-13.92325,16.53385-14.79345,45.25054,88.32557,45.25054,88.32557-6.52652,32.6326-23.93058,42.20483-17.1865,17.18651-19.362,23.713-30.23954-20.66732-30.23954-20.66732L95.38237,638.96026V592.83952Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M94.29462,566.951s-5.43877-1.08776-11.09508,3.69836S51.002,593.27462,52.30734,595.015s13.053,26.54118,15.66365,36.54852,6.52652,11.31263,6.52652,11.31263,9.13713,6.52652,7.83182,11.31264-6.96162,70.05131.87021,84.40966,6.52652,26.97628,4.351,30.45709,20.88486-10.00733,20.88486-10.00733,34.373-27.84649,36.98362-36.11341a97.263,97.263,0,0,0,3.48081-17.40406s-22.19017-87.89047-29.15179-92.67658S94.29462,566.951,94.29462,566.951Z" transform="translate(-24.21825 -28.87901)" fill="#575a89"/><path d="M142.0946,567.29509s10.72115-6.65307,12.89666-4.91267,22.62527,1.74041,23.06037,3.48081,1.3053,43.51014,16.09875,54.38767,5.22122,32.6326,5.22122,32.6326l10.87753,17.40406s-59.17285,56.99362-55.25787,37.41871c.21755-1.08775,0-1.3053,0-1.3053s-23.06037-98.768-20.01466-103.98922S143.55629,573.51306,142.0946,567.29509Z" transform="translate(-24.21825 -28.87901)" fill="#575a89"/><path d="M233.3095,607.19786l-59.17378,20.44976s-58.73868,13.92325-49.60156,30.022S172.39531,646.357,172.39531,646.357l78.7996-8.82909S282.476,611.11377,233.3095,607.19786Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><circle cx="93.78939" cy="509.57283" r="32.1975" fill="#ffb8b8"/><path d="M92.36668,506.4531l-5.95587-2.16578s12.45312-12.45312,29.77934-11.37019l-4.8731-4.873s11.91174-4.33148,22.74055,7.03872c5.69249,5.97707,12.27878,13.00279,16.38465,20.91719h6.37832l-2.66208,5.32415,9.31726,5.32415-9.56325-.95636a26.866,26.866,0,0,1-.90453,13.789l-2.16569,5.95579s-8.66312-17.32606-8.66312-19.49184v5.4144s-5.95587-4.87294-5.95587-8.12156l-3.24862,3.79009-1.62432-5.95587-20.0333,5.95587,3.24863-4.87294-12.45312,1.62431,4.8731-5.95587s-14.07744,7.03872-14.619,12.99459-7.58,13.536-7.58,13.536L81.538,538.93944S76.66493,514.57467,92.36668,506.4531Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M146.61566,540.19858s1.05805,7.34674-4.02158,11.6902a10.68163,10.68163,0,0,1-11.82134,1.29251,14.7297,14.7297,0,0,1-4.40805-3.53378,18.98358,18.98358,0,0,1-1.516-2.01675,24.0899,24.0899,0,0,1-1.76144-3.21588q-.47687-1.04165-.911-2.22935c-.05564-.152-.1073-.301-.157-.449-2.63767-7.8395,2.49263-10.12648,7.20169-10.67488a24.18681,24.18681,0,0,1,2.97645-.15,26.68959,26.68959,0,0,1,3.49007.24639s.09637.001.27022.00794a20.96175,20.96175,0,0,1,2.67543.29706C142.2712,532.10177,147.83962,534.08077,146.61566,540.19858Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M114.22842,542.18553c-2.31877,6.36518-5.65784,9.48469-8.59653,10.99576a10.68165,10.68165,0,0,1-11.82135-1.29251,10.38378,10.38378,0,0,1-.89412-.86134,10.81892,10.81892,0,0,1-1.49121-2.05252,12.78124,12.78124,0,0,1-1.2011-2.98936,16.04808,16.04808,0,0,1-.51363-3.5,14.00278,14.00278,0,0,1,.07848-2.287c-1.14547-5.72738,3.661-7.82659,7.26428-8.59554a21.39066,21.39066,0,0,1,3.16223-.42619c.3189-.01789.50171-.01888.50171-.01888a27.42839,27.42839,0,0,1,5.71942-.16989C111.41291,531.38944,117.37277,533.55522,114.22842,542.18553Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M100.21547,531.17685l-9.99136,14.80871a16.04808,16.04808,0,0,1-.51363-3.5L97.05324,531.603A21.39066,21.39066,0,0,1,100.21547,531.17685Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M106.4366,530.98808,92.91642,551.02744a10.81892,10.81892,0,0,1-1.49121-2.05252l12.18-18.0524A26.08038,26.08038,0,0,1,106.4366,530.98808Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M132.19738,530.91158l-9.11016,13.5033q-.47687-1.04165-.911-2.22935c-.05564-.152-.1073-.301-.157-.449l7.20169-10.67488A24.18681,24.18681,0,0,1,132.19738,530.91158Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M138.6331,531.463l-12.26841,18.18454a18.98358,18.98358,0,0,1-1.516-2.01675l11.109-16.46485A20.96175,20.96175,0,0,1,138.6331,531.463Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M149,539.50315h-2.27379c1.0063-8.24976-11.03876-8.34518-11.03876-8.34518a27.46661,27.46661,0,0,0-5.76215-.166v-.03266H106.38v.02471a27.49535,27.49535,0,0,0-5.6628.174s-12.04507.09542-11.03876,8.34518H87.504v2.18564h2.19428c-.022,2.37451.44933,7.06789,4.11229,10.2a10.68165,10.68165,0,0,0,11.82135,1.29251c2.93869-1.51107,6.27776-4.63058,8.59653-10.99576a11.22868,11.22868,0,0,0,.802-5.37948,63.12484,63.12484,0,0,1,6.34375,0,11.22856,11.22856,0,0,0,.802,5.37948c2.31877,6.36518,5.65783,9.48469,8.59653,10.99576a10.68163,10.68163,0,0,0,11.82134-1.29251c3.663-3.1321,4.13427-7.82548,4.1123-10.2H149Zm-35.8187,2.72311c-2.20651,6.05721-5.42537,8.89059-8.18623,10.198a9.69145,9.69145,0,0,1-10.2447-1.19515c-3.48511-2.83339-3.94906-7.18778-3.93614-9.40721.006-.8822-.03378-1.76242-.06855-2.64363-.27519-6.92551,10.11654-7.007,10.11654-7.007S117.80194,529.54457,113.1813,542.22626Zm8.28451-5.91767a42.17881,42.17881,0,0,0-6.527,0c-.54505-2.43265-2.38208-3.80371-4.56371-4.55454h15.65441C123.84789,532.50488,122.01086,533.87594,121.46581,536.30859Zm24.30043,2.8379c-.03576.88916-.0755,1.77832-.06954,2.66748.01391,2.24028-.455,6.63541-3.97191,9.49363a9.77755,9.77755,0,0,1-10.33511,1.20906c-2.78768-1.31834-6.03833-4.17756-8.26669-10.29437-4.66238-12.79893,12.43332-10.14735,12.43332-10.14735S146.04342,532.15641,145.76624,539.14649Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/></svg> \ No newline at end of file diff --git a/src/assets/logo-mini.svg b/src/assets/logo-mini.svg new file mode 100644 index 0000000..53df94c --- /dev/null +++ b/src/assets/logo-mini.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 50" width="64" height="50"> + <defs> + <image width="64" height="50" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAyCAYAAADsg90UAAAAAXNSR0IB2cksfwAACI5JREFUeJy1WgtsW9UZdvNq0xU6WhZoCCVx7Gunbld1GSsMdYpGREhwr+2IMbQWqRoTk+iWPZi2wWhm1kwEmqV52feRJrbvvd6DiUnbQCAemzY2xh4tSB0wOqZIqAtLYzultIWEpt13btLq+sap/R8nRzpK4vh+5/++85///8851yEk1V+hX6B0tyE3OWwt0x789VR78AKlZ0KBz1oxBE3+BdUW9PNuQ7nJbk/BDQ/v4hi0x44z1R64jyrAVCjQ/fLNN8/ZoUWdgqGc57AFE6I86giH+QRw6XI9QE4RBz3iTAyVW3EyQdEDUmeIIhyeFNtMHO/o0B4e8qYASfVvLk2p4BKgdnioFCAvEQeddhnyFivOpOgvBaFXiAKcygQDrk927S/zjkae5xUA/X3YI/C5AFwHLrSPw+2+YYfCMugiCvDaCbGt0hc9uAXuP1OEAPACZQ+fAGguQ9nGgglx0OfsOAhq24lBcG/YYQa/kWLIz3XlCW4B6mKRCoCMEQdNu3VpnRVnMhBYA2L/LVCATCooXuNJSHXFzv58P+mMyyu5RQDAKNntdLnNjoN0+NMCM0D8901NDkGXuyBAseRZn3Ubagu3AFjTd1GXAdZdpCqurMgSIBS4BwRn8wgwje/d4pV6yz2adGQJyM/bo/ZyC+DSlWqApIiDHqtPyFdlCyBeD4Lv5xHgr5mAWO4ZjTRh9s8tlQDoryIbrOISoLYvvAIALxIHnIHn3GnFmfDfztLhH/IEv/vYd72xyKElJM/6Gdjj4fYCuNA3yYMa6ogdBwQfvIwAk+mguHZz3+MbMPsfLrEALD3v5RfAkH3UOID+Jqqwj2ULIDZeJvhF2He8I0NfX2ry8wI85VSy41LBzaUPsXT4L/Iy0OUbrTgpsXUlyI7lEOAsvGOboPRdKejK28shAPqpek1etxjHArxAiXCo/pAdB2QPLRQg8BLcv8ITi4h4bnaZBGD2+IsQQG0DCDUyv2LfjcHVQyB93iLAecz+bvY/T1x6YrnImwIkVakIAeSrAfIucdCz7qRcY8VJh8RrQDplWfvHxttaVvkGe6vg/h8tpwDoR926wpcOb9CkEhQ4Mbrqym4rTkrcydLhs5bU95Wwwwx+311m8qxPQ4CtvE6AdKjcLlCrQkNJXNXdnYUD0t+eF+AE1v76rV0/qvTEo/8kkkGJq/yFLIKhPsgtgEszl8E4cdAxPHdllgDBwGZW9k6Fguaa9A4PtMEwkrDe0chhCPAZ/E5dNn/kPiWqGe5mVSH1rJCdze2w4rDNDsi/gdn/FPtb0KTfUmeyQenvuE45WCLQd6unsc3fwKeAw0yHX+Zwu247DpbB3emQv3R7x7du8GgybdtrKGc39Ty23rQnqfKk5y9wCwD1XACZJg56xGUMZFVhx1taytjPBnWAfuihyT+3TEiAQwC1Mhzmqwrr9QhbBoeJg36A6Ou0Y/kGe2qQ+mhiGspHDcODTZfs0eRr8fkE0Z4xpyGt4RJgTnX1carq8Jw9dhzv6BB5k+VJyK9t6+y8dNK74bGHMSHK00Scc/CC7fwC6MotAjX6GuqTzsTBkosYW/f9YKUnIb1OFiAW/c4Ce5Lq18jLKKnu5xaApTWBHn0n8Nz6ixhw4zvJ5HXlvU2R3gWui02XizwhrEznbTW9vQ64nUEckBUut13EQOHzFFUA70jErBv+09xcYrXHqUXK8H9qIXXapSs1dm4FN1SF95DdzlD72LMNUt/15CMvXT65NfzIRtQOq5FCv7jAHkPppdqDZ3YvZFZgY8WEQN8dvvFxpB8hLvWT3T8uyWxckG9CEfX38fk0ahGgmboMMIk/2xg5UJKbYZ62sf9RbI7UPxGJzLgT0R2Y/RM0z1HO+QZ6Gl/3+dh2Wmdb6HQwUJc9IfI6fPc40Z5xCLeW2wvw8Pfoy0B5mfoMAuYLn+7oKE0FxZqp+YvWTHugw24PvvtLIjZLh83cAghzmxHqASb5qntz/4EvsfEy7UHroepvJoKtWdUcPPKrVGwsA6k2FuYTAPXAGoC8RfYCStflqRvv3VuB4Hc1SI9bBJjAZ1VWe+p1+TqBHpfG+M8Ksa0EgLacAnhiETNzIPjdbztLPIfPWrME0CSkQ+UfxDFmkQ5v5RPAYcYBckFTcDfUWc+hwZsw06tA+EiOi5RoDns66ctA/Qm3AE4tuhYgZ5Zl9uPR32165PtlINoMwjM5jtPfSvn9WTe/iEufw7PUW+U3a2NSKZ8CTU0s+DyzHAJgq9yuNDaywxNtkQuVWaTDBqs5SIdsQt4hjsXOCvmvzrDu6Fdnebo3Hj3u69xXngoFqkH09KL3ie2BB6y2XCsfZNt1apnOqsL7uY/KoB57k+SDJRUhIZlX2iD4UJ4b5ef+3dqabY9hlunUdPt0XXyIryqs1yKVAv3qbPFuKNNedaAR5FeD4NE8AqRTwZ1ZmxqnHv0EcI4Rxz3hNqSqxThevrEXqpJq31IJgOD3TN3+h0tYmmPpLt9bJex80W4SRBzmEF7kE8Bhbo5aONwutwCx6K4JUVyByu/JfOTn+6EFAiTNN1uoAgxyC1BvqFcAZLJo8pr8rlvuq8wExfpFUl+u/s7/dt6R9UKkS5ergHeaOP6Yc2SQLw7Mqa6SDznsHakvzLAyoeAPCyRvVoXpUGCb1ZZqRWFnhdQXPWcg3Jac5App7C2MImf/5Kb+nupJ0X8FSL1NEOACEyyHPQ9QbWA73CIEkBuEIqrCzUO9CsNB6esCqQ8pAqD/Oe33l9vs2SLQd6svuhJSWW6GeVptLFKGbMD9eltjZ2cjw5m4o60ChF4lCvBeJhjIuntAYF4N3KNEO9Lwgmo+F/D5mNt1cbr/2OeD916qx+HSB4gCsDdNdmXZM7dbjRJtYXeZd/EJ4DDX3Q4uARLSj604yO23UgVA2jRy2EO+OkNX/w+fZNm8pw5QbAAAAABJRU5ErkJggg=="/> + </defs> + <style> + tspan { white-space:pre } + </style> + <use id="Background" href="#img1" x="0" y="0" /> +</svg> \ No newline at end of file diff --git a/src/components/auth/auth.vue b/src/components/auth/auth.vue new file mode 100644 index 0000000..ae010d4 --- /dev/null +++ b/src/components/auth/auth.vue @@ -0,0 +1,30 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; + +export default defineComponent({ + name: 'auth', + props: { + value: { + type: String, + default: () => '', + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 vuex 中的用户权限 + const getUserAuthBtnList = computed(() => { + return userInfos.value.authBtnList.some((v: string) => v === props.value); + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/auth/authAll.vue b/src/components/auth/authAll.vue new file mode 100644 index 0000000..76c5e01 --- /dev/null +++ b/src/components/auth/authAll.vue @@ -0,0 +1,31 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +export default defineComponent({ + name: 'authAll', + props: { + value: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 pinia 中的用户权限 + const getUserAuthBtnList = computed(() => { + return judementSameArr(props.value, userInfos.value.authBtnList); + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/auth/auths.vue b/src/components/auth/auths.vue new file mode 100644 index 0000000..ef31019 --- /dev/null +++ b/src/components/auth/auths.vue @@ -0,0 +1,36 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; + +export default defineComponent({ + name: 'auths', + props: { + value: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 vuex 中的用户权限 + const getUserAuthBtnList = computed(() => { + let flag = false; + userInfos.value.authBtnList.map((val: string) => { + props.value.map((v) => { + if (val === v) flag = true; + }); + }); + return flag; + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/cropper/index.vue b/src/components/cropper/index.vue new file mode 100644 index 0000000..b23a266 --- /dev/null +++ b/src/components/cropper/index.vue @@ -0,0 +1,149 @@ +<template> + <div> + <el-dialog title="更换头像" v-model="isShowDialog" width="769px"> + <div class="cropper-warp"> + <div class="cropper-warp-left"> + <img :src="cropperImg" class="cropper-warp-left-img" /> + </div> + <div class="cropper-warp-right"> + <div class="cropper-warp-right-title">预览</div> + <div class="cropper-warp-right-item"> + <div class="cropper-warp-right-value"> + <img :src="cropperImgBase64" class="cropper-warp-right-value-img" /> + </div> + <div class="cropper-warp-right-label">100 x 100</div> + </div> + <div class="cropper-warp-right-item"> + <div class="cropper-warp-right-value"> + <img :src="cropperImgBase64" class="cropper-warp-right-value-img cropper-size" /> + </div> + <div class="cropper-warp-right-label">50 x 50</div> + </div> + </div> + </div> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">更 换</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, nextTick, defineComponent } from 'vue'; +import Cropper from 'cropperjs'; +import 'cropperjs/dist/cropper.css'; + +export default defineComponent({ + name: 'cropperIndex', + setup() { + const state = reactive({ + isShowDialog: false, + cropperImg: '', + cropperImgBase64: '', + cropper: null, + }); + // 打开弹窗 + const openDialog = (imgs: any) => { + state.cropperImg = imgs; + state.isShowDialog = true; + nextTick(() => { + initCropper(); + }); + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 更换 + const onSubmit = () => { + // state.cropperImgBase64 = state.cropper.getCroppedCanvas().toDataURL('image/jpeg'); + }; + // 初始化cropperjs图片裁剪 + const initCropper = () => { + const letImg: any = document.querySelector('.cropper-warp-left-img'); + (<any>state.cropper) = new Cropper(letImg, { + viewMode: 1, + dragMode: 'none', + initialAspectRatio: 1, + aspectRatio: 1, + preview: '.before', + background: false, + autoCropArea: 0.6, + zoomOnWheel: false, + crop: () => { + state.cropperImgBase64 = (<any>state.cropper).getCroppedCanvas().toDataURL('image/jpeg'); + }, + }); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + initCropper, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.cropper-warp { + display: flex; + .cropper-warp-left { + position: relative; + display: inline-block; + height: 350px; + flex: 1; + border: 1px solid var(--el-border-color); + background: var(--el-color-white); + overflow: hidden; + background-repeat: no-repeat; + cursor: move; + border-radius: var(--el-border-radius-base); + .cropper-warp-left-img { + width: 100%; + height: 100%; + } + } + .cropper-warp-right { + width: 150px; + height: 350px; + .cropper-warp-right-title { + text-align: center; + height: 20px; + line-height: 20px; + } + .cropper-warp-right-item { + margin: 15px 0; + .cropper-warp-right-value { + display: flex; + .cropper-warp-right-value-img { + width: 100px; + height: 100px; + border-radius: var(--el-border-radius-circle); + margin: auto; + } + .cropper-size { + width: 50px; + height: 50px; + } + } + .cropper-warp-right-label { + text-align: center; + font-size: 12px; + color: var(--el-text-color-primary); + height: 30px; + line-height: 30px; + } + } + } +} +</style> diff --git a/src/components/editor/index.vue b/src/components/editor/index.vue new file mode 100644 index 0000000..78e5726 --- /dev/null +++ b/src/components/editor/index.vue @@ -0,0 +1,115 @@ +<template> + <div class="editor-container"> + <div ref="editorToolbar"></div> + <div ref="editorContent" :style="{ height }"></div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, watch, defineComponent } from 'vue'; +import { createEditor, createToolbar, IEditorConfig, IToolbarConfig, IDomEditor } from '@wangeditor/editor'; +import '@wangeditor/editor/dist/css/style.css'; +import { toolbarKeys } from './toolbar'; + +// 定义接口来定义对象的类型 +interface WangeditorState { + editorToolbar: HTMLDivElement | null; + editorContent: HTMLDivElement | null; + editor: any; +} + +export default defineComponent({ + name: 'wngEditor', + props: { + // 节点 id + id: { + type: String, + default: () => 'wangeditor', + }, + // 是否禁用 + isDisable: { + type: Boolean, + default: () => false, + }, + // 内容框默认 placeholder + placeholder: { + type: String, + default: () => '请输入内容', + }, + // 双向绑定:双向绑定值,字段名为固定,改了之后将不生效 + // 参考:https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5 + modelValue: String, + // https://www.wangeditor.com/v5/getting-started.html#mode-%E6%A8%A1%E5%BC%8F + // 模式,可选 <default|simple>,默认 default + mode: { + type: String, + default: () => 'default', + }, + // 高度 + height: { + type: String, + default: () => '310px', + }, + }, + setup(props, { emit }) { + const state = reactive<WangeditorState>({ + editorToolbar: null, + editor: null, + editorContent: null, + }); + // 富文本配置 + const wangeditorConfig = () => { + const editorConfig: Partial<IEditorConfig> = { MENU_CONF: {} }; + props.isDisable ? (editorConfig.readOnly = true) : (editorConfig.readOnly = false); + editorConfig.placeholder = props.placeholder; + editorConfig.onChange = (editor: IDomEditor) => { + // console.log('content', editor.children); + // console.log('html', editor.getHtml()); + emit('update:modelValue', editor.getHtml()); + }; + (<any>editorConfig).MENU_CONF['uploadImage'] = { + base64LimitSize: 10 * 1024 * 1024, + }; + return editorConfig; + }; + // + const toolbarConfig = () => { + const toolbarConfig: Partial<IToolbarConfig> = {}; + toolbarConfig.toolbarKeys = toolbarKeys; + return toolbarConfig; + }; + // 初始化富文本 + // https://www.wangeditor.com/ + const initWangeditor = () => { + state.editor = createEditor({ + html: props.modelValue, + selector: state.editorContent!, + config: wangeditorConfig(), + mode: props.mode, + }); + createToolbar({ + editor: state.editor, + selector: state.editorToolbar!, + mode: props.mode, + config: toolbarConfig(), + }); + }; + // 页面加载时 + onMounted(() => { + initWangeditor(); + }); + // 监听双向绑定值的改变 + // https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I + watch( + () => props.modelValue, + (value) => { + state.editor.clear(); + state.editor.dangerouslyInsertHtml(value); + } + ); + return { + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/components/editor/toolbar.ts b/src/components/editor/toolbar.ts new file mode 100644 index 0000000..14a9bf3 --- /dev/null +++ b/src/components/editor/toolbar.ts @@ -0,0 +1,60 @@ +/** + * 工具栏配置 + */ +export const toolbarKeys = [ + 'headerSelect', + 'blockquote', + '|', + 'bold', + 'underline', + 'italic', + { + key: 'group-more-style', + title: '更多', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>', + menuKeys: ['through', 'code', 'sup', 'sub', 'clearStyle'], + }, + 'color', + 'bgColor', + '|', + 'fontSize', + 'fontFamily', + 'lineHeight', + '|', + 'bulletedList', + 'numberedList', + 'todo', + { + key: 'group-justify', + title: '对齐', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>', + menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify'], + }, + { + key: 'group-indent', + title: '缩进', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>', + menuKeys: ['indent', 'delIndent'], + }, + '|', + 'emotion', + 'insertLink', + { + key: 'group-image', + title: '图片', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z"></path></svg>', + menuKeys: ['uploadImage'], + }, + 'insertTable', + 'codeBlock', + 'divider', + '|', + 'undo', + 'redo', + '|', + 'fullScreen', +]; diff --git a/src/components/iconSelector/index.vue b/src/components/iconSelector/index.vue new file mode 100644 index 0000000..07de786 --- /dev/null +++ b/src/components/iconSelector/index.vue @@ -0,0 +1,252 @@ +<template> + <div class="icon-selector w100 h100"> + <el-popover + placement="bottom" + :width="fontIconWidth" + trigger="click" + transition="el-zoom-in-top" + popper-class="icon-selector-popper" + @show="onPopoverShow" + > + <template #reference> + <el-input + v-model="fontIconSearch" + :placeholder="fontIconPlaceholder" + :clearable="clearable" + :disabled="disabled" + :size="size" + ref="inputWidthRef" + @clear="onClearFontIcon" + @focus="onIconFocus" + @blur="onIconBlur" + > + <template #prepend> + <SvgIcon + :name="fontIconPrefix === '' ? prepend : fontIconPrefix" + class="font14" + v-if="fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : fontIconPrefix?.indexOf('ele-') > -1" + /> + <i v-else :class="fontIconPrefix === '' ? prepend : fontIconPrefix" class="font14"></i> + </template> + </el-input> + </template> + <template #default> + <div class="icon-selector-warp"> + <div class="icon-selector-warp-title flex"> + <div class="flex-auto">{{ title }}</div> + <div class="icon-selector-warp-title-tab" v-if="type === 'all'"> + <span :class="{ 'span-active': fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">ali</span> + <span :class="{ 'span-active': fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">ele</span> + <span :class="{ 'span-active': fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">awe</span> + </div> + </div> + <div class="icon-selector-warp-row"> + <el-scrollbar ref="selectorScrollbarRef"> + <el-row :gutter="10" v-if="fontIconSheetsFilterList.length > 0"> + <el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" @click="onColClick(v)" v-for="(v, k) in fontIconSheetsFilterList" :key="k"> + <div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconPrefix === v }"> + <div class="flex-margin"> + <div class="icon-selector-warp-item-value"> + <SvgIcon :name="v" /> + </div> + </div> + </div> + </el-col> + </el-row> + <el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0" :description="emptyDescription"></el-empty> + </el-scrollbar> + </div> + </div> + </template> + </el-popover> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue'; +import initIconfont from '/@/utils/getStyleSheets'; + +export default defineComponent({ + name: 'iconSelector', + emits: ['update:modelValue', 'get', 'clear'], + props: { + // 输入框前置内容 + prepend: { + type: String, + default: () => 'ele-Pointer', + }, + // 输入框占位文本 + placeholder: { + type: String, + default: () => '请输入内容搜索图标或者选择图标', + }, + // 输入框占位文本 + size: { + type: String, + default: () => 'default', + }, + // 弹窗标题 + title: { + type: String, + default: () => '请选择图标', + }, + // icon 图标类型 + type: { + type: String, + default: () => 'ele', + }, + // 禁用 + disabled: { + type: Boolean, + default: () => false, + }, + // 是否可清空 + clearable: { + type: Boolean, + default: () => true, + }, + // 自定义空状态描述文字 + emptyDescription: { + type: String, + default: () => '无相关图标', + }, + // 双向绑定值,默认为 modelValue, + // 参考:https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5 + // 参考:https://v3.cn.vuejs.org/guide/component-custom-events.html#%E5%A4%9A%E4%B8%AA-v-model-%E7%BB%91%E5%AE%9A + modelValue: String, + }, + setup(props, { emit }) { + const inputWidthRef = ref(); + const selectorScrollbarRef = ref(); + const state = reactive({ + fontIconPrefix: '', + fontIconWidth: 0, + fontIconSearch: '', + fontIconTabsIndex: 0, + fontIconSheetsList: [], + fontIconPlaceholder: '', + fontIconType: 'ali', + fontIconShow: true, + }); + // 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值 + const onIconFocus = () => { + if (!props.modelValue) return false; + state.fontIconSearch = ''; + state.fontIconPlaceholder = props.modelValue; + }; + // 处理 input 失去焦点时,为空将清空 input 值,为点击选中图标时,将取原先值 + const onIconBlur = () => { + setTimeout(() => { + const icon = state.fontIconSheetsList.filter((icon: string) => icon === state.fontIconSearch); + if (icon.length <= 0) state.fontIconSearch = ''; + }, 300); + }; + // 处理 icon 双向绑定数值回显 + const initModeValueEcho = () => { + if (props.modelValue === '') return ((<string | undefined>state.fontIconPlaceholder) = props.placeholder); + (<string | undefined>state.fontIconPlaceholder) = props.modelValue; + (<string | undefined>state.fontIconPrefix) = props.modelValue; + }; + // 处理 icon type 类型为 all 时,类型 ali、ele、awe 回显问题 + const initFontIconTypeEcho = () => { + if ((<any>props.modelValue)?.indexOf('iconfont') > -1) onIconChange('ali'); + else if ((<any>props.modelValue)?.indexOf('ele-') > -1) onIconChange('ele'); + else if ((<any>props.modelValue)?.indexOf('fa') > -1) onIconChange('awe'); + else onIconChange('ali'); + }; + // 图标搜索及图标数据显示 + const fontIconSheetsFilterList = computed(() => { + if (!state.fontIconSearch) return state.fontIconSheetsList; + let search = state.fontIconSearch.trim().toLowerCase(); + return state.fontIconSheetsList.filter((item: any) => { + if (item.toLowerCase().indexOf(search) !== -1) return item; + }); + }); + // 获取 input 的宽度 + const getInputWidth = () => { + nextTick(() => { + state.fontIconWidth = inputWidthRef.value.$el.offsetWidth; + }); + }; + // 监听页面宽度改变 + const initResize = () => { + window.addEventListener('resize', () => { + getInputWidth(); + }); + }; + // 初始化数据 + const initFontIconData = async (type: string) => { + state.fontIconSheetsList = []; + if (type === 'ali') { + await initIconfont.ali().then((res: any) => { + // 阿里字体图标使用 `iconfont xxx` + state.fontIconSheetsList = res.map((i: string) => `iconfont ${i}`); + }); + } else if (type === 'ele') { + await initIconfont.ele().then((res: any) => { + state.fontIconSheetsList = res; + }); + } else if (type === 'awe') { + await initIconfont.awe().then((res: any) => { + // fontawesome字体图标使用 `fa xxx` + state.fontIconSheetsList = res.map((i: string) => `fa ${i}`); + }); + } + // 初始化 input 的 placeholder + // 参考(单项数据流):https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81 + state.fontIconPlaceholder = props.placeholder; + // 初始化双向绑定回显 + initModeValueEcho(); + }; + // 图标点击切换 + const onIconChange = (type: string) => { + state.fontIconType = type; + initFontIconData(type); + }; + // 获取当前点击的 icon 图标 + const onColClick = (v: any) => { + state.fontIconPlaceholder = v; + state.fontIconPrefix = v; + emit('get', state.fontIconPrefix); + emit('update:modelValue', state.fontIconPrefix); + }; + // 清空当前点击的 icon 图标 + const onClearFontIcon = () => { + state.fontIconPrefix = ''; + emit('clear', state.fontIconPrefix); + emit('update:modelValue', state.fontIconPrefix); + }; + // 监听 Popover 打开,用于双向绑定值回显 + const onPopoverShow = () => { + initModeValueEcho(); + initFontIconTypeEcho(); + }; + // 页面加载时 + onMounted(() => { + initModeValueEcho(); + initResize(); + getInputWidth(); + }); + + // 监听双向绑定 modelValue 的变化 + watch( + () => props.modelValue, + () => { + initModeValueEcho(); + } + ); + return { + inputWidthRef, + selectorScrollbarRef, + fontIconSheetsFilterList, + onColClick, + onIconChange, + onClearFontIcon, + onIconFocus, + onIconBlur, + onPopoverShow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/components/noticeBar/index.vue b/src/components/noticeBar/index.vue new file mode 100644 index 0000000..6a81bfd --- /dev/null +++ b/src/components/noticeBar/index.vue @@ -0,0 +1,195 @@ +<template> + <div class="notice-bar" :style="{ background, height: `${height}px` }" v-show="!isMode"> + <div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }"> + <i v-if="leftIcon" class="notice-bar-warp-left-icon" :class="leftIcon"></i> + <div class="notice-bar-warp-text-box" ref="noticeBarWarpRef"> + <div class="notice-bar-warp-text" ref="noticeBarTextRef" v-if="!scrollable">{{ text }}</div> + <div class="notice-bar-warp-slot" v-else><slot /></div> + </div> + <SvgIcon :name="rightIcon" v-if="rightIcon" class="notice-bar-warp-right-icon" @click="onRightIconClick" /> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, ref, onMounted, nextTick } from 'vue'; + +export default defineComponent({ + name: 'noticeBar', + props: { + // 通知栏模式,可选值为 closeable link + mode: { + type: String, + default: () => '', + }, + // 通知文本内容 + text: { + type: String, + default: () => '', + }, + // 通知文本颜色 + color: { + type: String, + default: () => 'var(--el-color-warning)', + }, + // 通知背景色 + background: { + type: String, + default: () => 'var(--el-color-warning-light-9)', + }, + // 字体大小,单位px + size: { + type: [Number, String], + default: () => 14, + }, + // 通知栏高度,单位px + height: { + type: Number, + default: () => 40, + }, + // 动画延迟时间 (s) + delay: { + type: Number, + default: () => 1, + }, + // 滚动速率 (px/s) + speed: { + type: Number, + default: () => 100, + }, + // 是否开启垂直滚动 + scrollable: { + type: Boolean, + default: () => false, + }, + // 自定义左侧图标 + leftIcon: { + type: String, + default: () => '', + }, + // 自定义右侧图标 + rightIcon: { + type: String, + default: () => '', + }, + }, + setup(props, { emit }) { + const noticeBarWarpRef = ref(); + const noticeBarTextRef = ref(); + const state = reactive({ + order: 1, + oneTime: 0, + twoTime: 0, + warpOWidth: 0, + textOWidth: 0, + isMode: false, + }); + // 初始化 animation 各项参数 + const initAnimation = () => { + nextTick(() => { + state.warpOWidth = noticeBarWarpRef.value.offsetWidth; + state.textOWidth = noticeBarTextRef.value.offsetWidth; + document.styleSheets[0].insertRule(`@keyframes oneAnimation {0% {left: 0px;} 100% {left: -${state.textOWidth}px;}}`); + document.styleSheets[0].insertRule(`@keyframes twoAnimation {0% {left: ${state.warpOWidth}px;} 100% {left: -${state.textOWidth}px;}}`); + computeAnimationTime(); + setTimeout(() => { + changeAnimation(); + }, props.delay * 1000); + }); + }; + // 计算 animation 滚动时长 + const computeAnimationTime = () => { + state.oneTime = state.textOWidth / props.speed; + state.twoTime = (state.textOWidth + state.warpOWidth) / props.speed; + }; + // 改变 animation 动画调用 + const changeAnimation = () => { + if (state.order === 1) { + noticeBarTextRef.value.style.cssText = `animation: oneAnimation ${state.oneTime}s linear; opactity: 1;}`; + state.order = 2; + } else { + noticeBarTextRef.value.style.cssText = `animation: twoAnimation ${state.twoTime}s linear infinite; opacity: 1;`; + } + }; + // 监听 animation 动画的结束 + const listenerAnimationend = () => { + noticeBarTextRef.value.addEventListener( + 'animationend', + () => { + changeAnimation(); + }, + false + ); + }; + // 右侧 icon 图标点击 + const onRightIconClick = () => { + if (!props.mode) return false; + if (props.mode === 'closeable') { + state.isMode = true; + emit('close'); + } else if (props.mode === 'link') { + emit('link'); + } + }; + // 页面加载时 + onMounted(() => { + if (props.scrollable) return false; + initAnimation(); + listenerAnimationend(); + }); + return { + noticeBarWarpRef, + noticeBarTextRef, + onRightIconClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.notice-bar { + padding: 0 15px; + width: 100%; + border-radius: 4px; + .notice-bar-warp { + display: flex; + align-items: center; + width: 100%; + height: inherit; + .notice-bar-warp-text-box { + flex: 1; + height: inherit; + display: flex; + align-items: center; + overflow: hidden; + position: relative; + .notice-bar-warp-text { + white-space: nowrap; + position: absolute; + left: 0; + } + .notice-bar-warp-slot { + width: 100%; + white-space: nowrap; + ::v-deep(.el-carousel__item) { + display: flex; + align-items: center; + } + } + } + .notice-bar-warp-left-icon { + width: 24px; + font-size: inherit !important; + } + .notice-bar-warp-right-icon { + width: 24px; + text-align: right; + font-size: inherit !important; + &:hover { + cursor: pointer; + } + } + } +} +</style> diff --git a/src/components/svgIcon/index.vue b/src/components/svgIcon/index.vue new file mode 100644 index 0000000..1fab298 --- /dev/null +++ b/src/components/svgIcon/index.vue @@ -0,0 +1,73 @@ +<template> + <i v-if="isShowIconSvg" class="el-icon" :style="setIconSvgStyle"> + <component :is="getIconName" /> + </i> + <div v-else-if="isShowIconImg" :style="setIconImgOutStyle"> + <img :src="getIconName" :style="setIconSvgInsStyle" /> + </div> + <i v-else :class="getIconName" :style="setIconSvgStyle" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'svgIcon', + props: { + // svg 图标组件名字 + name: { + type: String, + }, + // svg 大小 + size: { + type: Number, + default: () => 14, + }, + // svg 颜色 + color: { + type: String, + }, + }, + setup(props) { + // 在线链接、本地引入地址前缀 + const linesString = ['https', 'http', '/src', '/assets', import.meta.env.VITE_PUBLIC_PATH]; + + // 获取 icon 图标名称 + const getIconName = computed(() => { + return props?.name; + }); + // 用于判断 element plus 自带 svg 图标的显示、隐藏 + const isShowIconSvg = computed(() => { + return props?.name?.startsWith('ele-'); + }); + // 用于判断在线链接、本地引入等图标显示、隐藏 + const isShowIconImg = computed(() => { + return linesString.find((str) => props.name?.startsWith(str)); + }); + // 设置图标样式 + const setIconSvgStyle = computed(() => { + return `font-size: ${props.size}px;color: ${props.color};`; + }); + // 设置图片样式 + const setIconImgOutStyle = computed(() => { + return `width: ${props.size}px;height: ${props.size}px;display: inline-block;overflow: hidden;`; + }); + // 设置图片样式 + // https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0 + const setIconSvgInsStyle = computed(() => { + const filterStyle: string[] = []; + const compatibles: string[] = ['-webkit', '-ms', '-o', '-moz']; + compatibles.forEach((j) => filterStyle.push(`${j}-filter: drop-shadow(${props.color} 30px 0);`)); + return `width: ${props.size}px;height: ${props.size}px;position: relative;left: -${props.size}px;${filterStyle.join('')}`; + }); + return { + getIconName, + isShowIconSvg, + isShowIconImg, + setIconSvgStyle, + setIconImgOutStyle, + setIconSvgInsStyle, + }; + }, +}); +</script> diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..a45e72c --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,67 @@ +import { createI18n } from 'vue-i18n'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import zhcnLocale from 'element-plus/lib/locale/lang/zh-cn'; +import enLocale from 'element-plus/lib/locale/lang/en'; +import zhtwLocale from 'element-plus/lib/locale/lang/zh-tw'; + +import nextZhcn from '/@/i18n/lang/zh-cn'; +import nextEn from '/@/i18n/lang/en'; +import nextZhtw from '/@/i18n/lang/zh-tw'; + +import pagesLoginZhcn from '/@/i18n/pages/login/zh-cn'; +import pagesLoginEn from '/@/i18n/pages/login/en'; +import pagesLoginZhtw from '/@/i18n/pages/login/zh-tw'; +import pagesFormI18nZhcn from '/@/i18n/pages/formI18n/zh-cn'; +import pagesFormI18nEn from '/@/i18n/pages/formI18n/en'; +import pagesFormI18nZhtw from '/@/i18n/pages/formI18n/zh-tw'; + +// 定义语言国际化内容 +/** + * 说明: + * /src/i18n/lang 下的 ts 为框架的国际化内容 + * /src/i18n/pages 下的 ts 为各界面的国际化内容 + */ +const messages = { + [zhcnLocale.name]: { + ...zhcnLocale, + message: { + ...nextZhcn, + ...pagesLoginZhcn, + ...pagesFormI18nZhcn, + }, + }, + [enLocale.name]: { + ...enLocale, + message: { + ...nextEn, + ...pagesLoginEn, + ...pagesFormI18nEn, + }, + }, + [zhtwLocale.name]: { + ...zhtwLocale, + message: { + ...nextZhtw, + ...pagesLoginZhtw, + ...pagesFormI18nZhtw, + }, + }, +}; + +// 读取 pinia 默认语言 +const stores = useThemeConfig(pinia); +const { themeConfig } = storeToRefs(stores); + +// 导出语言国际化 +// https://vue-i18n.intlify.dev/guide/essentials/fallback.html#explicit-fallback-with-one-locale +export const i18n = createI18n({ + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true, + fallbackWarn: false, + locale: themeConfig.value.globalI18n, + fallbackLocale: zhcnLocale.name, + messages, +}); diff --git a/src/i18n/lang/en.ts b/src/i18n/lang/en.ts new file mode 100644 index 0000000..46ae830 --- /dev/null +++ b/src/i18n/lang/en.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: 'home', + system: 'system', + systemMenu: 'systemMenu', + systemRole: 'systemRole', + systemUser: 'systemUser', + systemDept: 'systemDept', + systemDic: 'systemDic', + limits: 'limits', + limitsFrontEnd: 'FrontEnd', + limitsFrontEndPage: 'FrontEndPage', + limitsFrontEndBtn: 'FrontEndBtn', + limitsBackEnd: 'BackEnd', + limitsBackEndEndPage: 'BackEndEndPage', + menu: 'menu', + menu1: 'menu1', + menu11: 'menu11', + menu12: 'menu12', + menu121: 'menu121', + menu122: 'menu122', + menu13: 'menu13', + menu2: 'menu2', + funIndex: 'function', + funTagsView: 'funTagsView', + funCountup: 'countup', + funWangEditor: 'wangEditor', + funCropper: 'cropper', + funQrcode: 'qrcode', + funEchartsMap: 'EchartsMap', + funPrintJs: 'PrintJs', + funClipboard: 'Copy cut', + funGridLayout: 'Drag layout', + funSplitpanes: 'Pane splitter', + funDragVerify: 'Validator', + pagesIndex: 'pages', + pagesFiltering: 'Filtering', + pagesFilteringDetails: 'FilteringDetails', + pagesFilteringDetails1: 'FilteringDetails1', + pagesIocnfont: 'iconfont icon', + pagesElement: 'element icon', + pagesAwesome: 'awesome icon', + pagesFormAdapt: 'FormAdapt', + pagesTableRules: 'pagesTableRules', + pagesFormI18n: 'FormI18n', + pagesFormRules: 'Multi form validation', + pagesDynamicForm: 'Dynamic complex form', + pagesWorkflow: 'Workflow', + pagesListAdapt: 'ListAdapt', + pagesWaterfall: 'Waterfall', + pagesSteps: 'Steps', + pagesPreview: 'Large preview', + pagesWaves: 'Wave effect', + pagesTree: 'tree alter table', + pagesDrag: 'Drag command', + pagesLazyImg: 'Image lazy loading', + makeIndex: 'makeIndex', + makeSelector: 'Icon selector', + makeNoticeBar: 'notification bar', + makeSvgDemo: 'Svgicon demo', + paramsIndex: 'Routing parameters', + paramsCommon: 'General routing', + paramsDynamic: 'Dynamic routing', + paramsCommonDetails: 'General routing details', + paramsDynamicDetails: 'Dynamic routing details', + chartIndex: 'chartIndex', + visualizingIndex: 'visualizingIndex', + visualizingLinkDemo1: 'visualizingLinkDemo1', + visualizingLinkDemo2: 'visualizingLinkDemo2', + personal: 'personal', + tools: 'tools', + layoutLinkView: 'LinkView', + layoutIfameView: 'IfameView', + }, + staticRoutes: { + signIn: 'signIn', + notFound: 'notFound', + noPower: 'noPower', + }, + user: { + title0: 'Component size', + title1: 'Language switching', + title2: 'Menu search', + title3: 'Layout configuration', + title4: 'news', + title5: 'Full screen on', + title6: 'Full screen off', + dropdownLarge: 'large', + dropdownDefault: 'default', + dropdownSmall: 'small', + dropdown1: 'home page', + dropdown2: 'Personal Center', + dropdown3: '404', + dropdown4: '401', + dropdown5: 'Log out', + dropdown6: 'Code warehouse', + searchPlaceholder: 'Menu search: support Chinese, routing path', + newTitle: 'notice', + newBtn: 'All read', + newGo: 'Go to the notification center', + newDesc: 'No notice', + logOutTitle: 'Tips', + logOutMessage: 'This operation will log out. Do you want to continue?', + logOutConfirm: 'determine', + logOutCancel: 'cancel', + logOutExit: 'Exiting', + }, + tagsView: { + refresh: 'refresh', + close: 'close', + closeOther: 'closeOther', + closeAll: 'closeAll', + fullscreen: 'fullscreen', + closeFullscreen: 'closeFullscreen', + }, + notFound: { + foundTitle: 'Wrong address input, please re-enter the address~', + foundMsg: 'You can check the web address first, and then re-enter or give us feedback.', + foundBtn: 'Back to home page', + }, + noAccess: { + accessTitle: 'You are not authorized to operate~', + accessMsg: 'Contact information: add QQ group discussion 665452019', + accessBtn: 'Reauthorization', + }, + layout: { + configTitle: 'Layout configuration', + oneTitle: 'Global Themes', + twoTopTitle: 'top bar set up', + twoMenuTitle: 'Menu set up', + twoColumnsTitle: 'Columns set up', + twoTopBar: 'Top bar background', + twoTopBarColor: 'Top bar default font color', + twoIsTopBarColorGradual: 'Top bar gradient', + twoMenuBar: 'Menu background', + twoMenuBarColor: 'Menu default font color', + twoIsMenuBarColorGradual: 'Menu gradient', + twoColumnsMenuBar: 'Column menu background', + twoColumnsMenuBarColor: 'Default font color bar menu', + twoIsColumnsMenuBarColorGradual: 'Column gradient', + threeTitle: 'Interface settings', + threeIsCollapse: 'Menu horizontal collapse', + threeIsUniqueOpened: 'Menu accordion', + threeIsFixedHeader: 'Fixed header', + threeIsClassicSplitMenu: 'Classic layout split menu', + threeIsLockScreen: 'Open the lock screen', + threeLockScreenTime: 'screen locking(s/s)', + fourTitle: 'Interface display', + fourIsShowLogo: 'Sidebar logo', + fourIsBreadcrumb: 'Open breadcrumb', + fourIsBreadcrumbIcon: 'Open breadcrumb icon', + fourIsTagsview: 'Open tagsview', + fourIsTagsviewIcon: 'Open tagsview Icon', + fourIsCacheTagsView: 'Enable tagsview cache', + fourIsSortableTagsView: 'Enable tagsview drag', + fourIsShareTagsView: 'Enable tagsview sharing', + fourIsFooter: 'Open footer', + fourIsGrayscale: 'Grey model', + fourIsInvert: 'Color weak mode', + fourIsDark: 'Dark Mode', + fourIsWartermark: 'Turn on watermark', + fourWartermarkText: 'Watermark copy', + fiveTitle: 'Other settings', + fiveTagsStyle: 'Tagsview style', + fiveAnimation: 'page animation', + fiveColumnsAsideStyle: 'Column style', + fiveColumnsAsideLayout: 'Column layout', + sixTitle: 'Layout switch', + sixDefaults: 'One', + sixClassic: 'Two', + sixTransverse: 'Three', + sixColumns: 'Four', + tipText: 'Click the button below to copy the layout configuration to `/src/stores/themeConfig.ts` It has been modified in.', + copyText: 'replication configuration', + resetText: 'restore default', + copyTextSuccess: 'Copy succeeded!', + copyTextError: 'Copy failed!', + }, +}; diff --git a/src/i18n/lang/zh-cn.ts b/src/i18n/lang/zh-cn.ts new file mode 100644 index 0000000..79ef328 --- /dev/null +++ b/src/i18n/lang/zh-cn.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: '首页', + system: '系统设置', + systemMenu: '菜单管理', + systemRole: '角色管理', + systemUser: '用户管理', + systemDept: '部门管理', + systemDic: '字典管理', + limits: '权限管理', + limitsFrontEnd: '前端控制', + limitsFrontEndPage: '页面权限', + limitsFrontEndBtn: '按钮权限', + limitsBackEnd: '后端控制', + limitsBackEndEndPage: '页面权限', + menu: '菜单嵌套', + menu1: '菜单1', + menu11: '菜单11', + menu12: '菜单12', + menu121: '菜单121', + menu122: '菜单122', + menu13: '菜单13', + menu2: '菜单2', + funIndex: '功能', + funTagsView: 'tagsView 操作', + funCountup: '数字滚动', + funWangEditor: 'Editor 编辑器', + funCropper: '图片裁剪', + funQrcode: '二维码生成', + funEchartsMap: '地理坐标/地图', + funPrintJs: '页面打印', + funClipboard: '复制剪切', + funGridLayout: '拖拽布局', + funSplitpanes: '窗格拆分器', + funDragVerify: '验证器', + pagesIndex: '页面', + pagesFiltering: '过滤筛选组件', + pagesFilteringDetails: '过滤筛选组件详情', + pagesFilteringDetails1: '过滤筛选组件详情111', + pagesIocnfont: 'ali 字体图标', + pagesElement: 'ele 字体图标', + pagesAwesome: 'awe 字体图标', + pagesFormAdapt: '表单自适应', + pagesTableRules: '表单表格验证', + pagesFormI18n: '表单国际化', + pagesFormRules: '多表单验证', + pagesDynamicForm: '动态复杂表单', + pagesWorkflow: '工作流', + pagesListAdapt: '列表自适应', + pagesWaterfall: '瀑布屏', + pagesSteps: '步骤条', + pagesPreview: '大图预览', + pagesWaves: '波浪效果', + pagesTree: '树形改表格', + pagesDrag: '拖动指令', + pagesLazyImg: '图片懒加载', + makeIndex: '组件封装', + makeSelector: '图标选择器', + makeNoticeBar: '滚动通知栏', + makeSvgDemo: 'svgIcon 演示', + paramsIndex: '路由参数', + paramsCommon: '普通路由', + paramsDynamic: '动态路由', + paramsCommonDetails: '普通路由详情', + paramsDynamicDetails: '动态路由详情', + chartIndex: '大数据图表', + visualizingIndex: '数据可视化', + visualizingLinkDemo1: '数据可视化演示1', + visualizingLinkDemo2: '数据可视化演示2', + personal: '个人中心', + tools: '工具类集合', + layoutLinkView: '外链', + layoutIfameView: '内嵌 iframe', + }, + staticRoutes: { + signIn: '登录', + notFound: '找不到此页面', + noPower: '没有权限', + }, + user: { + title0: '组件大小', + title1: '语言切换', + title2: '菜单搜索', + title3: '布局配置', + title4: '消息', + title5: '开全屏', + title6: '关全屏', + dropdownLarge: '大型', + dropdownDefault: '默认', + dropdownSmall: '小型', + dropdown1: '首页', + dropdown2: '个人中心', + dropdown3: '404', + dropdown4: '401', + dropdown5: '退出登录', + dropdown6: '代码仓库', + searchPlaceholder: '菜单搜索:支持中文、路由路径', + newTitle: '通知', + newBtn: '全部已读', + newGo: '前往通知中心', + newDesc: '暂无通知', + logOutTitle: '提示', + logOutMessage: '此操作将退出登录, 是否继续?', + logOutConfirm: '确定', + logOutCancel: '取消', + logOutExit: '退出中', + }, + tagsView: { + refresh: '刷新', + close: '关闭', + closeOther: '关闭其它', + closeAll: '全部关闭', + fullscreen: '当前页全屏', + closeFullscreen: '关闭全屏', + }, + notFound: { + foundTitle: '地址输入错误,请重新输入地址~', + foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。', + foundBtn: '返回首页', + }, + noAccess: { + accessTitle: '您未被授权,没有操作权限~', + accessMsg: '联系方式:加QQ群探讨 665452019', + accessBtn: '重新授权', + }, + layout: { + configTitle: '布局配置', + oneTitle: '全局主题', + twoTopTitle: '顶栏设置', + twoMenuTitle: '菜单设置', + twoColumnsTitle: '分栏设置', + twoTopBar: '顶栏背景', + twoTopBarColor: '顶栏默认字体颜色', + twoIsTopBarColorGradual: '顶栏背景渐变', + twoMenuBar: '菜单背景', + twoMenuBarColor: '菜单默认字体颜色', + twoIsMenuBarColorGradual: '菜单背景渐变', + twoColumnsMenuBar: '分栏菜单背景', + twoColumnsMenuBarColor: '分栏菜单默认字体颜色', + twoIsColumnsMenuBarColorGradual: '分栏菜单背景渐变', + threeTitle: '界面设置', + threeIsCollapse: '菜单水平折叠', + threeIsUniqueOpened: '菜单手风琴', + threeIsFixedHeader: '固定 Header', + threeIsClassicSplitMenu: '经典布局分割菜单', + threeIsLockScreen: '开启锁屏', + threeLockScreenTime: '自动锁屏(s/秒)', + fourTitle: '界面显示', + fourIsShowLogo: '侧边栏 Logo', + fourIsBreadcrumb: '开启 Breadcrumb', + fourIsBreadcrumbIcon: '开启 Breadcrumb 图标', + fourIsTagsview: '开启 Tagsview', + fourIsTagsviewIcon: '开启 Tagsview 图标', + fourIsCacheTagsView: '开启 TagsView 缓存', + fourIsSortableTagsView: '开启 TagsView 拖拽', + fourIsShareTagsView: '开启 TagsView 共用', + fourIsFooter: '开启 Footer', + fourIsGrayscale: '灰色模式', + fourIsInvert: '色弱模式', + fourIsDark: '深色模式', + fourIsWartermark: '开启水印', + fourWartermarkText: '水印文案', + fiveTitle: '其它设置', + fiveTagsStyle: 'Tagsview 风格', + fiveAnimation: '主页面切换动画', + fiveColumnsAsideStyle: '分栏高亮风格', + fiveColumnsAsideLayout: '分栏布局风格', + sixTitle: '布局切换', + sixDefaults: '默认', + sixClassic: '经典', + sixTransverse: '横向', + sixColumns: '分栏', + tipText: '点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。', + copyText: '一键复制配置', + resetText: '一键恢复默认', + copyTextSuccess: '复制成功!', + copyTextError: '复制失败!', + }, +}; diff --git a/src/i18n/lang/zh-tw.ts b/src/i18n/lang/zh-tw.ts new file mode 100644 index 0000000..d900abb --- /dev/null +++ b/src/i18n/lang/zh-tw.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: '首頁', + system: '系統設置', + systemMenu: '選單管理', + systemRole: '角色管理', + systemUser: '用戶管理', + systemDept: '部門管理', + systemDic: '字典管理', + limits: '許可權管理', + limitsFrontEnd: '前端控制', + limitsFrontEndPage: '頁面許可權', + limitsFrontEndBtn: '按鈕許可權', + limitsBackEnd: '後端控制', + limitsBackEndEndPage: '頁面許可權', + menu: '選單嵌套', + menu1: '選單1', + menu11: '選單11', + menu12: '選單12', + menu121: '選單121', + menu122: '選單122', + menu13: '選單13', + menu2: '選單2', + funIndex: '功能', + funTagsView: 'tagsView 操作', + funCountup: '數位滾動', + funWangEditor: 'Editor 編輯器', + funCropper: '圖片裁剪', + funQrcode: '二維碼生成', + funEchartsMap: '地理座標/地圖', + funPrintJs: '頁面列印', + funClipboard: '複製剪切', + funGridLayout: '拖拽佈局', + funSplitpanes: '窗格折開器', + funDragVerify: '驗證器', + pagesIndex: '頁面', + pagesFiltering: '過濾篩選組件', + pagesFilteringDetails: '過濾篩選組件詳情', + pagesFilteringDetails1: '過濾篩選組件詳情111', + pagesIocnfont: 'ali 字體圖標', + pagesElement: 'ele 字體圖標', + pagesAwesome: 'awe 字體圖標', + pagesFormAdapt: '表單自我調整', + pagesTableRules: '表單表格驗證', + pagesFormI18n: '表單國際化', + pagesFormRules: '多表單驗證', + pagesDynamicForm: '動態複雜表單', + pagesWorkflow: '工作流', + pagesListAdapt: '清單自我調整', + pagesWaterfall: '瀑布屏', + pagesSteps: '步驟條', + pagesPreview: '大圖預覽', + pagesWaves: '波浪效果', + pagesTree: '樹形改表格', + pagesDrag: '拖動指令', + pagesLazyImg: '圖片懶加載', + makeIndex: '組件封裝', + makeSelector: '圖標選擇器', + makeNoticeBar: '滾動通知欄', + makeSvgDemo: 'svgIcon 演示', + paramsIndex: '路由參數', + paramsCommon: '普通路由', + paramsDynamic: '動態路由', + paramsCommonDetails: '普通路由詳情', + paramsDynamicDetails: '動態路由詳情', + chartIndex: '大資料圖表', + visualizingIndex: '數據視覺化', + visualizingLinkDemo1: '數據視覺化演示1', + visualizingLinkDemo2: '數據視覺化演示2', + personal: '個人中心', + tools: '工具類集合', + layoutLinkView: '外鏈', + layoutIfameView: '内嵌 iframe', + }, + staticRoutes: { + signIn: '登入', + notFound: '找不到此頁面', + noPower: '沒有許可權', + }, + user: { + title0: '組件大小', + title1: '語言切換', + title2: '選單蒐索', + title3: '佈局配寘', + title4: '消息', + title5: '開全屏', + title6: '關全屏', + dropdownLarge: '大型', + dropdownDefault: '默認', + dropdownSmall: '小型', + dropdown1: '首頁', + dropdown2: '個人中心', + dropdown3: '404', + dropdown4: '401', + dropdown5: '登出', + dropdown6: '程式碼倉庫', + searchPlaceholder: '選單蒐索:支援中文、路由路徑', + newTitle: '通知', + newBtn: '全部已讀', + newGo: '前往通知中心', + newDesc: '暫無通知', + logOutTitle: '提示', + logOutMessage: '此操作將登出,是否繼續?', + logOutConfirm: '確定', + logOutCancel: '取消', + logOutExit: '退出中', + }, + tagsView: { + refresh: '重繪', + close: '關閉', + closeOther: '關閉其它', + closeAll: '全部關閉', + fullscreen: '當前頁全屏', + closeFullscreen: '關閉全屏', + }, + notFound: { + foundTitle: '地址輸入錯誤,請重新輸入地址~', + foundMsg: '您可以先檢查網址,然後重新輸入或給我們迴響問題。', + foundBtn: '返回首頁', + }, + noAccess: { + accessTitle: '您未被授權,沒有操作許可權~', + accessMsg: '聯繫方式:加QQ群探討665452019', + accessBtn: '重新授權', + }, + layout: { + configTitle: '佈局配寘', + oneTitle: '全域主題', + twoTopTitle: '頂欄設定', + twoMenuTitle: '選單設定', + twoColumnsTitle: '分欄設定', + twoTopBar: '頂欄背景', + twoTopBarColor: '頂欄默認字體顏色', + twoIsTopBarColorGradual: '頂欄背景漸變', + twoMenuBar: '選單背景', + twoMenuBarColor: '選單默認字體顏色', + twoIsMenuBarColorGradual: '選單背景漸變', + twoColumnsMenuBar: '分欄選單背景', + twoColumnsMenuBarColor: '分欄選單默認字體顏色', + twoIsColumnsMenuBarColorGradual: '分欄選單背景漸變', + threeTitle: '介面設定', + threeIsCollapse: '選單水准折疊', + threeIsUniqueOpened: '選單手風琴', + threeIsFixedHeader: '固定 Header', + threeIsClassicSplitMenu: '經典佈局分割選單', + threeIsLockScreen: '開啟鎖屏', + threeLockScreenTime: '自動鎖屏(s/秒)', + fourTitle: '介面顯示', + fourIsShowLogo: '側邊欄 Logo', + fourIsBreadcrumb: '開啟 Breadcrumb', + fourIsBreadcrumbIcon: '開啟 Breadcrumb 圖標', + fourIsTagsview: '開啟 Tagsview', + fourIsTagsviewIcon: '開啟 Tagsview 圖標', + fourIsCacheTagsView: '開啟 TagsView 緩存', + fourIsSortableTagsView: '開啟 TagsView 拖拽', + fourIsShareTagsView: '開啟 TagsView 共用', + fourIsFooter: '開啟 Footer', + fourIsGrayscale: '灰色模式', + fourIsInvert: '色弱模式', + fourIsDark: '深色模式', + fourIsWartermark: '開啟浮水印', + fourWartermarkText: '浮水印文案', + fiveTitle: '其它設定', + fiveTagsStyle: 'Tagsview 風格', + fiveAnimation: '主頁面切換動畫', + fiveColumnsAsideStyle: '分欄高亮風格', + fiveColumnsAsideLayout: '分欄佈局風格', + sixTitle: '佈局切換', + sixDefaults: '默認', + sixClassic: '經典', + sixTransverse: '橫向', + sixColumns: '分欄', + tipText: '點擊下方按鈕,複製佈局配寘去`src/stores/themeConfig.ts`中修改。', + copyText: '一鍵複製配寘', + resetText: '一鍵恢復默認', + copyTextSuccess: '複製成功!', + copyTextError: '複製失敗!', + }, +}; diff --git a/src/i18n/pages/formI18n/en.ts b/src/i18n/pages/formI18n/en.ts new file mode 100644 index 0000000..b3c54d6 --- /dev/null +++ b/src/i18n/pages/formI18n/en.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: 'name', + email: 'email', + autograph: 'autograph', + }, + formI18nPlaceholder: { + name: 'Please enter your name', + email: 'Please enter the users Department', + autograph: 'Please enter the login account name', + }, +}; diff --git a/src/i18n/pages/formI18n/zh-cn.ts b/src/i18n/pages/formI18n/zh-cn.ts new file mode 100644 index 0000000..0bed3ec --- /dev/null +++ b/src/i18n/pages/formI18n/zh-cn.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: '姓名', + email: '用户归属部门', + autograph: '登陆账户名', + }, + formI18nPlaceholder: { + name: '请输入姓名', + email: '请输入用户归属部门', + autograph: '请输入登陆账户名', + }, +}; diff --git a/src/i18n/pages/formI18n/zh-tw.ts b/src/i18n/pages/formI18n/zh-tw.ts new file mode 100644 index 0000000..393ac03 --- /dev/null +++ b/src/i18n/pages/formI18n/zh-tw.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: '姓名', + email: '用戶歸屬部門', + autograph: '登入帳戶名', + }, + formI18nPlaceholder: { + name: '請輸入姓名', + email: '請輸入用戶歸屬部門', + autograph: '請輸入登入帳戶名', + }, +}; diff --git a/src/i18n/pages/login/en.ts b/src/i18n/pages/login/en.ts new file mode 100644 index 0000000..2654a18 --- /dev/null +++ b/src/i18n/pages/login/en.ts @@ -0,0 +1,29 @@ +// 定义内容 +export default { + label: { + one1: 'User name login', + two2: 'Mobile number', + }, + link: { + one3: 'Third party login', + two4: 'Links', + }, + account: { + accountPlaceholder1: 'The user name admin or not is common', + accountPlaceholder2: 'Password: 123456', + accountPlaceholder3: 'Please enter the verification code', + accountBtnText: 'Sign in', + }, + mobile: { + placeholder1: 'Please input mobile phone number', + placeholder2: 'Please enter the verification code', + codeText: 'Get code', + btnText: 'Sign in', + msgText: + 'Warm tip: it is recommended to use Google, Microsoft edge, version 79.0.1072.62 and above browsers, and 360 browser, please use speed mode', + }, + scan: { + text: 'Open the mobile phone to scan and quickly log in / register', + }, + signInText: 'welcome back!', +}; diff --git a/src/i18n/pages/login/zh-cn.ts b/src/i18n/pages/login/zh-cn.ts new file mode 100644 index 0000000..3367b53 --- /dev/null +++ b/src/i18n/pages/login/zh-cn.ts @@ -0,0 +1,28 @@ +// 定义内容 +export default { + label: { + one1: '用户名登录', + two2: '手机号登录', + }, + link: { + one3: '第三方登录', + two4: '友情链接', + }, + account: { + accountPlaceholder1: '用户名 admin 或不输均为 common', + accountPlaceholder2: '密码:123456', + accountPlaceholder3: '请输入验证码', + accountBtnText: '登 录', + }, + mobile: { + placeholder1: '请输入手机号', + placeholder2: '请输入验证码', + codeText: '获取验证码', + btnText: '登 录', + msgText: '* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式', + }, + scan: { + text: '打开手机扫一扫,快速登录/注册', + }, + signInText: '欢迎回来!', +}; diff --git a/src/i18n/pages/login/zh-tw.ts b/src/i18n/pages/login/zh-tw.ts new file mode 100644 index 0000000..138e8c8 --- /dev/null +++ b/src/i18n/pages/login/zh-tw.ts @@ -0,0 +1,28 @@ +// 定义内容 +export default { + label: { + one1: '用戶名登入', + two2: '手機號登入', + }, + link: { + one3: '協力廠商登入', + two4: '友情連結', + }, + account: { + accountPlaceholder1: '用戶名admin或不輸均為common', + accountPlaceholder2: '密碼:123456', + accountPlaceholder3: '請輸入驗證碼', + accountBtnText: '登入', + }, + mobile: { + placeholder1: '請輸入手機號', + placeholder2: '請輸入驗證碼', + codeText: '獲取驗證碼', + btnText: '登入', + msgText: '* 溫馨提示:建議使用穀歌、Microsoft Edge,版本79.0.1072.62及以上瀏覽器,360瀏覽器請使用極速模式', + }, + scan: { + text: '打開手機掃一掃,快速登錄/注册', + }, + signInText: '歡迎回來!', +}; diff --git a/src/layout/component/aside.vue b/src/layout/component/aside.vue new file mode 100644 index 0000000..d4ee363 --- /dev/null +++ b/src/layout/component/aside.vue @@ -0,0 +1,163 @@ +<template> + <div class="h100" v-show="!isTagsViewCurrenFull"> + <el-aside class="layout-aside" :class="setCollapseStyle"> + <Logo v-if="setShowLogo" /> + <el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef" @mouseenter="onAsideEnterLeave(true)" @mouseleave="onAsideEnterLeave(false)"> + <Vertical :menuList="menuList" /> + </el-scrollbar> + </el-aside> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, watch, getCurrentInstance, onBeforeMount, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import Logo from '/@/layout/logo/index.vue'; +import Vertical from '/@/layout/navMenu/vertical.vue'; + +export default defineComponent({ + name: 'layoutAside', + components: { Logo, Vertical }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { routesList } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const state = reactive({ + menuList: [], + clientWidth: 0, + }); + // 设置菜单展开/收起时的宽度 + const setCollapseStyle = computed(() => { + const { layout, isCollapse, menuBar } = themeConfig.value; + const asideBrTheme = ['#FFFFFF', '#FFF', '#fff', '#ffffff']; + const asideBrColor = asideBrTheme.includes(menuBar) ? 'layout-el-aside-br-color' : ''; + // 判断是否是手机端 + if (state.clientWidth <= 1000) { + if (isCollapse) { + document.body.setAttribute('class', 'el-popup-parent--hidden'); + const asideEle = document.querySelector('.layout-container') as HTMLElement; + const modeDivs = document.createElement('div'); + modeDivs.setAttribute('class', 'layout-aside-mobile-mode'); + asideEle.appendChild(modeDivs); + modeDivs.addEventListener('click', closeLayoutAsideMobileMode); + return [asideBrColor, 'layout-aside-mobile', 'layout-aside-mobile-open']; + } else { + // 关闭弹窗 + closeLayoutAsideMobileMode(); + return [asideBrColor, 'layout-aside-mobile', 'layout-aside-mobile-close']; + } + } else { + if (layout === 'columns') { + // 分栏布局,菜单收起时宽度给 1px + if (isCollapse) return [asideBrColor, 'layout-aside-pc-1']; + else return [asideBrColor, 'layout-aside-pc-220']; + } else { + // 其它布局给 64px + if (isCollapse) return [asideBrColor, 'layout-aside-pc-64']; + else return [asideBrColor, 'layout-aside-pc-220']; + } + } + }); + // 关闭移动端蒙版 + const closeLayoutAsideMobileMode = () => { + const el = document.querySelector('.layout-aside-mobile-mode'); + el?.setAttribute('style', 'animation: error-img-two 0.3s'); + setTimeout(() => { + el?.parentNode?.removeChild(el); + }, 300); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) themeConfig.value.isCollapse = false; + document.body.setAttribute('class', ''); + }; + // 设置显示/隐藏 logo + const setShowLogo = computed(() => { + let { layout, isShowLogo } = themeConfig.value; + return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns'); + }); + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + if (themeConfig.value.layout === 'columns') return false; + (state.menuList as any) = filterRoutesFun(routesList.value); + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 设置菜单导航是否固定(移动端) + const initMenuFixed = (clientWidth: number) => { + state.clientWidth = clientWidth; + }; + // 鼠标移入、移出 + const onAsideEnterLeave = (bool: Boolean) => { + let { layout } = themeConfig.value; + if (layout !== 'columns') return false; + if (!bool) proxy.mittBus.emit('restoreDefault'); + stores.setColumnsMenuHover(bool); + }; + // 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度 + watch(themeConfig.value, (val) => { + if (val.isShowLogoChange !== val.isShowLogo) { + if (!proxy.$refs.layoutAsideScrollbarRef) return false; + proxy.$refs.layoutAsideScrollbarRef.update(); + } + }); + // 监听vuex值的变化,动态赋值给菜单中 + watch( + pinia.state, + (val) => { + let { layout, isClassicSplitMenu } = val.themeConfig.themeConfig; + if (layout === 'classic' && isClassicSplitMenu) return false; + setFilterRoutes(); + }, + { + deep: true, + } + ); + // 页面加载前 + onBeforeMount(() => { + initMenuFixed(document.body.clientWidth); + setFilterRoutes(); + // 此界面不需要取消监听(proxy.mittBus.off('setSendColumnsChildren)) + // 因为切换布局时有的监听需要使用,取消了监听,某些操作将不生效 + proxy.mittBus.on('setSendColumnsChildren', (res: any) => { + state.menuList = res.children; + }); + proxy.mittBus.on('setSendClassicChildren', (res: any) => { + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + state.menuList = []; + state.menuList = res.children; + } + }); + proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => { + setFilterRoutes(); + }); + proxy.mittBus.on('layoutMobileResize', (res: any) => { + initMenuFixed(res.clientWidth); + closeLayoutAsideMobileMode(); + }); + }); + return { + setCollapseStyle, + setShowLogo, + isTagsViewCurrenFull, + onAsideEnterLeave, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/component/columnsAside.vue b/src/layout/component/columnsAside.vue new file mode 100644 index 0000000..7fd7806 --- /dev/null +++ b/src/layout/component/columnsAside.vue @@ -0,0 +1,292 @@ +<template> + <div class="layout-columns-aside"> + <el-scrollbar> + <ul @mouseleave="onColumnsAsideMenuMouseleave()"> + <li + v-for="(v, k) in columnsAsideList" + :key="k" + @click="onColumnsAsideMenuClick(v, k)" + @mouseenter="onColumnsAsideMenuMouseenter(v, k)" + :ref=" + (el) => { + if (el) columnsAsideOffsetTopRefs[k] = el; + } + " + :class="{ 'layout-columns-active': liIndex === k, 'layout-columns-hover': liHoverIndex === k }" + :title="$t(v.meta.title)" + > + <div :class="themeConfig.columnsAsideLayout" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)"> + <SvgIcon :name="v.meta.icon" /> + <div class="columns-vertical-title font12"> + {{ + $t(v.meta.title) && $t(v.meta.title).length >= 4 + ? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 : 3) + : $t(v.meta.title) + }} + </div> + </div> + <div :class="themeConfig.columnsAsideLayout" v-else> + <a :href="v.meta.isLink" target="_blank"> + <SvgIcon :name="v.meta.icon" /> + <div class="columns-vertical-title font12"> + {{ + $t(v.meta.title) && $t(v.meta.title).length >= 4 + ? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 : 3) + : $t(v.meta.title) + }} + </div> + </a> + </div> + </li> + <div ref="columnsAsideActiveRef" :class="themeConfig.columnsAsideStyle"></div> + </ul> + </el-scrollbar> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref, onMounted, nextTick, getCurrentInstance, watch, onUnmounted, defineComponent } from 'vue'; +import { useRoute, useRouter, onBeforeRouteUpdate, RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface ColumnsAsideState { + columnsAsideList: any[]; + liIndex: number; + liOldIndex: null | number; + liHoverIndex: null | number; + liOldPath: null | string; + difference: number; + routeSplit: string[]; +} + +export default defineComponent({ + name: 'layoutColumnsAside', + setup() { + const columnsAsideOffsetTopRefs: any = ref([]); + const columnsAsideActiveRef = ref(); + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { routesList, isColumnsMenuHover, isColumnsNavHover } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const router = useRouter(); + const state = reactive<ColumnsAsideState>({ + columnsAsideList: [], + liIndex: 0, + liOldIndex: null, + liHoverIndex: null, + liOldPath: null, + difference: 0, + routeSplit: [], + }); + // 设置菜单高亮位置移动 + const setColumnsAsideMove = (k: number) => { + state.liIndex = k; + columnsAsideActiveRef.value.style.top = `${columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference}px`; + }; + // 菜单高亮点击事件 + const onColumnsAsideMenuClick = (v: Object, k: number) => { + setColumnsAsideMove(k); + let { path, redirect } = v as any; + if (redirect) router.push(redirect); + else router.push(path); + }; + // 鼠标移入时,显示当前的子级菜单 + const onColumnsAsideMenuMouseenter = (v: RouteRecordRaw, k: number) => { + let { path } = v; + state.liOldPath = path; + state.liOldIndex = k; + state.liHoverIndex = k; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(path)); + stores.setColumnsMenuHover(false); + stores.setColumnsNavHover(true); + }; + // 鼠标移走时,显示原来的子级菜单 + const onColumnsAsideMenuMouseleave = async () => { + await stores.setColumnsNavHover(false); + // 添加延时器,防止拿到的 store.state.routesList 值不是最新的 + setTimeout(() => { + if (!isColumnsMenuHover && !isColumnsNavHover) proxy.mittBus.emit('restoreDefault'); + }, 100); + }; + // 设置高亮动态位置 + const onColumnsAsideDown = (k: number) => { + nextTick(() => { + setColumnsAsideMove(k); + }); + }; + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + state.columnsAsideList = filterRoutesFun(routesList.value); + const resData: any = setSendChildren(route.path); + if (Object.keys(resData).length <= 0) return false; + onColumnsAsideDown(resData.item[0].k); + proxy.mittBus.emit('setSendColumnsChildren', resData); + }; + // 传送当前子级数据到菜单中 + const setSendChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + state.columnsAsideList.map((v: any, k: number) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮 + const setColumnsMenuHighlight = (path: string) => { + state.routeSplit = path.split('/'); + state.routeSplit.shift(); + const routeFirst = `/${state.routeSplit[0]}`; + const currentSplitRoute = state.columnsAsideList.find((v: any) => v.path === routeFirst); + if (!currentSplitRoute) return false; + // 延迟拿值,防止取不到 + setTimeout(() => { + onColumnsAsideDown((<any>currentSplitRoute).k); + }, 0); + }; + // 监听布局配置信息的变化,动态增加菜单高亮位置移动像素 + watch( + pinia.state, + (val) => { + val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (state.difference = 3) : (state.difference = 0); + if (!val.routesList.isColumnsMenuHover && !val.routesList.isColumnsNavHover) { + state.liHoverIndex = null; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(route.path)); + } else { + state.liHoverIndex = state.liOldIndex; + if (!state.liOldPath) return false; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(state.liOldPath)); + } + }, + { + deep: true, + } + ); + // 页面加载时 + onMounted(() => { + setFilterRoutes(); + // 销毁变量,防止鼠标再次移入时,保留了上次的记录 + proxy.mittBus.on('restoreDefault', () => { + state.liOldIndex = null; + state.liOldPath = null; + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('restoreDefault', () => {}); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + setColumnsMenuHighlight(to.path); + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(to.path)); + }); + return { + themeConfig, + columnsAsideOffsetTopRefs, + columnsAsideActiveRef, + onColumnsAsideDown, + onColumnsAsideMenuClick, + onColumnsAsideMenuMouseenter, + onColumnsAsideMenuMouseleave, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-columns-aside { + width: 70px; + height: 100%; + background: var(--next-bg-columnsMenuBar); + ul { + position: relative; + li { + color: var(--next-bg-columnsMenuBarColor); + width: 100%; + height: 50px; + text-align: center; + display: flex; + cursor: pointer; + position: relative; + z-index: 1; + .columns-vertical { + margin: auto; + .columns-vertical-title { + padding-top: 1px; + } + } + .columns-horizontal { + display: flex; + height: 50px; + width: 100%; + align-items: center; + padding: 0 5px; + i { + margin-right: 3px; + } + a { + display: flex; + .columns-horizontal-title { + padding-top: 1px; + } + } + } + a { + text-decoration: none; + color: var(--next-bg-columnsMenuBarColor); + } + } + .layout-columns-active { + color: var(--next-bg-columnsMenuBarColor) !important; + transition: 0.3s ease-in-out; + } + .layout-columns-hover { + color: var(--el-color-primary); + a { + color: var(--el-color-primary); + } + } + .columns-round { + background: var(--el-color-primary); + color: var(--el-color-white); + position: absolute; + left: 50%; + top: 2px; + height: 44px; + width: 65px; + transform: translateX(-50%); + z-index: 0; + transition: 0.3s ease-in-out; + border-radius: 5px; + } + .columns-card { + @extend .columns-round; + top: 0; + height: 50px; + width: 100%; + border-radius: 0; + } + } +} +</style> diff --git a/src/layout/component/header.vue b/src/layout/component/header.vue new file mode 100644 index 0000000..21c9e2d --- /dev/null +++ b/src/layout/component/header.vue @@ -0,0 +1,34 @@ +<template> + <el-header class="layout-header" :height="setHeaderHeight" v-show="!isTagsViewCurrenFull"> + <NavBarsIndex /> + </el-header> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import NavBarsIndex from '/@/layout/navBars/index.vue'; + +export default defineComponent({ + name: 'layoutHeader', + components: { NavBarsIndex }, + setup() { + const storesTagsViewRoutes = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + // 设置 header 的高度 + const setHeaderHeight = computed(() => { + let { isTagsview, layout } = themeConfig.value; + if (isTagsview && layout !== 'classic') return '84px'; + else return '50px'; + }); + return { + setHeaderHeight, + isTagsViewCurrenFull, + }; + }, +}); +</script> diff --git a/src/layout/component/main.vue b/src/layout/component/main.vue new file mode 100644 index 0000000..18eba60 --- /dev/null +++ b/src/layout/component/main.vue @@ -0,0 +1,101 @@ +<template> + <el-main class="layout-main"> + <el-scrollbar + ref="layoutScrollbarRef" + :class="{ + 'layout-scrollbar': + (!isClassicOrTransverse && !currentRouteMeta.isLink && !currentRouteMeta.isIframe) || + (!isClassicOrTransverse && currentRouteMeta.isLink && !currentRouteMeta.isIframe), + }" + > + <LayoutParentView + :style="{ + padding: !isClassicOrTransverse || (currentRouteMeta.isLink && currentRouteMeta.isIframe) ? '0' : '15px', + transition: 'padding 0.3s ease-in-out', + }" + /> + <Footer v-if="themeConfig.isFooter" /> + </el-scrollbar> + </el-main> +</template> + +<script lang="ts"> +import { defineComponent, toRefs, reactive, getCurrentInstance, watch, onMounted, computed } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { NextLoading } from '/@/utils/loading'; +import LayoutParentView from '/@/layout/routerView/parent.vue'; +import Footer from '/@/layout/footer/index.vue'; + +// 定义接口来定义对象的类型 +interface MainState { + headerHeight: string | number; + currentRouteMeta: any; +} + +export default defineComponent({ + name: 'layoutMain', + components: { LayoutParentView, Footer }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive<MainState>({ + headerHeight: '', + currentRouteMeta: {}, + }); + // 判断布局 + const isClassicOrTransverse = computed(() => { + const { layout } = themeConfig.value; + return layout === 'classic' || layout === 'transverse'; + }); + // 设置 main 的高度 + const initHeaderHeight = () => { + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + let { isTagsview } = themeConfig.value; + if (isTagsview) return (state.headerHeight = bool ? `86px` : `115px`); + else return (state.headerHeight = `80px`); + }; + // 初始化获取当前路由 meta,用于设置 iframes padding + const initGetMeta = () => { + state.currentRouteMeta = route.meta; + }; + // 页面加载前 + onMounted(async () => { + await initGetMeta(); + initHeaderHeight(); + NextLoading.done(); + }); + // 监听路由变化 + watch( + () => route.path, + () => { + state.currentRouteMeta = route.meta; + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + state.headerHeight = bool ? `86px` : `115px`; + proxy.$refs.layoutScrollbarRef.update(); + } + ); + // 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度 + watch( + themeConfig, + (val) => { + state.currentRouteMeta = route.meta; + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + state.headerHeight = val.isTagsview ? (bool ? `86px` : `115px`) : '51px'; + proxy.$refs?.layoutScrollbarRef?.update(); + }, + { + deep: true, + } + ); + return { + themeConfig, + isClassicOrTransverse, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/footer/index.vue b/src/layout/footer/index.vue new file mode 100644 index 0000000..ef00591 --- /dev/null +++ b/src/layout/footer/index.vue @@ -0,0 +1,47 @@ +<template> + <div class="layout-footer mt15" v-show="isDelayFooter"> + <div class="layout-footer-warp"> + <div>vue-next-admin,Made by lyt with ❤️</div> + <div class="mt5">深圳市 xxx 公司版权所有</div> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent } from 'vue'; +import { onBeforeRouteUpdate } from 'vue-router'; + +export default defineComponent({ + name: 'layoutFooter', + setup() { + const state = reactive({ + isDelayFooter: true, + }); + // 路由改变时,等主界面动画加载完毕再显示 footer + onBeforeRouteUpdate(() => { + setTimeout(() => { + state.isDelayFooter = false; + setTimeout(() => { + state.isDelayFooter = true; + }, 800); + }, 0); + }); + return { + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-footer { + width: 100%; + display: flex; + &-warp { + margin: auto; + color: var(--el-text-color-secondary); + text-align: center; + animation: error-num 1s ease-in-out; + } +} +</style> diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..50643a4 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,54 @@ +<template> + <component :is="themeConfig.layout" /> +</template> + +<script lang="ts"> +import { onBeforeMount, onUnmounted, getCurrentInstance, defineComponent, defineAsyncComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Local } from '/@/utils/storage'; + +export default defineComponent({ + name: 'layout', + components: { + defaults: defineAsyncComponent(() => import('/@/layout/main/defaults.vue')), + classic: defineAsyncComponent(() => import('/@/layout/main/classic.vue')), + transverse: defineAsyncComponent(() => import('/@/layout/main/transverse.vue')), + columns: defineAsyncComponent(() => import('/@/layout/main/columns.vue')), + }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 窗口大小改变时(适配移动端) + const onLayoutResize = () => { + if (!Local.get('oldLayout')) Local.set('oldLayout', themeConfig.value.layout); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) { + themeConfig.value.isCollapse = false; + proxy.mittBus.emit('layoutMobileResize', { + layout: 'defaults', + clientWidth, + }); + } else { + proxy.mittBus.emit('layoutMobileResize', { + layout: Local.get('oldLayout') ? Local.get('oldLayout') : themeConfig.value.layout, + clientWidth, + }); + } + }; + // 页面加载前 + onBeforeMount(() => { + onLayoutResize(); + window.addEventListener('resize', onLayoutResize); + }); + // 页面卸载时 + onUnmounted(() => { + window.removeEventListener('resize', onLayoutResize); + }); + return { + themeConfig, + }; + }, +}); +</script> diff --git a/src/layout/lockScreen/index.vue b/src/layout/lockScreen/index.vue new file mode 100644 index 0000000..10b8fed --- /dev/null +++ b/src/layout/lockScreen/index.vue @@ -0,0 +1,372 @@ +<template> + <div v-show="isShowLockScreen"> + <div class="layout-lock-screen-mask"></div> + <div class="layout-lock-screen-img" :class="{ 'layout-lock-screen-filter': isShowLoockLogin }"></div> + <div class="layout-lock-screen"> + <div + class="layout-lock-screen-date" + ref="layoutLockScreenDateRef" + @mousedown="onDown" + @mousemove="onMove" + @mouseup="onEnd" + @touchstart.stop="onDown" + @touchmove.stop="onMove" + @touchend.stop="onEnd" + > + <div class="layout-lock-screen-date-box"> + <div class="layout-lock-screen-date-box-time"> + {{ time.hm }}<span class="layout-lock-screen-date-box-minutes">{{ time.s }}</span> + </div> + <div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div> + </div> + <div class="layout-lock-screen-date-top"> + <SvgIcon name="ele-Top" /> + <div class="layout-lock-screen-date-top-text">上滑解锁</div> + </div> + </div> + <transition name="el-zoom-in-center"> + <div v-show="isShowLoockLogin" class="layout-lock-screen-login"> + <div class="layout-lock-screen-login-box"> + <div class="layout-lock-screen-login-box-img"> + <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" /> + </div> + <div class="layout-lock-screen-login-box-name">Administrator</div> + <div class="layout-lock-screen-login-box-value"> + <el-input + placeholder="请输入密码" + ref="layoutLockScreenInputRef" + v-model="lockScreenPassword" + @keyup.enter.native.stop="onLockScreenSubmit()" + > + <template #append> + <el-button @click="onLockScreenSubmit"> + <el-icon class="el-input__icon"> + <ele-Right /> + </el-icon> + </el-button> + </template> + </el-input> + </div> + </div> + <div class="layout-lock-screen-login-icon"> + <SvgIcon name="ele-Microphone" :size="20" /> + <SvgIcon name="ele-AlarmClock" :size="20" /> + <SvgIcon name="ele-SwitchButton" :size="20" /> + </div> + </div> + </transition> + </div> + </div> +</template> + +<script lang="ts"> +import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInstance, defineComponent } from 'vue'; +import { formatDate } from '/@/utils/formatTime'; +import { Local } from '/@/utils/storage'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface LockScreenState { + transparency: number; + downClientY: number; + moveDifference: number; + isShowLoockLogin: boolean; + isFlags: boolean; + querySelectorEl: HTMLElement | string; + time: { + hm: string; + s: string; + mdq: string; + }; + setIntervalTime: number; + isShowLockScreen: boolean; + isShowLockScreenIntervalTime: number; + lockScreenPassword: string; +} + +export default defineComponent({ + name: 'layoutLockScreen', + setup() { + const { proxy } = <any>getCurrentInstance(); + const layoutLockScreenInputRef = ref(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<LockScreenState>({ + transparency: 1, + downClientY: 0, + moveDifference: 0, + isShowLoockLogin: false, + isFlags: false, + querySelectorEl: '', + time: { + hm: '', + s: '', + mdq: '', + }, + setIntervalTime: 0, + isShowLockScreen: false, + isShowLockScreenIntervalTime: 0, + lockScreenPassword: '', + }); + // 鼠标按下 + const onDown = (down: any) => { + state.isFlags = true; + state.downClientY = down.touches ? down.touches[0].clientY : down.clientY; + }; + // 鼠标移动 + const onMove = (move: any) => { + if (state.isFlags) { + const el = <HTMLElement>state.querySelectorEl; + const opacitys = (state.transparency -= 1 / 200); + if (move.touches) { + state.moveDifference = move.touches[0].clientY - state.downClientY; + } else { + state.moveDifference = move.clientY - state.downClientY; + } + if (state.moveDifference >= 0) return false; + el.setAttribute('style', `top:${state.moveDifference}px;cursor:pointer;opacity:${opacitys};`); + if (state.moveDifference < -400) { + el.setAttribute('style', `top:${-el.clientHeight}px;cursor:pointer;transition:all 0.3s ease;`); + state.moveDifference = -el.clientHeight; + setTimeout(() => { + el && el.parentNode?.removeChild(el); + }, 300); + } + if (state.moveDifference === -el.clientHeight) { + state.isShowLoockLogin = true; + layoutLockScreenInputRef.value.focus(); + } + } + }; + // 鼠标松开 + const onEnd = () => { + state.isFlags = false; + state.transparency = 1; + if (state.moveDifference >= -400) { + (<HTMLElement>state.querySelectorEl).setAttribute('style', `top:0px;opacity:1;transition:all 0.3s ease;`); + } + }; + // 获取要拖拽的初始元素 + const initGetElement = () => { + nextTick(() => { + state.querySelectorEl = proxy.$refs.layoutLockScreenDateRef; + }); + }; + // 时间初始化 + const initTime = () => { + state.time.hm = formatDate(new Date(), 'HH:MM'); + state.time.s = formatDate(new Date(), 'SS'); + state.time.mdq = formatDate(new Date(), 'mm月dd日,WWW'); + }; + // 时间初始化定时器 + const initSetTime = () => { + initTime(); + state.setIntervalTime = window.setInterval(() => { + initTime(); + }, 1000); + }; + // 锁屏时间定时器 + const initLockScreen = () => { + if (themeConfig.value.isLockScreen) { + state.isShowLockScreenIntervalTime = window.setInterval(() => { + if (themeConfig.value.lockScreenTime <= 1) { + state.isShowLockScreen = true; + setLocalThemeConfig(); + return false; + } + themeConfig.value.lockScreenTime--; + }, 1000); + } else { + clearInterval(state.isShowLockScreenIntervalTime); + } + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + themeConfig.value.isDrawer = false; + Local.set('themeConfig', themeConfig.value); + }; + // 密码输入点击事件 + const onLockScreenSubmit = () => { + themeConfig.value.isLockScreen = false; + themeConfig.value.lockScreenTime = 30; + setLocalThemeConfig(); + }; + // 页面加载时 + onMounted(() => { + initGetElement(); + initSetTime(); + initLockScreen(); + }); + // 页面卸载时 + onUnmounted(() => { + window.clearInterval(state.setIntervalTime); + window.clearInterval(state.isShowLockScreenIntervalTime); + }); + return { + layoutLockScreenInputRef, + onDown, + onMove, + onEnd, + onLockScreenSubmit, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-lock-screen-fixed { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.layout-lock-screen-filter { + filter: blur(1px); +} +.layout-lock-screen-mask { + background: var(--el-color-white); + @extend .layout-lock-screen-fixed; + z-index: 9999990; +} +.layout-lock-screen-img { + @extend .layout-lock-screen-fixed; + background-image: url('https://img-blog.csdnimg.cn/afa9c317667f47d5bea34b85af45979e.png#pic_center'); + background-size: 100% 100%; + z-index: 9999991; +} +.layout-lock-screen { + @extend .layout-lock-screen-fixed; + z-index: 9999992; + &-date { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + color: var(--el-color-white); + z-index: 9999993; + user-select: none; + &-box { + position: absolute; + left: 30px; + bottom: 50px; + &-time { + font-size: 100px; + color: var(--el-color-white); + } + &-info { + font-size: 40px; + color: var(--el-color-white); + } + &-minutes { + font-size: 16px; + } + } + &-top { + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 100%; + border: 1px solid var(--el-border-color-light, #ebeef5); + background: rgba(255, 255, 255, 0.1); + color: var(--el-color-white); + opacity: 0.8; + position: absolute; + right: 30px; + bottom: 50px; + text-align: center; + overflow: hidden; + transition: all 0.3s ease; + i { + transition: all 0.3s ease; + } + &-text { + opacity: 0; + position: absolute; + top: 150%; + font-size: 12px; + color: var(--el-color-white); + left: 50%; + line-height: 1.2; + transform: translate(-50%, -50%); + transition: all 0.3s ease; + width: 35px; + } + &:hover { + border: 1px solid rgba(255, 255, 255, 0.5); + background: rgba(255, 255, 255, 0.2); + box-shadow: 0 0 12px 0 rgba(255, 255, 255, 0.5); + color: var(--el-color-white); + opacity: 1; + transition: all 0.3s ease; + i { + transform: translateY(-40px); + transition: all 0.3s ease; + } + .layout-lock-screen-date-top-text { + opacity: 1; + top: 50%; + transition: all 0.3s ease; + } + } + } + } + &-login { + position: relative; + z-index: 9999994; + width: 100%; + height: 100%; + left: 0; + top: 0; + display: flex; + flex-direction: column; + justify-content: center; + color: var(--el-color-white); + &-box { + text-align: center; + margin: auto; + &-img { + width: 180px; + height: 180px; + margin: auto; + img { + width: 100%; + height: 100%; + border-radius: 100%; + } + } + &-name { + font-size: 26px; + margin: 15px 0 30px; + } + } + &-icon { + position: absolute; + right: 30px; + bottom: 30px; + i { + font-size: 20px; + margin-left: 15px; + cursor: pointer; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + } + } +} +::v-deep(.el-input-group__append) { + background: var(--el-color-white); + padding: 0px 15px; +} +::v-deep(.el-input__inner) { + border-right-color: var(--el-border-color-extra-light); + &:hover { + border-color: var(--el-border-color-extra-light); + } +} +</style> diff --git a/src/layout/logo/index.vue b/src/layout/logo/index.vue new file mode 100644 index 0000000..3d2b543 --- /dev/null +++ b/src/layout/logo/index.vue @@ -0,0 +1,85 @@ +<template> + <div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange"> + <img :src="logoMini" class="layout-logo-medium-img" /> + <span>{{ themeConfig.globalTitle }}</span> + </div> + <div class="layout-logo-size" v-else @click="onThemeConfigChange"> + <img :src="logoMini" class="layout-logo-size-img" /> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +import logoMini from '/@/assets/logo-mini.svg'; + +export default defineComponent({ + name: 'layoutLogo', + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 设置 logo 的显示。classic 经典布局默认显示 logo + const setShowLogo = computed(() => { + let { isCollapse, layout } = themeConfig.value; + return !isCollapse || layout === 'classic' || document.body.clientWidth < 1000; + }); + // logo 点击实现菜单展开/收起 + const onThemeConfigChange = () => { + if (themeConfig.value.layout === 'transverse') return false; + themeConfig.value.isCollapse = !themeConfig.value.isCollapse; + }; + return { + logoMini, + setShowLogo, + themeConfig, + onThemeConfigChange, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-logo { + width: 220px; + height: 50px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px; + color: var(--el-color-primary); + font-size: 16px; + cursor: pointer; + animation: logoAnimation 0.3s ease-in-out; + span { + white-space: nowrap; + display: inline-block; + } + &:hover { + span { + color: var(--color-primary-light-2); + } + } + &-medium-img { + width: 20px; + margin-right: 5px; + } +} +.layout-logo-size { + width: 100%; + height: 50px; + display: flex; + cursor: pointer; + animation: logoAnimation 0.3s ease-in-out; + &-img { + width: 20px; + margin: auto; + } + &:hover { + img { + animation: logoAnimation 0.3s ease-in-out; + } + } +} +</style> diff --git a/src/layout/main/classic.vue b/src/layout/main/classic.vue new file mode 100644 index 0000000..b92290f --- /dev/null +++ b/src/layout/main/classic.vue @@ -0,0 +1,35 @@ +<template> + <el-container class="layout-container flex-center"> + <Header /> + <el-container class="layout-mian-height-50"> + <Aside /> + <div class="flex-center layout-backtop"> + <TagsView v-if="themeConfig.isTagsview" /> + <Main /> + </div> + </el-container> + <el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; +import TagsView from '/@/layout/navBars/tagsView/tagsView.vue'; + +export default defineComponent({ + name: 'layoutClassic', + components: { Aside, Header, Main, TagsView }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + return { + themeConfig, + }; + }, +}); +</script> diff --git a/src/layout/main/columns.vue b/src/layout/main/columns.vue new file mode 100644 index 0000000..0aa1d31 --- /dev/null +++ b/src/layout/main/columns.vue @@ -0,0 +1,41 @@ +<template> + <el-container class="layout-container"> + <ColumnsAside /> + <div class="layout-columns-warp"> + <Aside /> + <el-container class="flex-center layout-backtop" :class="{ 'layout-backtop': !isFixedHeader }"> + <Header v-if="isFixedHeader" /> + <el-scrollbar :class="{ 'layout-backtop': isFixedHeader }"> + <Header v-if="!isFixedHeader" /> + <Main /> + </el-scrollbar> + </el-container> + </div> + <el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; +import ColumnsAside from '/@/layout/component/columnsAside.vue'; + +export default defineComponent({ + name: 'layoutColumns', + components: { Aside, Header, Main, ColumnsAside }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const isFixedHeader = computed(() => { + return themeConfig.value.isFixedHeader; + }); + return { + isFixedHeader, + }; + }, +}); +</script> diff --git a/src/layout/main/defaults.vue b/src/layout/main/defaults.vue new file mode 100644 index 0000000..0cabb0c --- /dev/null +++ b/src/layout/main/defaults.vue @@ -0,0 +1,47 @@ +<template> + <el-container class="layout-container"> + <Aside /> + <el-container class="flex-center" :class="{ 'layout-backtop': !isFixedHeader }"> + <Header v-if="isFixedHeader" /> + <el-scrollbar ref="layoutDefaultsScrollbarRef" :class="{ 'layout-backtop': isFixedHeader }"> + <Header v-if="!isFixedHeader" /> + <Main /> + </el-scrollbar> + </el-container> + <el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { computed, getCurrentInstance, watch, defineComponent } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; + +export default defineComponent({ + name: 'layoutDefaults', + components: { Aside, Header, Main }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const route = useRoute(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const isFixedHeader = computed(() => { + return themeConfig.value.isFixedHeader; + }); + // 监听路由的变化 + watch( + () => route.path, + () => { + proxy.$refs.layoutDefaultsScrollbarRef.wrap$.scrollTop = 0; + } + ); + return { + isFixedHeader, + }; + }, +}); +</script> diff --git a/src/layout/main/transverse.vue b/src/layout/main/transverse.vue new file mode 100644 index 0000000..538f911 --- /dev/null +++ b/src/layout/main/transverse.vue @@ -0,0 +1,17 @@ +<template> + <el-container class="layout-container flex-center layout-backtop"> + <Header /> + <Main /> + <el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; + +export default { + name: 'layoutTransverse', + components: { Header, Main }, +}; +</script> diff --git a/src/layout/navBars/breadcrumb/breadcrumb.vue b/src/layout/navBars/breadcrumb/breadcrumb.vue new file mode 100644 index 0000000..541a841 --- /dev/null +++ b/src/layout/navBars/breadcrumb/breadcrumb.vue @@ -0,0 +1,163 @@ +<template> + <div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb"> + <SvgIcon + class="layout-navbars-breadcrumb-icon" + :name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'" + :size="16" + @click="onThemeConfigChange" + /> + <el-breadcrumb class="layout-navbars-breadcrumb-hide"> + <transition-group name="breadcrumb"> + <el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName"> + <span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span"> + <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" /> + <div v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div> + <div v-else>{{ v.meta.tagsViewName }}</div> + </span> + <a v-else @click.prevent="onBreadcrumbClick(v)"> + <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />{{ $t(v.meta.title) }} + </a> + </el-breadcrumb-item> + </transition-group> + </el-breadcrumb> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, onMounted, defineComponent } from 'vue'; +import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'; +import { Local } from '/@/utils/storage'; +import other from '/@/utils/other'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useRoutesList } from '/@/stores/routesList'; + +// 定义接口来定义对象的类型 +interface BreadcrumbState { + breadcrumbList: Array<any>; + routeSplit: Array<string>; + routeSplitFirst: string; + routeSplitIndex: number; +} + +export default defineComponent({ + name: 'layoutBreadcrumb', + setup() { + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { routesList } = storeToRefs(stores); + const route = useRoute(); + const router = useRouter(); + const state = reactive<BreadcrumbState>({ + breadcrumbList: [], + routeSplit: [], + routeSplitFirst: '', + routeSplitIndex: 1, + }); + // 动态设置经典、横向布局不显示 + const isShowBreadcrumb = computed(() => { + initRouteSplit(route.path); + const { layout, isBreadcrumb } = themeConfig.value; + if (layout === 'classic' || layout === 'transverse') return false; + else return isBreadcrumb ? true : false; + }); + // 面包屑点击时 + const onBreadcrumbClick = (v: any) => { + const { redirect, path } = v; + if (redirect) router.push(redirect); + else router.push(path); + }; + // 展开/收起左侧菜单点击 + const onThemeConfigChange = () => { + themeConfig.value.isCollapse = !themeConfig.value.isCollapse; + setLocalThemeConfig(); + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + Local.remove('themeConfig'); + Local.set('themeConfig', themeConfig.value); + }; + // 处理面包屑数据 + const getBreadcrumbList = (arr: Array<string>) => { + arr.forEach((item: any) => { + state.routeSplit.forEach((v: any, k: number, arrs: any) => { + if (state.routeSplitFirst === item.path) { + state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`; + state.breadcrumbList.push(item); + state.routeSplitIndex++; + if (item.children) getBreadcrumbList(item.children); + } + }); + }); + }; + // 当前路由字符串切割成数组,并删除第一项空内容 + const initRouteSplit = (path: string) => { + if (!themeConfig.value.isBreadcrumb) return false; + state.breadcrumbList = [routesList.value[0]]; + state.routeSplit = path.split('/'); + state.routeSplit.shift(); + state.routeSplitFirst = `/${state.routeSplit[0]}`; + state.routeSplitIndex = 1; + getBreadcrumbList(routesList.value); + if (route.name === 'home' || (route.name === 'notFound' && state.breadcrumbList.length > 1)) state.breadcrumbList.shift(); + if (state.breadcrumbList.length > 0) state.breadcrumbList[state.breadcrumbList.length - 1].meta.tagsViewName = other.setTagsViewNameI18n(route); + }; + // 页面加载时 + onMounted(() => { + initRouteSplit(route.path); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + initRouteSplit(to.path); + }); + return { + onThemeConfigChange, + isShowBreadcrumb, + themeConfig, + onBreadcrumbClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb { + flex: 1; + height: inherit; + display: flex; + align-items: center; + .layout-navbars-breadcrumb-icon { + cursor: pointer; + font-size: 18px; + color: var(--next-bg-topBarColor); + height: 100%; + width: 40px; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + .layout-navbars-breadcrumb-span { + display: flex; + opacity: 0.7; + color: var(--next-bg-topBarColor); + } + .layout-navbars-breadcrumb-iconfont { + font-size: 14px; + margin-right: 5px; + } + ::v-deep(.el-breadcrumb__separator) { + opacity: 0.7; + color: var(--next-bg-topBarColor); + } + ::v-deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) { + font-weight: unset !important; + color: var(--next-bg-topBarColor); + &:hover { + color: var(--el-color-primary) !important; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/closeFull.vue b/src/layout/navBars/breadcrumb/closeFull.vue new file mode 100644 index 0000000..a0f0525 --- /dev/null +++ b/src/layout/navBars/breadcrumb/closeFull.vue @@ -0,0 +1,61 @@ +<template> + <div class="layout-navbars-close-full" v-if="isTagsViewCurrenFull"> + <div class="layout-navbars-close-full-icon"> + <SvgIcon name="ele-Close" :title="$t('message.tagsView.closeFullscreen')" @click="onCloseFullscreen" /> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: 'layoutCloseFull', + setup() { + const stores = useTagsViewRoutes(); + const { isTagsViewCurrenFull } = storeToRefs(stores); + // 关闭当前全屏 + const onCloseFullscreen = () => { + stores.setCurrenFullscreen(false); + }; + return { + isTagsViewCurrenFull, + onCloseFullscreen, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-close-full { + position: fixed; + z-index: 9999999999; + right: -30px; + top: -30px; + .layout-navbars-close-full-icon { + width: 60px; + height: 60px; + border-radius: 100%; + cursor: pointer; + background: rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + position: relative; + ::v-deep(i) { + position: absolute; + left: 10px; + top: 35px; + color: #333333; + transition: all 0.3s ease; + } + } + &:hover { + transition: all 0.3s ease; + ::v-deep(i) { + color: var(--el-color-primary); + transition: all 0.3s ease; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/index.vue b/src/layout/navBars/breadcrumb/index.vue new file mode 100644 index 0000000..2810718 --- /dev/null +++ b/src/layout/navBars/breadcrumb/index.vue @@ -0,0 +1,119 @@ +<template> + <div class="layout-navbars-breadcrumb-index"> + <Logo v-if="setIsShowLogo" /> + <Breadcrumb /> + <Horizontal :menuList="menuList" v-if="isLayoutTransverse" /> + <User /> + </div> +</template> + +<script lang="ts"> +import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, defineComponent } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Breadcrumb from '/@/layout/navBars/breadcrumb/breadcrumb.vue'; +import User from '/@/layout/navBars/breadcrumb/user.vue'; +import Logo from '/@/layout/logo/index.vue'; +import Horizontal from '/@/layout/navMenu/horizontal.vue'; + +// 定义接口来定义对象的类型 +interface IndexState { + menuList: object[]; +} + +export default defineComponent({ + name: 'layoutBreadcrumbIndex', + components: { Breadcrumb, User, Logo, Horizontal }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { routesList } = storeToRefs(stores); + const route = useRoute(); + const state = reactive<IndexState>({ + menuList: [], + }); + // 设置 logo 显示/隐藏 + const setIsShowLogo = computed(() => { + let { isShowLogo, layout } = themeConfig.value; + return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse'); + }); + // 设置是否显示横向导航菜单 + const isLayoutTransverse = computed(() => { + let { layout, isClassicSplitMenu } = themeConfig.value; + return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic'); + }); + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + state.menuList = delClassicChildren(filterRoutesFun(routesList.value)); + const resData = setSendClassicChildren(route.path); + proxy.mittBus.emit('setSendClassicChildren', resData); + } else { + state.menuList = filterRoutesFun(routesList.value); + } + }; + // 设置了分割菜单时,删除底下 children + const delClassicChildren = (arr: Array<object>) => { + arr.map((v: any) => { + if (v.children) delete v.children; + }); + return arr; + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 传送当前子级数据到菜单中 + const setSendClassicChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + filterRoutesFun(routesList.value).map((v, k) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 页面加载时 + onMounted(() => { + setFilterRoutes(); + proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => { + setFilterRoutes(); + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('getBreadcrumbIndexSetFilterRoutes', () => {}); + }); + return { + setIsShowLogo, + isLayoutTransverse, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb-index { + height: 50px; + display: flex; + align-items: center; + background: var(--next-bg-topBar); + border-bottom: 1px solid var(--next-border-color-light); +} +</style> diff --git a/src/layout/navBars/breadcrumb/search.vue b/src/layout/navBars/breadcrumb/search.vue new file mode 100644 index 0000000..431043c --- /dev/null +++ b/src/layout/navBars/breadcrumb/search.vue @@ -0,0 +1,138 @@ +<template> + <div class="layout-search-dialog"> + <el-dialog v-model="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false"> + <el-autocomplete + v-model="menuQuery" + :fetch-suggestions="menuSearch" + :placeholder="$t('message.user.searchPlaceholder')" + ref="layoutMenuAutocompleteRef" + @select="onHandleSelect" + @blur="onSearchBlur" + > + <template #prefix> + <el-icon class="el-input__icon"> + <ele-Search /> + </el-icon> + </template> + <template #default="{ item }"> + <div> + <SvgIcon :name="item.meta.icon" class="mr5" /> + {{ $t(item.meta.title) }} + </div> + </template> + </el-autocomplete> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent, ref, nextTick } from 'vue'; +import { useRouter } from 'vue-router'; +import { useI18n } from 'vue-i18n'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +// 定义接口来定义对象的类型 +interface SearchState { + isShowSearch: boolean; + menuQuery: string; + tagsViewList: object[]; +} +interface Restaurant { + path: string; + meta: { + title: string; + }; +} + +export default defineComponent({ + name: 'layoutBreadcrumbSearch', + setup() { + const storesTagsViewRoutes = useTagsViewRoutes(); + const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes); + const layoutMenuAutocompleteRef = ref(); + const { t } = useI18n(); + const router = useRouter(); + const state = reactive<SearchState>({ + isShowSearch: false, + menuQuery: '', + tagsViewList: [], + }); + // 搜索弹窗打开 + const openSearch = () => { + state.menuQuery = ''; + state.isShowSearch = true; + initTageView(); + nextTick(() => { + setTimeout(() => { + layoutMenuAutocompleteRef.value.focus(); + }); + }); + }; + // 搜索弹窗关闭 + const closeSearch = () => { + state.isShowSearch = false; + }; + // 菜单搜索数据过滤 + const menuSearch = (queryString: string, cb: Function) => { + let results = queryString ? state.tagsViewList.filter(createFilter(queryString)) : state.tagsViewList; + cb(results); + }; + // 菜单搜索过滤 + const createFilter: any = (queryString: string) => { + return (restaurant: Restaurant) => { + return ( + restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 || + restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1 || + t(restaurant.meta.title).indexOf(queryString.toLowerCase()) > -1 + ); + }; + }; + // 初始化菜单数据 + const initTageView = () => { + if (state.tagsViewList.length > 0) return false; + tagsViewRoutes.value.map((v: any) => { + if (!v.meta.isHide) state.tagsViewList.push({ ...v }); + }); + }; + // 当前菜单选中时 + const onHandleSelect = (item: any) => { + let { path, redirect } = item; + if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink); + else if (redirect) router.push(redirect); + else router.push(path); + closeSearch(); + }; + // input 失去焦点时 + const onSearchBlur = () => { + closeSearch(); + }; + return { + layoutMenuAutocompleteRef, + openSearch, + closeSearch, + menuSearch, + onHandleSelect, + onSearchBlur, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-search-dialog { + ::v-deep(.el-dialog) { + box-shadow: unset !important; + border-radius: 0 !important; + background: rgba(0, 0, 0, 0.5); + } + ::v-deep(.el-autocomplete) { + width: 560px; + position: absolute; + top: 100px; + left: 50%; + transform: translateX(-50%); + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/setings.vue b/src/layout/navBars/breadcrumb/setings.vue new file mode 100644 index 0000000..856f260 --- /dev/null +++ b/src/layout/navBars/breadcrumb/setings.vue @@ -0,0 +1,816 @@ +<template> + <div class="layout-breadcrumb-seting"> + <el-drawer + :title="$t('message.layout.configTitle')" + v-model="getThemeConfig.isDrawer" + direction="rtl" + destroy-on-close + size="260px" + @close="onDrawerClose" + > + <el-scrollbar class="layout-breadcrumb-seting-bar"> + <!-- 全局主题 --> + <el-divider content-position="left">{{ $t('message.layout.oneTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">primary</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.primary" size="default" @change="onColorPickerChange"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsDark') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isIsDark" size="small" @change="onAddDarkChange"></el-switch> + </div> + </div> + + <!-- 顶栏设置 --> + <el-divider content-position="left">{{ $t('message.layout.twoTopTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.topBar" size="default" @change="onBgColorPickerChange('topBar')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.topBarColor" size="default" @change="onBgColorPickerChange('topBarColor')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt10"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsTopBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTopBarColorGradual" size="small" @change="onTopBarGradualChange"></el-switch> + </div> + </div> + + <!-- 菜单设置 --> + <el-divider content-position="left">{{ $t('message.layout.twoMenuTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.menuBar" size="default" @change="onBgColorPickerChange('menuBar')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.menuBarColor" size="default" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsMenuBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isMenuBarColorGradual" size="small" @change="onMenuBarGradualChange"></el-switch> + </div> + </div> + + <!-- 分栏设置 --> + <el-divider content-position="left" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">{{ + $t('message.layout.twoColumnsTitle') + }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker + v-model="getThemeConfig.columnsMenuBar" + size="default" + @change="onBgColorPickerChange('columnsMenuBar')" + :disabled="getThemeConfig.layout !== 'columns'" + > + </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker + v-model="getThemeConfig.columnsMenuBarColor" + size="default" + @change="onBgColorPickerChange('columnsMenuBarColor')" + :disabled="getThemeConfig.layout !== 'columns'" + > + </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsColumnsMenuBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isColumnsMenuBarColorGradual" + size="small" + @change="onColumnsMenuBarGradualChange" + :disabled="getThemeConfig.layout !== 'columns'" + ></el-switch> + </div> + </div> + + <!-- 界面设置 --> + <el-divider content-position="left">{{ $t('message.layout.threeTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsCollapse') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isCollapse" + :disabled="getThemeConfig.layout === 'transverse'" + size="small" + @change="onThemeConfigChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsUniqueOpened') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isUniqueOpened" + :disabled="getThemeConfig.layout === 'transverse'" + size="small" + @change="setLocalThemeConfig" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsFixedHeader') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isFixedHeader" size="small" @change="onIsFixedHeaderChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'classic' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsClassicSplitMenu') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isClassicSplitMenu" + :disabled="getThemeConfig.layout !== 'classic'" + size="small" + @change="onClassicSplitMenuChange" + > + </el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsLockScreen') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isLockScreen" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt11"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeLockScreenTime') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-input-number + v-model="getThemeConfig.lockScreenTime" + controls-position="right" + :min="1" + :max="9999" + @change="setLocalThemeConfig" + size="default" + style="width: 90px" + > + </el-input-number> + </div> + </div> + + <!-- 界面显示 --> + <el-divider content-position="left">{{ $t('message.layout.fourTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShowLogo') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isShowLogo" size="small" @change="onIsShowLogoChange"></el-switch> + </div> + </div> + <div + class="layout-breadcrumb-seting-bar-flex mt15" + :style="{ opacity: getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse' ? 0.5 : 1 }" + > + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumb') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isBreadcrumb" + :disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'" + size="small" + @change="onIsBreadcrumbChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumbIcon') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isBreadcrumbIcon" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsview') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTagsview" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsviewIcon') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTagsviewIcon" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsCacheTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isCacheTagsView" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: isMobile ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsSortableTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isSortableTagsView" + :disabled="isMobile ? true : false" + size="small" + @change="onSortableTagsViewChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShareTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isShareTagsView" size="small" @change="onShareTagsViewChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsFooter') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isFooter" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsGrayscale') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isGrayscale" size="small" @change="onAddFilterChange('grayscale')"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsInvert') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isInvert" size="small" @change="onAddFilterChange('invert')"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsWartermark') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isWartermark" size="small" @change="onWartermarkChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourWartermarkText') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-input v-model="getThemeConfig.wartermarkText" size="default" style="width: 90px" @input="onWartermarkTextInput($event)"></el-input> + </div> + </div> + + <!-- 其它设置 --> + <el-divider content-position="left">{{ $t('message.layout.fiveTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveTagsStyle') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig"> + <el-option label="风格1" value="tags-style-one"></el-option> + <el-option label="风格4" value="tags-style-four"></el-option> + <el-option label="风格5" value="tags-style-five"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveAnimation') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select v-model="getThemeConfig.animation" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig"> + <el-option label="slide-right" value="slide-right"></el-option> + <el-option label="slide-left" value="slide-left"></el-option> + <el-option label="opacitys" value="opacitys"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select + v-model="getThemeConfig.columnsAsideStyle" + placeholder="请选择" + size="default" + style="width: 90px" + :disabled="getThemeConfig.layout !== 'columns' ? true : false" + @change="setLocalThemeConfig" + > + <el-option label="圆角" value="columns-round"></el-option> + <el-option label="卡片" value="columns-card"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15 mb27" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select + v-model="getThemeConfig.columnsAsideLayout" + placeholder="请选择" + size="default" + style="width: 90px" + :disabled="getThemeConfig.layout !== 'columns' ? true : false" + @change="setLocalThemeConfig" + > + <el-option label="水平" value="columns-horizontal"></el-option> + <el-option label="垂直" value="columns-vertical"></el-option> + </el-select> + </div> + </div> + + <!-- 布局切换 --> + <el-divider content-position="left">{{ $t('message.layout.sixTitle') }}</el-divider> + <div class="layout-drawer-content-flex"> + <!-- defaults 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('defaults')"> + <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'defaults' }"> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <header class="el-header" style="height: 10px"></header> + <main class="el-main"></main> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'defaults' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixDefaults') }}</p> + </div> + </div> + </div> + <!-- classic 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('classic')"> + <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'classic' }"> + <header class="el-header" style="height: 10px"></header> + <section class="el-container"> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <main class="el-main"></main> + </section> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'classic' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixClassic') }}</p> + </div> + </div> + </div> + <!-- transverse 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('transverse')"> + <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'transverse' }"> + <header class="el-header" style="height: 10px"></header> + <section class="el-container"> + <section class="el-container is-vertical"> + <main class="el-main"></main> + </section> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'transverse' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixTransverse') }}</p> + </div> + </div> + </div> + <!-- columns 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('columns')"> + <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }"> + <aside class="el-aside-dark" style="width: 10px"></aside> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <header class="el-header" style="height: 10px"></header> + <main class="el-main"></main> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p> + </div> + </div> + </div> + </div> + <div class="copy-config"> + <el-alert :title="$t('message.layout.tipText')" type="warning" :closable="false"> </el-alert> + <el-button size="default" class="copy-config-btn" type="primary" ref="copyConfigBtnRef" @click="onCopyConfigClick"> + <el-icon class="mr5"> + <ele-CopyDocument /> + </el-icon> + {{ $t('message.layout.copyText') }} + </el-button> + <el-button size="default" class="copy-config-btn-reset" type="info" @click="onResetConfigClick"> + <el-icon class="mr5"> + <ele-RefreshRight /> + </el-icon> + {{ $t('message.layout.resetText') }} + </el-button> + </div> + </el-scrollbar> + </el-drawer> + </div> +</template> + +<script lang="ts"> +import { nextTick, onUnmounted, onMounted, getCurrentInstance, defineComponent, computed, reactive, toRefs } from 'vue'; +import { ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { getLightColor, getDarkColor } from '/@/utils/theme'; +import { verifyAndSpace } from '/@/utils/toolsValidate'; +import { Local } from '/@/utils/storage'; +import Watermark from '/@/utils/wartermark'; +import commonFunction from '/@/utils/commonFunction'; +import other from '/@/utils/other'; + +export default defineComponent({ + name: 'layoutBreadcrumbSeting', + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { copyText } = commonFunction(); + const state = reactive({ + isMobile: false, + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 1、全局主题 + const onColorPickerChange = () => { + if (!getThemeConfig.value.primary) return ElMessage.warning('全局主题 primary 颜色值不能为空'); + // 颜色加深 + document.documentElement.style.setProperty('--el-color-primary-dark-2', `${getDarkColor(getThemeConfig.value.primary, 0.1)}`); + document.documentElement.style.setProperty('--el-color-primary', getThemeConfig.value.primary); + // 颜色变浅 + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(getThemeConfig.value.primary, i / 10)}`); + } + setDispatchThemeConfig(); + }; + // 2、菜单 / 顶栏 + const onBgColorPickerChange = (bg: string) => { + document.documentElement.style.setProperty(`--next-bg-${bg}`, (<any>getThemeConfig.value)[bg]); + if (bg === 'menuBar') { + document.documentElement.style.setProperty(`--next-bg-menuBar-light-1`, <any>getLightColor(getThemeConfig.value.menuBar, 0.05)); + } + onTopBarGradualChange(); + onMenuBarGradualChange(); + onColumnsMenuBarGradualChange(); + setDispatchThemeConfig(); + }; + // 2、菜单 / 顶栏 --> 顶栏背景渐变 + const onTopBarGradualChange = () => { + setGraduaFun('.layout-navbars-breadcrumb-index', getThemeConfig.value.isTopBarColorGradual, getThemeConfig.value.topBar); + }; + // 2、菜单 / 顶栏 --> 菜单背景渐变 + const onMenuBarGradualChange = () => { + setGraduaFun('.layout-container .el-aside', getThemeConfig.value.isMenuBarColorGradual, getThemeConfig.value.menuBar); + }; + // 2、菜单 / 顶栏 --> 分栏菜单背景渐变 + const onColumnsMenuBarGradualChange = () => { + setGraduaFun('.layout-container .layout-columns-aside', getThemeConfig.value.isColumnsMenuBarColorGradual, getThemeConfig.value.columnsMenuBar); + }; + // 2、菜单 / 顶栏 --> 背景渐变函数 + const setGraduaFun = (el: string, bool: boolean, color: string) => { + setTimeout(() => { + let els = document.querySelector(el); + if (!els) return false; + document.documentElement.style.setProperty('--el-menu-bg-color', document.documentElement.style.getPropertyValue('--next-bg-menuBar')); + if (bool) els.setAttribute('style', `background:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)}) !important;`); + else els.setAttribute('style', ``); + setLocalThemeConfig(); + }, 200); + }; + // 3、界面设置 --> 菜单水平折叠 + const onThemeConfigChange = () => { + setDispatchThemeConfig(); + }; + // 3、界面设置 --> 固定 Header + const onIsFixedHeaderChange = () => { + getThemeConfig.value.isFixedHeaderChange = getThemeConfig.value.isFixedHeader ? false : true; + setLocalThemeConfig(); + }; + // 3、界面设置 --> 经典布局分割菜单 + const onClassicSplitMenuChange = () => { + getThemeConfig.value.isBreadcrumb = false; + setLocalThemeConfig(); + proxy.mittBus.emit('getBreadcrumbIndexSetFilterRoutes'); + }; + // 4、界面显示 --> 侧边栏 Logo + const onIsShowLogoChange = () => { + getThemeConfig.value.isShowLogoChange = getThemeConfig.value.isShowLogo ? false : true; + setLocalThemeConfig(); + }; + // 4、界面显示 --> 面包屑 Breadcrumb + const onIsBreadcrumbChange = () => { + if (getThemeConfig.value.layout === 'classic') { + getThemeConfig.value.isClassicSplitMenu = false; + } + setLocalThemeConfig(); + }; + // 4、界面显示 --> 开启 TagsView 拖拽 + const onSortableTagsViewChange = () => { + proxy.mittBus.emit('openOrCloseSortable'); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 开启 TagsView 共用 + const onShareTagsViewChange = () => { + proxy.mittBus.emit('openShareTagsView'); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 灰色模式/色弱模式 + const onAddFilterChange = (attr: string) => { + if (attr === 'grayscale') { + if (getThemeConfig.value.isGrayscale) getThemeConfig.value.isInvert = false; + } else { + if (getThemeConfig.value.isInvert) getThemeConfig.value.isGrayscale = false; + } + const cssAttr = + attr === 'grayscale' ? `grayscale(${getThemeConfig.value.isGrayscale ? 1 : 0})` : `invert(${getThemeConfig.value.isInvert ? '80%' : '0%'})`; + const appEle: any = document.body; + appEle.setAttribute('style', `filter: ${cssAttr}`); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 深色模式 + const onAddDarkChange = () => { + const body = document.documentElement as HTMLElement; + if (getThemeConfig.value.isIsDark) body.setAttribute('data-theme', 'dark'); + else body.setAttribute('data-theme', ''); + }; + // 4、界面显示 --> 开启水印 + const onWartermarkChange = () => { + getThemeConfig.value.isWartermark ? Watermark.set(getThemeConfig.value.wartermarkText) : Watermark.del(); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 水印文案 + const onWartermarkTextInput = (val: any) => { + getThemeConfig.value.wartermarkText = verifyAndSpace(val); + if (getThemeConfig.value.wartermarkText === '') return false; + if (getThemeConfig.value.isWartermark) Watermark.set(getThemeConfig.value.wartermarkText); + setLocalThemeConfig(); + }; + // 5、布局切换 + const onSetLayout = (layout: string) => { + Local.set('oldLayout', layout); + if (getThemeConfig.value.layout === layout) return false; + if (layout === 'transverse') getThemeConfig.value.isCollapse = false; + getThemeConfig.value.layout = layout; + getThemeConfig.value.isDrawer = false; + initLayoutChangeFun(); + }; + // 设置布局切换函数 + const initLayoutChangeFun = () => { + onBgColorPickerChange('menuBar'); + onBgColorPickerChange('menuBarColor'); + onBgColorPickerChange('topBar'); + onBgColorPickerChange('topBarColor'); + onBgColorPickerChange('columnsMenuBar'); + onBgColorPickerChange('columnsMenuBarColor'); + }; + // 关闭弹窗时,初始化变量。变量用于处理 proxy.$refs.layoutScrollbarRef.update() + const onDrawerClose = () => { + getThemeConfig.value.isFixedHeaderChange = false; + getThemeConfig.value.isShowLogoChange = false; + getThemeConfig.value.isDrawer = false; + setLocalThemeConfig(); + }; + // 布局配置弹窗打开 + const openDrawer = () => { + getThemeConfig.value.isDrawer = true; + }; + // 触发 store 布局配置更新 + const setDispatchThemeConfig = () => { + setLocalThemeConfig(); + setLocalThemeConfigStyle(); + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + Local.remove('themeConfig'); + Local.set('themeConfig', getThemeConfig.value); + }; + // 存储布局配置全局主题样式(html根标签) + const setLocalThemeConfigStyle = () => { + Local.set('themeConfigStyle', document.documentElement.style.cssText); + }; + // 一键复制配置 + const onCopyConfigClick = () => { + let copyThemeConfig = Local.get('themeConfig'); + copyThemeConfig.isDrawer = false; + copyText(JSON.stringify(copyThemeConfig)).then(() => { + getThemeConfig.value.isDrawer = false; + }); + }; + // 一键恢复默认 + const onResetConfigClick = () => { + Local.clear(); + window.location.reload(); + }; + // 初始化菜单样式等 + const initSetStyle = () => { + // 2、菜单 / 顶栏 --> 顶栏背景渐变 + onTopBarGradualChange(); + // 2、菜单 / 顶栏 --> 菜单背景渐变 + onMenuBarGradualChange(); + // 2、菜单 / 顶栏 --> 分栏菜单背景渐变 + onColumnsMenuBarGradualChange(); + }; + onMounted(() => { + nextTick(() => { + // 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题 + if (!Local.get('frequency')) initLayoutChangeFun(); + Local.set('frequency', 1); + // 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端) + proxy.mittBus.on('layoutMobileResize', (res: any) => { + getThemeConfig.value.layout = res.layout; + getThemeConfig.value.isDrawer = false; + initLayoutChangeFun(); + state.isMobile = other.isMobile(); + }); + setTimeout(() => { + // 默认样式 + onColorPickerChange(); + // 灰色模式 + if (getThemeConfig.value.isGrayscale) onAddFilterChange('grayscale'); + // 色弱模式 + if (getThemeConfig.value.isInvert) onAddFilterChange('invert'); + // 深色模式 + if (getThemeConfig.value.isIsDark) onAddDarkChange(); + // 开启水印 + onWartermarkChange(); + // 语言国际化 + if (Local.get('themeConfig')) proxy.$i18n.locale = Local.get('themeConfig').globalI18n; + // 初始化菜单样式等 + initSetStyle(); + }, 100); + }); + }); + onUnmounted(() => { + proxy.mittBus.off('layoutMobileResize', () => {}); + }); + return { + openDrawer, + onColorPickerChange, + onBgColorPickerChange, + onTopBarGradualChange, + onMenuBarGradualChange, + onColumnsMenuBarGradualChange, + onThemeConfigChange, + onIsFixedHeaderChange, + onIsShowLogoChange, + getThemeConfig, + onDrawerClose, + onAddFilterChange, + onAddDarkChange, + onWartermarkChange, + onWartermarkTextInput, + onSetLayout, + setLocalThemeConfig, + onClassicSplitMenuChange, + onIsBreadcrumbChange, + onSortableTagsViewChange, + onShareTagsViewChange, + onCopyConfigClick, + onResetConfigClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-breadcrumb-seting-bar { + height: calc(100vh - 50px); + padding: 0 15px; + ::v-deep(.el-scrollbar__view) { + overflow-x: hidden !important; + } + .layout-breadcrumb-seting-bar-flex { + display: flex; + align-items: center; + margin-bottom: 5px; + &-label { + flex: 1; + color: var(--el-text-color-primary); + } + } + .layout-drawer-content-flex { + overflow: hidden; + display: flex; + flex-wrap: wrap; + align-content: flex-start; + margin: 0 -5px; + .layout-drawer-content-item { + width: 50%; + height: 70px; + cursor: pointer; + border: 1px solid transparent; + position: relative; + padding: 5px; + .el-container { + height: 100%; + .el-aside-dark { + background-color: var(--next-color-seting-header); + } + .el-aside { + background-color: var(--next-color-seting-aside); + } + .el-header { + background-color: var(--next-color-seting-header); + } + .el-main { + background-color: var(--next-color-seting-main); + } + } + .el-circular { + border-radius: 2px; + overflow: hidden; + border: 1px solid transparent; + transition: all 0.3s ease-in-out; + } + .drawer-layout-active { + border: 1px solid; + border-color: var(--el-color-primary); + } + .layout-tips-warp, + .layout-tips-warp-active { + transition: all 0.3s ease-in-out; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + border: 1px solid; + border-color: var(--el-color-primary-light-5); + border-radius: 100%; + padding: 4px; + .layout-tips-box { + transition: inherit; + width: 30px; + height: 30px; + z-index: 9; + border: 1px solid; + border-color: var(--el-color-primary-light-5); + border-radius: 100%; + .layout-tips-txt { + transition: inherit; + position: relative; + top: 5px; + font-size: 12px; + line-height: 1; + letter-spacing: 2px; + white-space: nowrap; + color: var(--el-color-primary-light-5); + text-align: center; + transform: rotate(30deg); + left: -1px; + background-color: var(--next-color-seting-main); + width: 32px; + height: 17px; + line-height: 17px; + } + } + } + .layout-tips-warp-active { + border: 1px solid; + border-color: var(--el-color-primary); + .layout-tips-box { + border: 1px solid; + border-color: var(--el-color-primary); + .layout-tips-txt { + color: var(--el-color-primary) !important; + background-color: var(--next-color-seting-main) !important; + } + } + } + &:hover { + .el-circular { + transition: all 0.3s ease-in-out; + border: 1px solid; + border-color: var(--el-color-primary); + } + .layout-tips-warp { + transition: all 0.3s ease-in-out; + border-color: var(--el-color-primary); + .layout-tips-box { + transition: inherit; + border-color: var(--el-color-primary); + .layout-tips-txt { + transition: inherit; + color: var(--el-color-primary) !important; + background-color: var(--next-color-seting-main) !important; + } + } + } + } + } + } + .copy-config { + margin: 10px 0; + .copy-config-btn { + width: 100%; + margin-top: 15px; + } + .copy-config-btn-reset { + width: 100%; + margin: 10px 0 0; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue new file mode 100644 index 0000000..6782651 --- /dev/null +++ b/src/layout/navBars/breadcrumb/user.vue @@ -0,0 +1,298 @@ +<template> + <div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }"> + <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onComponentSizeChange"> + <div class="layout-navbars-breadcrumb-user-icon"> + <i class="iconfont icon-ziti" :title="$t('message.user.title0')"></i> + </div> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="large" :disabled="disabledSize === 'large'">{{ $t('message.user.dropdownLarge') }}</el-dropdown-item> + <el-dropdown-item command="default" :disabled="disabledSize === 'default'">{{ $t('message.user.dropdownDefault') }}</el-dropdown-item> + <el-dropdown-item command="small" :disabled="disabledSize === 'small'">{{ $t('message.user.dropdownSmall') }}</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange"> + <div class="layout-navbars-breadcrumb-user-icon"> + <i class="iconfont" :class="disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('message.user.title1')"></i> + </div> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="zh-cn" :disabled="disabledI18n === 'zh-cn'">简体中文</el-dropdown-item> + <el-dropdown-item command="en" :disabled="disabledI18n === 'en'">English</el-dropdown-item> + <el-dropdown-item command="zh-tw" :disabled="disabledI18n === 'zh-tw'">繁體中文</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick"> + <el-icon :title="$t('message.user.title2')"> + <ele-Search /> + </el-icon> + </div> + <div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick"> + <i class="icon-skin iconfont" :title="$t('message.user.title3')"></i> + </div> + <div class="layout-navbars-breadcrumb-user-icon"> + <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false"> + <template #reference> + <el-badge :is-dot="true"> + <el-icon :title="$t('message.user.title4')"> + <ele-Bell /> + </el-icon> + </el-badge> + </template> + <template #default> + <UserNews /> + </template> + </el-popover> + </div> + <div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick"> + <i + class="iconfont" + :title="isScreenfull ? $t('message.user.title6') : $t('message.user.title5')" + :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'" + ></i> + </div> + <el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick"> + <span class="layout-navbars-breadcrumb-user-link"> + <img :src="userInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" /> + {{ userInfos.userName === '' ? 'common' : userInfos.userName }} + <el-icon class="el-icon--right"> + <ele-ArrowDown /> + </el-icon> + </span> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="/home">{{ $t('message.user.dropdown1') }}</el-dropdown-item> + <el-dropdown-item command="wareHouse">{{ $t('message.user.dropdown6') }}</el-dropdown-item> + <el-dropdown-item command="/personal">{{ $t('message.user.dropdown2') }}</el-dropdown-item> + <el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item> + <el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item> + <el-dropdown-item divided command="logOut">{{ $t('message.user.dropdown5') }}</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <Search ref="searchRef" /> + </div> +</template> + +<script lang="ts"> +import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { useRouter } from 'vue-router'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import screenfull from 'screenfull'; +import { useI18n } from 'vue-i18n'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import other from '/@/utils/other'; +import { Session, Local } from '/@/utils/storage'; +import UserNews from '/@/layout/navBars/breadcrumb/userNews.vue'; +import Search from '/@/layout/navBars/breadcrumb/search.vue'; + +export default defineComponent({ + name: 'layoutBreadcrumbUser', + components: { UserNews, Search }, + setup() { + const { t } = useI18n(); + const { proxy } = <any>getCurrentInstance(); + const router = useRouter(); + const stores = useUserInfo(); + const storesThemeConfig = useThemeConfig(); + const { userInfos } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const searchRef = ref(); + const state = reactive({ + isScreenfull: false, + disabledI18n: 'zh-cn', + disabledSize: 'large', + }); + // 设置分割样式 + const layoutUserFlexNum = computed(() => { + let num: string | number = ''; + const { layout, isClassicSplitMenu } = themeConfig.value; + const layoutArr: string[] = ['defaults', 'columns']; + if (layoutArr.includes(layout) || (layout === 'classic' && !isClassicSplitMenu)) num = '1'; + else num = ''; + return num; + }); + // 全屏点击时 + const onScreenfullClick = () => { + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(); + screenfull.on('change', () => { + if (screenfull.isFullscreen) state.isScreenfull = true; + else state.isScreenfull = false; + }); + }; + // 布局配置 icon 点击时 + const onLayoutSetingClick = () => { + proxy.mittBus.emit('openSetingsDrawer'); + }; + // 下拉菜单点击时 + const onHandleCommandClick = (path: string) => { + if (path === 'logOut') { + ElMessageBox({ + closeOnClickModal: false, + closeOnPressEscape: false, + title: t('message.user.logOutTitle'), + message: t('message.user.logOutMessage'), + showCancelButton: true, + confirmButtonText: t('message.user.logOutConfirm'), + cancelButtonText: t('message.user.logOutCancel'), + buttonSize: 'default', + beforeClose: (action, instance, done) => { + if (action === 'confirm') { + instance.confirmButtonLoading = true; + instance.confirmButtonText = t('message.user.logOutExit'); + setTimeout(() => { + done(); + setTimeout(() => { + instance.confirmButtonLoading = false; + }, 300); + }, 700); + } else { + done(); + } + }, + }) + .then(async () => { + Session.clear(); // 清除缓存/token等 + // 使用 reload 时,不需要调用 resetRoute() 重置路由 + window.location.reload(); + }) + .catch(() => {}); + } else if (path === 'wareHouse') { + window.open('https://gitee.com/lyt-top/vue-next-admin'); + } else { + router.push(path); + } + }; + // 菜单搜索点击 + const onSearchClick = () => { + searchRef.value.openSearch(); + }; + // 组件大小改变 + const onComponentSizeChange = (size: string) => { + Local.remove('themeConfig'); + themeConfig.value.globalComponentSize = size; + Local.set('themeConfig', themeConfig.value); + initComponentSize(); + window.location.reload(); + }; + // 语言切换 + const onLanguageChange = (lang: string) => { + Local.remove('themeConfig'); + themeConfig.value.globalI18n = lang; + Local.set('themeConfig', themeConfig.value); + proxy.$i18n.locale = lang; + initI18n(); + other.useTitle(); + }; + // 设置 element plus 组件的国际化 + const setI18nConfig = (locale: string) => { + proxy.mittBus.emit('getI18nConfig', proxy.$i18n.messages[locale]); + }; + // 初始化言语国际化 + const initI18n = () => { + switch (Local.get('themeConfig').globalI18n) { + case 'zh-cn': + state.disabledI18n = 'zh-cn'; + setI18nConfig('zh-cn'); + break; + case 'en': + state.disabledI18n = 'en'; + setI18nConfig('en'); + break; + case 'zh-tw': + state.disabledI18n = 'zh-tw'; + setI18nConfig('zh-tw'); + break; + } + }; + // 初始化全局组件大小 + const initComponentSize = () => { + switch (Local.get('themeConfig').globalComponentSize) { + case 'large': + state.disabledSize = 'large'; + break; + case 'default': + state.disabledSize = 'default'; + break; + case 'small': + state.disabledSize = 'small'; + break; + } + }; + // 页面加载时 + onMounted(() => { + if (Local.get('themeConfig')) { + initI18n(); + initComponentSize(); + } + }); + return { + userInfos, + onLayoutSetingClick, + onHandleCommandClick, + onScreenfullClick, + onSearchClick, + onComponentSizeChange, + onLanguageChange, + searchRef, + layoutUserFlexNum, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb-user { + display: flex; + align-items: center; + justify-content: flex-end; + &-link { + height: 100%; + display: flex; + align-items: center; + white-space: nowrap; + &-photo { + width: 25px; + height: 25px; + border-radius: 100%; + } + } + &-icon { + padding: 0 10px; + cursor: pointer; + color: var(--next-bg-topBarColor); + height: 50px; + line-height: 50px; + display: flex; + align-items: center; + &:hover { + background: var(--next-color-user-hover); + i { + display: inline-block; + animation: logoAnimation 0.3s ease-in-out; + } + } + } + ::v-deep(.el-dropdown) { + color: var(--next-bg-topBarColor); + } + ::v-deep(.el-badge) { + height: 40px; + line-height: 40px; + display: flex; + align-items: center; + } + ::v-deep(.el-badge__content.is-fixed) { + top: 12px; + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/userNews.vue b/src/layout/navBars/breadcrumb/userNews.vue new file mode 100644 index 0000000..cae954a --- /dev/null +++ b/src/layout/navBars/breadcrumb/userNews.vue @@ -0,0 +1,115 @@ +<template> + <div class="layout-navbars-breadcrumb-user-news"> + <div class="head-box"> + <div class="head-box-title">{{ $t('message.user.newTitle') }}</div> + <div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">{{ $t('message.user.newBtn') }}</div> + </div> + <div class="content-box"> + <template v-if="newsList.length > 0"> + <div class="content-box-item" v-for="(v, k) in newsList" :key="k"> + <div>{{ v.label }}</div> + <div class="content-box-msg"> + {{ v.value }} + </div> + <div class="content-box-time">{{ v.time }}</div> + </div> + </template> + <el-empty :description="$t('message.user.newDesc')" v-else></el-empty> + </div> + <div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">{{ $t('message.user.newGo') }}</div> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'layoutBreadcrumbUserNews', + setup() { + const state = reactive({ + newsList: [ + { + label: '关于版本发布的通知', + value: 'vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,正式发布时间:2021年02月28日!', + time: '2020-12-08', + }, + { + label: '关于学习交流的通知', + value: 'QQ群号码 665452019,欢迎小伙伴入群学习交流探讨!', + time: '2020-12-08', + }, + ], + }); + // 全部已读点击 + const onAllReadClick = () => { + state.newsList = []; + }; + // 前往通知中心点击 + const onGoToGiteeClick = () => { + window.open('https://gitee.com/lyt-top/vue-next-admin'); + }; + return { + onAllReadClick, + onGoToGiteeClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb-user-news { + .head-box { + display: flex; + border-bottom: 1px solid var(--el-border-color-lighter); + box-sizing: border-box; + color: var(--el-text-color-primary); + justify-content: space-between; + height: 35px; + align-items: center; + .head-box-btn { + color: var(--el-color-primary); + font-size: 13px; + cursor: pointer; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + } + .content-box { + font-size: 13px; + .content-box-item { + padding-top: 12px; + &:last-of-type { + padding-bottom: 12px; + } + .content-box-msg { + color: var(--el-text-color-secondary); + margin-top: 5px; + margin-bottom: 5px; + } + .content-box-time { + color: var(--el-text-color-secondary); + } + } + } + .foot-box { + height: 35px; + color: var(--el-color-primary); + font-size: 13px; + cursor: pointer; + opacity: 0.8; + display: flex; + align-items: center; + justify-content: center; + border-top: 1px solid var(--el-border-color-lighter); + &:hover { + opacity: 1; + } + } + ::v-deep(.el-empty__description p) { + font-size: 13px; + } +} +</style> diff --git a/src/layout/navBars/index.vue b/src/layout/navBars/index.vue new file mode 100644 index 0000000..f41a0cf --- /dev/null +++ b/src/layout/navBars/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="layout-navbars-container"> + <BreadcrumbIndex /> + <TagsView v-if="setShowTagsView" /> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import BreadcrumbIndex from '/@/layout/navBars/breadcrumb/index.vue'; +import TagsView from '/@/layout/navBars/tagsView/tagsView.vue'; + +export default defineComponent({ + name: 'layoutNavBars', + components: { BreadcrumbIndex, TagsView }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 是否显示 tagsView + const setShowTagsView = computed(() => { + let { layout, isTagsview } = themeConfig.value; + return layout !== 'classic' && isTagsview; + }); + return { + setShowTagsView, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-container { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; +} +</style> diff --git a/src/layout/navBars/tagsView/contextmenu.vue b/src/layout/navBars/tagsView/contextmenu.vue new file mode 100644 index 0000000..c717aae --- /dev/null +++ b/src/layout/navBars/tagsView/contextmenu.vue @@ -0,0 +1,138 @@ +<template> + <transition name="el-zoom-in-center"> + <div + aria-hidden="true" + class="el-dropdown__popper el-popper is-light is-pure custom-contextmenu" + role="tooltip" + data-popper-placement="bottom" + :style="`top: ${dropdowns.y + 5}px;left: ${dropdowns.x}px;`" + :key="Math.random()" + v-show="isShow" + > + <ul class="el-dropdown-menu"> + <template v-for="(v, k) in dropdownList"> + <li + class="el-dropdown-menu__item" + aria-disabled="false" + tabindex="-1" + :key="k" + v-if="!v.affix" + @click="onCurrentContextmenuClick(v.contextMenuClickId)" + > + <SvgIcon :name="v.icon" /> + <span>{{ $t(v.txt) }}</span> + </li> + </template> + </ul> + <div class="el-popper__arrow" :style="{ left: `${arrowLeft}px` }"></div> + </div> + </transition> +</template> + +<script lang="ts"> +import { computed, defineComponent, reactive, toRefs, onMounted, onUnmounted, watch } from 'vue'; + +export default defineComponent({ + name: 'layoutTagsViewContextmenu', + props: { + dropdown: { + type: Object, + default: () => { + return { + x: 0, + y: 0, + }; + }, + }, + }, + setup(props, { emit }) { + const state = reactive({ + isShow: false, + dropdownList: [ + { contextMenuClickId: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'ele-RefreshRight' }, + { contextMenuClickId: 1, txt: 'message.tagsView.close', affix: false, icon: 'ele-Close' }, + { contextMenuClickId: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'ele-CircleClose' }, + { contextMenuClickId: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'ele-FolderDelete' }, + { + contextMenuClickId: 4, + txt: 'message.tagsView.fullscreen', + affix: false, + icon: 'iconfont icon-fullscreen', + }, + ], + item: {}, + arrowLeft: 10, + }); + // 父级传过来的坐标 x,y 值 + const dropdowns = computed(() => { + // 117 为 `Dropdown 下拉菜单` 的宽度 + if (props.dropdown.x + 117 > document.documentElement.clientWidth) { + return { + x: document.documentElement.clientWidth - 117 - 5, + y: props.dropdown.y, + }; + } else { + return props.dropdown; + } + }); + // 当前项菜单点击 + const onCurrentContextmenuClick = (contextMenuClickId: number) => { + emit('currentContextmenuClick', Object.assign({}, { contextMenuClickId }, state.item)); + }; + // 打开右键菜单:判断是否固定,固定则不显示关闭按钮 + const openContextmenu = (item: any) => { + state.item = item; + item.meta.isAffix ? (state.dropdownList[1].affix = true) : (state.dropdownList[1].affix = false); + closeContextmenu(); + setTimeout(() => { + state.isShow = true; + }, 10); + }; + // 关闭右键菜单 + const closeContextmenu = () => { + state.isShow = false; + }; + // 监听页面监听进行右键菜单的关闭 + onMounted(() => { + document.body.addEventListener('click', closeContextmenu); + }); + // 页面卸载时,移除右键菜单监听事件 + onUnmounted(() => { + document.body.removeEventListener('click', closeContextmenu); + }); + // 监听下拉菜单位置 + watch( + () => props.dropdown, + ({ x }) => { + if (x + 117 > document.documentElement.clientWidth) state.arrowLeft = 117 - (document.documentElement.clientWidth - x); + else state.arrowLeft = 10; + }, + { + deep: true, + } + ); + return { + dropdowns, + openContextmenu, + closeContextmenu, + onCurrentContextmenuClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.custom-contextmenu { + transform-origin: center top; + z-index: 2190; + position: fixed; + .el-dropdown-menu__item { + font-size: 12px !important; + white-space: nowrap; + i { + font-size: 12px !important; + } + } +} +</style> diff --git a/src/layout/navBars/tagsView/tagsView.vue b/src/layout/navBars/tagsView/tagsView.vue new file mode 100644 index 0000000..67e1b57 --- /dev/null +++ b/src/layout/navBars/tagsView/tagsView.vue @@ -0,0 +1,734 @@ +<template> + <div class="layout-navbars-tagsview" :class="{ 'layout-navbars-tagsview-shadow': getThemeConfig.layout === 'classic' }"> + <el-scrollbar ref="scrollbarRef" @wheel.prevent="onHandleScroll"> + <ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef"> + <li + v-for="(v, k) in tagsViewList" + :key="k" + class="layout-navbars-tagsview-ul-li" + :data-url="v.url" + :class="{ 'is-active': isActive(v) }" + @contextmenu.prevent="onContextmenu(v, $event)" + @click="onTagsClick(v, k)" + :ref=" + (el) => { + if (el) tagsRefs[k] = el; + } + " + > + <i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont" v-if="isActive(v)"></i> + <SvgIcon :name="v.meta.icon" v-if="!isActive(v) && getThemeConfig.isTagsviewIcon" class="pr5" /> + <span>{{ setTagsViewNameI18n(v) }}</span> + <template v-if="isActive(v)"> + <SvgIcon + name="ele-RefreshRight" + class="ml5 layout-navbars-tagsview-ul-li-refresh" + @click.stop="refreshCurrentTagsView($route.fullPath)" + /> + <SvgIcon + name="ele-Close" + class="layout-navbars-tagsview-ul-li-icon layout-icon-active" + v-if="!v.meta.isAffix" + @click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)" + /> + </template> + <SvgIcon + name="ele-Close" + class="layout-navbars-tagsview-ul-li-icon layout-icon-three" + v-if="!v.meta.isAffix" + @click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)" + /> + </li> + </ul> + </el-scrollbar> + <Contextmenu :dropdown="dropdown" ref="contextmenuRef" @currentContextmenuClick="onCurrentContextmenuClick" /> + </div> +</template> + +<script lang="ts"> +import { + toRefs, + reactive, + onMounted, + computed, + ref, + nextTick, + onBeforeUpdate, + onBeforeMount, + onUnmounted, + getCurrentInstance, + watch, + defineComponent, +} from 'vue'; +import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'; +import Sortable from 'sortablejs'; +import { ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { Session } from '/@/utils/storage'; +import { isObjectValueEqual } from '/@/utils/arrayOperation'; +import other from '/@/utils/other'; +import Contextmenu from '/@/layout/navBars/tagsView/contextmenu.vue'; + +// 定义接口来定义对象的类型 +interface TagsViewState { + routeActive: string; + routePath: string | unknown; + dropdown: { + x: string | number; + y: string | number; + }; + sortable: any; + tagsRefsIndex: number; + tagsViewList: any[]; + tagsViewRoutesList: any[]; +} +interface RouteParams { + path: string; + url: string; + query: object; + params: object; +} +interface CurrentContextmenu { + meta: { + isDynamic: boolean; + }; + params: any; + query: any; + path: string; + contextMenuClickId: string | number; +} + +export default defineComponent({ + name: 'layoutTagsView', + components: { Contextmenu }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const tagsRefs = ref<any[]>([]); + const scrollbarRef = ref(); + const contextmenuRef = ref(); + const tagsUlRef = ref(); + const stores = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes); + const storesKeepALiveNames = useKeepALiveNames(); + const route = useRoute(); + const router = useRouter(); + const state = reactive<TagsViewState>({ + routeActive: '', + routePath: route.path, + dropdown: { x: '', y: '' }, + sortable: '', + tagsRefsIndex: 0, + tagsViewList: [], + tagsViewRoutesList: [], + }); + // 动态设置 tagsView 风格样式 + const setTagsStyle = computed(() => { + return themeConfig.value.tagsStyle; + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + const setTagsViewNameI18n = computed(() => { + return (v: any) => { + return other.setTagsViewNameI18n(v); + }; + }); + // 设置 tagsView 高亮 + const isActive = (v: RouteParams) => { + if (getThemeConfig.value.isShareTagsView) { + return v.path === state.routePath; + } else { + if ((v.query && Object.keys(v.query).length) || (v.params && Object.keys(v.params).length)) { + // 普通传参 + return v.url ? v.url === state.routeActive : v.path === state.routeActive; + } else { + // 通过 name 传参,params 取值,刷新页面参数消失 + // https://gitee.com/lyt-top/vue-next-admin/issues/I51RS9 + return v.path === state.routePath; + } + } + }; + // 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录 + const addBrowserSetSession = (tagsViewList: Array<object>) => { + Session.set('tagsViewList', tagsViewList); + }; + // 获取 vuex 中的 tagsViewRoutes 列表 + const getTagsViewRoutes = async () => { + state.routeActive = await setTagsViewHighlight(route); + state.routePath = (await route.meta.isDynamic) ? route.meta.isDynamicPath : route.path; + state.tagsViewList = []; + state.tagsViewRoutesList = tagsViewRoutes.value; + initTagsView(); + }; + // vuex 中获取路由信息:如果是设置了固定的(isAffix),进行初始化显示 + const initTagsView = async () => { + if (Session.get('tagsViewList') && getThemeConfig.value.isCacheTagsView) { + state.tagsViewList = await Session.get('tagsViewList'); + } else { + await state.tagsViewRoutesList.map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + storesKeepALiveNames.addCachedView(v); + } + }); + await addTagsView(route.path, route); + } + // 初始化当前元素(li)的下标 + getTagsRefsIndex(getThemeConfig.value.isShareTagsView ? state.routePath : state.routeActive); + }; + // 处理可开启多标签详情,单标签详情(动态路由(xxx/:id/:name"),普通路由处理) + const solveAddTagsView = async (path: string, to?: any) => { + let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path; + let current = state.tagsViewList.filter( + (v: any) => + v.path === isDynamicPath && + isObjectValueEqual( + to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null + ) + ); + if (current.length <= 0) { + // 防止:Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead. + let findItem = state.tagsViewRoutesList.find((v: any) => v.path === isDynamicPath); + if (!findItem) return false; + if (findItem.meta.isAffix) return false; + if (findItem.meta.isLink && !findItem.meta.isIframe) return false; + to.meta.isDynamic ? (findItem.params = to.params) : (findItem.query = to.query); + findItem.url = setTagsViewHighlight(findItem); + state.tagsViewList.push({ ...findItem }); + await storesKeepALiveNames.addCachedView(findItem); + addBrowserSetSession(state.tagsViewList); + } + }; + // 处理单标签时,第二次的值未覆盖第一次的 tagsViewList 值(Session Storage) + const singleAddTagsView = (path: string, to?: any) => { + let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path; + state.tagsViewList.forEach((v) => { + if ( + v.path === isDynamicPath && + !isObjectValueEqual( + to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null + ) + ) { + to.meta.isDynamic ? (v.params = to.params) : (v.query = to.query); + v.url = setTagsViewHighlight(v); + addBrowserSetSession(state.tagsViewList); + } + }); + }; + // 1、添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中(可开启多标签详情,单标签详情) + const addTagsView = (path: string, to?: any) => { + // 防止拿取不到路由信息 + nextTick(async () => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + let item: any = ''; + if (to && to.meta.isDynamic) { + // 动态路由(xxx/:id/:name"):参数不同,开启多个 tagsview + if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to); + else await singleAddTagsView(path, to); + if (state.tagsViewList.some((v: any) => v.path === to.meta.isDynamicPath)) return false; + item = state.tagsViewRoutesList.find((v: any) => v.path === to.meta.isDynamicPath); + } else { + // 普通路由:参数不同,开启多个 tagsview + if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to); + else await singleAddTagsView(path, to); + if (state.tagsViewList.some((v: any) => v.path === path)) return false; + item = state.tagsViewRoutesList.find((v: any) => v.path === path); + } + if (!item) return false; + if (item.meta.isLink && !item.meta.isIframe) return false; + if (to && to.meta.isDynamic) item.params = to?.params ? to?.params : route.params; + else item.query = to?.query ? to?.query : route.query; + item.url = setTagsViewHighlight(item); + await storesKeepALiveNames.addCachedView(item); + await state.tagsViewList.push({ ...item }); + await addBrowserSetSession(state.tagsViewList); + }); + }; + // 2、刷新当前 tagsView: + const refreshCurrentTagsView = async (fullPath: string) => { + const item = state.tagsViewList.find((v: any) => (getThemeConfig.value.isShareTagsView ? v.path === fullPath : v.url === fullPath)); + if (item != null) { + await storesKeepALiveNames.delCachedView(item); + proxy.mittBus.emit('onTagsViewRefreshRouterView', fullPath); + if (item.meta.isKeepAlive) storesKeepALiveNames.addCachedView(item); + } + }; + // 3、关闭当前 tagsView:如果是设置了固定的(isAffix),不可以关闭 + const closeCurrentTagsView = (path: string) => { + state.tagsViewList.map((v: any, k: number, arr: any) => { + if (!v.meta.isAffix) { + if (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path) { + storesKeepALiveNames.delCachedView(v); + state.tagsViewList.splice(k, 1); + setTimeout(() => { + if (state.tagsViewList.length === k && getThemeConfig.value.isShareTagsView ? state.routePath === path : state.routeActive === path) { + // 最后一个且高亮时 + if (arr[arr.length - 1].meta.isDynamic) { + // 动态路由(xxx/:id/:name") + if (k !== arr.length) router.push({ name: arr[k].name, params: arr[k].params }); + else router.push({ name: arr[arr.length - 1].name, params: arr[arr.length - 1].params }); + } else { + // 普通路由 + if (k !== arr.length) router.push({ path: arr[k].path, query: arr[k].query }); + else router.push({ path: arr[arr.length - 1].path, query: arr[arr.length - 1].query }); + } + } else { + // 非最后一个且高亮时,跳转到下一个 + if (state.tagsViewList.length !== k && getThemeConfig.value.isShareTagsView ? state.routePath === path : state.routeActive === path) { + if (arr[k].meta.isDynamic) { + // 动态路由(xxx/:id/:name") + router.push({ name: arr[k].name, params: arr[k].params }); + } else { + // 普通路由 + router.push({ path: arr[k].path, query: arr[k].query }); + } + } + } + }, 0); + } + } + }); + addBrowserSetSession(state.tagsViewList); + }; + // 4、关闭其它 tagsView:如果是设置了固定的(isAffix),不进行关闭 + const closeOtherTagsView = (path: string) => { + if (Session.get('tagsViewList')) { + state.tagsViewList = []; + Session.get('tagsViewList').map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + storesKeepALiveNames.delOthersCachedViews(v); + state.tagsViewList.push({ ...v }); + } + }); + addTagsView(path, route); + addBrowserSetSession(state.tagsViewList); + } + }; + // 5、关闭全部 tagsView:如果是设置了固定的(isAffix),不进行关闭 + const closeAllTagsView = () => { + if (Session.get('tagsViewList')) { + storesKeepALiveNames.delAllCachedViews(); + state.tagsViewList = []; + Session.get('tagsViewList').map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + router.push({ path: state.tagsViewList[state.tagsViewList.length - 1].path }); + } + }); + addBrowserSetSession(state.tagsViewList); + } + }; + // 6、开启当前页面全屏 + const openCurrenFullscreen = async (path: string) => { + const item = state.tagsViewList.find((v: any) => (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path)); + if (item.meta.isDynamic) await router.push({ name: item.name, params: item.params }); + else await router.push({ name: item.name, query: item.query }); + stores.setCurrenFullscreen(true); + }; + // 当前项右键菜单点击,拿当前点击的路由路径对比 浏览器缓存中的 tagsView 路由数组,取当前点击项的详细路由信息 + // 防止 tagsView 非当前页演示时,操作异常 + const getCurrentRouteItem = (path: string, cParams: any) => { + const itemRoute = Session.get('tagsViewList') ? Session.get('tagsViewList') : state.tagsViewList; + return itemRoute.find((v: any) => { + if ( + v.path === path && + isObjectValueEqual( + v.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + cParams && Object.keys(cParams ? cParams : {}).length > 0 ? cParams : null + ) + ) { + return v; + } else if (v.path === path && Object.keys(cParams ? cParams : {}).length <= 0) { + return v; + } + }); + }; + // 当前项右键菜单点击 + const onCurrentContextmenuClick = async (item: CurrentContextmenu) => { + const cParams = item.meta.isDynamic ? item.params : item.query; + if (!getCurrentRouteItem(item.path, cParams)) return ElMessage({ type: 'warning', message: '请正确输入路径及完整参数(query、params)' }); + const { path, name, params, query, meta, url } = getCurrentRouteItem(item.path, cParams); + switch (item.contextMenuClickId) { + case 0: + // 刷新当前 + if (meta.isDynamic) await router.push({ name, params }); + else await router.push({ path, query }); + refreshCurrentTagsView(route.fullPath); + break; + case 1: + // 关闭当前 + closeCurrentTagsView(getThemeConfig.value.isShareTagsView ? path : url); + break; + case 2: + // 关闭其它 + if (meta.isDynamic) await router.push({ name, params }); + else await router.push({ path, query }); + closeOtherTagsView(path); + break; + case 3: + // 关闭全部 + closeAllTagsView(); + break; + case 4: + // 开启当前页面全屏 + openCurrenFullscreen(getThemeConfig.value.isShareTagsView ? path : url); + break; + } + }; + // 右键点击时:传 x,y 坐标值到子组件中(props) + const onContextmenu = (v: any, e: any) => { + const { clientX, clientY } = e; + state.dropdown.x = clientX; + state.dropdown.y = clientY; + contextmenuRef.value.openContextmenu(v); + }; + // 当前的 tagsView 项点击时 + const onTagsClick = (v: any, k: number) => { + state.tagsRefsIndex = k; + router.push(v); + }; + // 处理 tagsView 高亮(多标签详情时使用,单标签详情未使用) + const setTagsViewHighlight = (v: any) => { + let params = v.query && Object.keys(v.query).length > 0 ? v.query : v.params; + if (!params || Object.keys(params).length <= 0) return v.path; + let path = ''; + for (let i in params) { + path += params[i]; + } + // 判断是否是动态路由(xxx/:id/:name") + return `${v.meta.isDynamic ? v.meta.isDynamicPath : v.path}-${path}`; + }; + // 更新滚动条显示 + const updateScrollbar = () => { + proxy.$refs.scrollbarRef.update(); + }; + // 鼠标滚轮滚动 + const onHandleScroll = (e: any) => { + proxy.$refs.scrollbarRef.$refs.wrap$.scrollLeft += e.wheelDelta / 4; + }; + // tagsView 横向滚动 + const tagsViewmoveToCurrentTag = () => { + nextTick(() => { + if (tagsRefs.value.length <= 0) return false; + // 当前 li 元素 + let liDom = tagsRefs.value[state.tagsRefsIndex]; + // 当前 li 元素下标 + let liIndex = state.tagsRefsIndex; + // 当前 ul 下 li 元素总长度 + let liLength = tagsRefs.value.length; + // 最前 li + let liFirst: any = tagsRefs.value[0]; + // 最后 li + let liLast: any = tagsRefs.value[tagsRefs.value.length - 1]; + // 当前滚动条的值 + let scrollRefs = proxy.$refs.scrollbarRef.$refs.wrap$; + // 当前滚动条滚动宽度 + let scrollS = scrollRefs.scrollWidth; + // 当前滚动条偏移宽度 + let offsetW = scrollRefs.offsetWidth; + // 当前滚动条偏移距离 + let scrollL = scrollRefs.scrollLeft; + // 上一个 tags li dom + let liPrevTag: any = tagsRefs.value[state.tagsRefsIndex - 1]; + // 下一个 tags li dom + let liNextTag: any = tagsRefs.value[state.tagsRefsIndex + 1]; + // 上一个 tags li dom 的偏移距离 + let beforePrevL: any = ''; + // 下一个 tags li dom 的偏移距离 + let afterNextL: any = ''; + if (liDom === liFirst) { + // 头部 + scrollRefs.scrollLeft = 0; + } else if (liDom === liLast) { + // 尾部 + scrollRefs.scrollLeft = scrollS - offsetW; + } else { + // 非头/尾部 + if (liIndex === 0) beforePrevL = liFirst.offsetLeft - 5; + else beforePrevL = liPrevTag?.offsetLeft - 5; + if (liIndex === liLength) afterNextL = liLast.offsetLeft + liLast.offsetWidth + 5; + else afterNextL = liNextTag.offsetLeft + liNextTag.offsetWidth + 5; + if (afterNextL > scrollL + offsetW) { + scrollRefs.scrollLeft = afterNextL - offsetW; + } else if (beforePrevL < scrollL) { + scrollRefs.scrollLeft = beforePrevL; + } + } + // 更新滚动条,防止不出现 + updateScrollbar(); + }); + }; + // 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动 + const getTagsRefsIndex = (path: string | unknown) => { + nextTick(async () => { + // await 使用该写法,防止拿取不到 tagsViewList 列表数据不完整 + let tagsViewList = await state.tagsViewList; + state.tagsRefsIndex = tagsViewList.findIndex((v: any) => { + if (getThemeConfig.value.isShareTagsView) { + return v.path === path; + } else { + return v.url === path; + } + }); + // 添加初始化横向滚动条移动到对应位置 + tagsViewmoveToCurrentTag(); + }); + }; + // 设置 tagsView 可以进行拖拽 + const initSortable = async () => { + const el = <HTMLElement>document.querySelector('.layout-navbars-tagsview-ul'); + if (!el) return false; + state.sortable.el && state.sortable.destroy(); + state.sortable = Sortable.create(el, { + animation: 300, + dataIdAttr: 'data-url', + disabled: getThemeConfig.value.isSortableTagsView ? false : true, + onEnd: () => { + const sortEndList: any = []; + state.sortable.toArray().map((val: any) => { + state.tagsViewList.map((v: any) => { + if (v.url === val) sortEndList.push({ ...v }); + }); + }); + addBrowserSetSession(sortEndList); + }, + }); + }; + // 拖动问题,https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI + const onSortableResize = async () => { + await initSortable(); + if (other.isMobile()) state.sortable.el && state.sortable.destroy(); + }; + // 页面加载前 + onBeforeMount(() => { + // 初始化,防止手机端直接访问时还可以拖拽 + onSortableResize(); + // 拖动问题,https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI + window.addEventListener('resize', onSortableResize); + // 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部 4 当前页全屏 + proxy.mittBus.on('onCurrentContextmenuClick', (data: CurrentContextmenu) => { + onCurrentContextmenuClick(data); + }); + // 监听布局配置界面开启/关闭拖拽 + proxy.mittBus.on('openOrCloseSortable', () => { + initSortable(); + }); + // 监听布局配置开启 TagsView 共用,为了演示还原默认值 + proxy.mittBus.on('openShareTagsView', () => { + if (getThemeConfig.value.isShareTagsView) { + router.push('/home'); + state.tagsViewList = []; + state.tagsViewRoutesList.map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + } + }); + } + }); + }); + // 页面卸载时 + onUnmounted(() => { + // 取消非本页面调用监听 + proxy.mittBus.off('onCurrentContextmenuClick', () => {}); + // 取消监听布局配置界面开启/关闭拖拽 + proxy.mittBus.off('openOrCloseSortable', () => {}); + // 取消监听布局配置开启 TagsView 共用 + proxy.mittBus.off('openShareTagsView', () => {}); + // 取消窗口 resize 监听 + window.removeEventListener('resize', onSortableResize); + }); + // 页面更新时 + onBeforeUpdate(() => { + tagsRefs.value = []; + }); + // 页面加载时 + onMounted(() => { + // 初始化 pinia 中的 tagsViewRoutes 列表 + getTagsViewRoutes(); + initSortable(); + }); + // 路由更新时(组件内生命钩子) + onBeforeRouteUpdate(async (to) => { + state.routeActive = setTagsViewHighlight(to); + state.routePath = to.meta.isDynamic ? to.meta.isDynamicPath : to.path; + await addTagsView(to.path, to); + getTagsRefsIndex(getThemeConfig.value.isShareTagsView ? state.routePath : state.routeActive); + }); + // 监听路由的变化,动态赋值给 tagsView + watch( + pinia.state, + (val) => { + if (val.tagsViewRoutes.tagsViewRoutes.length === state.tagsViewRoutesList.length) return false; + getTagsViewRoutes(); + }, + { + deep: true, + } + ); + return { + isActive, + onContextmenu, + onTagsClick, + tagsRefs, + contextmenuRef, + scrollbarRef, + tagsUlRef, + onHandleScroll, + getThemeConfig, + setTagsStyle, + setTagsViewNameI18n, + refreshCurrentTagsView, + closeCurrentTagsView, + onCurrentContextmenuClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-tagsview { + background-color: var(--el-color-white); + border-bottom: 1px solid var(--next-border-color-light); + position: relative; + z-index: 4; + ::v-deep(.el-scrollbar__wrap) { + overflow-x: auto !important; + } + &-ul { + list-style: none; + margin: 0; + padding: 0; + height: 34px; + display: flex; + align-items: center; + color: var(--el-text-color-regular); + font-size: 12px; + white-space: nowrap; + padding: 0 15px; + &-li { + height: 26px; + line-height: 26px; + display: flex; + align-items: center; + border: 1px solid var(--el-border-color-lighter); + padding: 0 15px; + margin-right: 5px; + border-radius: 2px; + position: relative; + z-index: 0; + cursor: pointer; + justify-content: space-between; + &:hover { + background-color: var(--el-color-primary-light-9); + color: var(--el-color-primary); + border-color: var(--el-color-primary-light-5); + } + &-iconfont { + position: relative; + left: -5px; + font-size: 12px; + } + &-icon { + border-radius: 100%; + position: relative; + height: 14px; + width: 14px; + text-align: center; + line-height: 14px; + right: -5px; + &:hover { + color: var(--el-color-white); + background-color: var(--el-color-primary-light-3); + } + } + .layout-icon-active { + display: block; + } + .layout-icon-three { + display: none; + } + } + .is-active { + color: var(--el-color-white); + background: var(--el-color-primary); + border-color: var(--el-color-primary); + transition: border-color 3s ease; + } + } + // 风格4 + .tags-style-four { + .layout-navbars-tagsview-ul-li { + margin-right: 0 !important; + border: none !important; + position: relative; + border-radius: 3px !important; + .layout-icon-active { + display: none; + } + .layout-icon-three { + display: block; + } + &:hover { + background: none !important; + } + } + .is-active { + background: none !important; + color: var(--el-color-primary) !important; + } + } + // 风格5 + .tags-style-five { + align-items: flex-end; + .tags-style-five-svg { + -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='68' height='34' viewBox='0 0 68 34' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m27,0c-7.99582,0 -11.95105,0.00205 -12,12l0,6c0,8.284 -0.48549,16.49691 -8.76949,16.49691l54.37857,-0.11145c-8.284,0 -8.60908,-8.10146 -8.60908,-16.38546l0,-6c0.11145,-12.08445 -4.38441,-12 -12,-12l-13,0z' fill='%23409eff'/%3E%3C/svg%3E") + 12 27 15; + } + .layout-navbars-tagsview-ul-li { + padding: 0 5px; + border-width: 15px 27px 15px; + border-style: solid; + border-color: transparent; + margin: 0 -15px; + .layout-icon-active, + .layout-navbars-tagsview-ul-li-iconfont, + .layout-navbars-tagsview-ul-li-refresh { + display: none; + } + .layout-icon-three { + display: block; + } + &:hover { + @extend .tags-style-five-svg; + background: var(--el-color-primary-light-9); + color: unset; + } + } + .is-active { + @extend .tags-style-five-svg; + background: var(--el-color-primary-light-9) !important; + color: var(--el-color-primary) !important; + z-index: 1; + } + } +} +.layout-navbars-tagsview-shadow { + box-shadow: rgb(0 21 41 / 4%) 0px 1px 4px; +} +</style> diff --git a/src/layout/navMenu/horizontal.vue b/src/layout/navMenu/horizontal.vue new file mode 100644 index 0000000..f738dd6 --- /dev/null +++ b/src/layout/navMenu/horizontal.vue @@ -0,0 +1,157 @@ +<template> + <div class="el-menu-horizontal-warp"> + <el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef"> + <el-menu router :default-active="defaultActive" :ellipsis="false" background-color="transparent" mode="horizontal"> + <template v-for="val in menuLists"> + <el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <SubItem :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </template> + <template #title v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </a> + </template> + </el-menu-item> + </template> + </template> + </el-menu> + </el-scrollbar> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, getCurrentInstance, onMounted, nextTick, onBeforeMount } from 'vue'; +import { useRoute, onBeforeRouteUpdate } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import SubItem from '/@/layout/navMenu/subItem.vue'; + +export default defineComponent({ + name: 'navMenuHorizontal', + components: { SubItem }, + props: { + menuList: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { routesList } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive({ + defaultActive: null, + }); + // 获取父级菜单数据 + const menuLists = computed(() => { + return <any>props.menuList; + }); + // 设置横向滚动条可以鼠标滚轮滚动 + const onElMenuHorizontalScroll = (e: any) => { + const eventDelta = e.wheelDelta || -e.deltaY * 40; + proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft + eventDelta / 4; + }; + // 初始化数据,页面刷新时,滚动条滚动到对应位置 + const initElMenuOffsetLeft = () => { + nextTick(() => { + let els: any = document.querySelector('.el-menu.el-menu--horizontal li.is-active'); + if (!els) return false; + proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = els.offsetLeft; + }); + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 传送当前子级数据到菜单中 + const setSendClassicChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + filterRoutesFun(routesList.value).map((v, k) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 设置页面当前路由高亮 + const setCurrentRouterHighlight = (currentRoute: any) => { + const { path, meta } = currentRoute; + if (themeConfig.value.layout === 'classic') { + (<any>state.defaultActive) = `/${path.split('/')[1]}`; + } else { + const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/'); + if (pathSplit.length >= 4 && meta.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/'); + else state.defaultActive = path; + } + }; + // 页面加载前 + onBeforeMount(() => { + setCurrentRouterHighlight(route); + }); + // 页面加载时 + onMounted(() => { + initElMenuOffsetLeft(); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + setCurrentRouterHighlight(to); + // 修复经典布局开启切割菜单时,点击tagsView后左侧导航菜单数据不变的问题 + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + proxy.mittBus.emit('setSendClassicChildren', setSendClassicChildren(to.path)); + } + }); + return { + menuLists, + onElMenuHorizontalScroll, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.el-menu-horizontal-warp { + flex: 1; + overflow: hidden; + margin-right: 30px; + ::v-deep(.el-scrollbar__bar.is-vertical) { + display: none; + } + ::v-deep(a) { + width: 100%; + } + .el-menu.el-menu--horizontal { + display: flex; + height: 100%; + width: 100%; + box-sizing: border-box; + } +} +</style> diff --git a/src/layout/navMenu/subItem.vue b/src/layout/navMenu/subItem.vue new file mode 100644 index 0000000..3fcefd3 --- /dev/null +++ b/src/layout/navMenu/subItem.vue @@ -0,0 +1,48 @@ +<template> + <template v-for="val in chils"> + <el-sub-menu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <sub-item :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <template v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </a> + </template> + </el-menu-item> + </template> + </template> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'navMenuSubItem', + props: { + chil: { + type: Array, + default: () => [], + }, + }, + setup(props) { + // 获取父级菜单数据 + const chils = computed(() => { + return <any>props.chil; + }); + return { + chils, + }; + }, +}); +</script> diff --git a/src/layout/navMenu/vertical.vue b/src/layout/navMenu/vertical.vue new file mode 100644 index 0000000..1bfa825 --- /dev/null +++ b/src/layout/navMenu/vertical.vue @@ -0,0 +1,101 @@ +<template> + <el-menu + router + :default-active="defaultActive" + background-color="transparent" + :collapse="isCollapse" + :unique-opened="getThemeConfig.isUniqueOpened" + :collapse-transition="false" + > + <template v-for="val in menuLists"> + <el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <SubItem :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <SvgIcon :name="val.meta.icon" /> + <template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <span>{{ $t(val.meta.title) }}</span> + </template> + <template #title v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100">{{ $t(val.meta.title) }}</a> + </template> + </el-menu-item> + </template> + </template> + </el-menu> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, onMounted, watch } from 'vue'; +import { useRoute, onBeforeRouteUpdate } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import SubItem from '/@/layout/navMenu/subItem.vue'; + +export default defineComponent({ + name: 'navMenuVertical', + components: { SubItem }, + props: { + menuList: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive({ + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + defaultActive: route.meta.isDynamic ? route.meta.isDynamicPath : route.path, + isCollapse: false, + }); + // 获取父级菜单数据 + const menuLists = computed(() => { + return <any>props.menuList; + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 菜单高亮(详情时,父级高亮) + const setParentHighlight = (currentRoute: any) => { + const { path, meta } = currentRoute; + const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/'); + if (pathSplit.length >= 4 && meta.isHide) return pathSplit.splice(0, 3).join('/'); + else return path; + }; + // 设置菜单的收起/展开 + watch( + themeConfig.value, + () => { + document.body.clientWidth <= 1000 ? (state.isCollapse = false) : (state.isCollapse = themeConfig.value.isCollapse); + }, + { + immediate: true, + } + ); + // 页面加载时 + onMounted(() => { + state.defaultActive = setParentHighlight(route); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + state.defaultActive = setParentHighlight(to); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) themeConfig.value.isCollapse = false; + }); + return { + menuLists, + getThemeConfig, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/routerView/iframes.vue b/src/layout/routerView/iframes.vue new file mode 100644 index 0000000..43e71c5 --- /dev/null +++ b/src/layout/routerView/iframes.vue @@ -0,0 +1,66 @@ +<template> + <div class="layout-view-bg-white flex mt1" :style="{ height: `calc(100vh - ${setIframeHeight}`, border: 'none' }" v-loading="iframeLoading"> + <iframe :src="iframeUrl" frameborder="0" height="100%" width="100%" ref="iframeDom" v-show="!iframeLoading"></iframe> + </div> +</template> + +<script lang="ts"> +import { defineComponent, reactive, toRefs, onMounted, nextTick, watch, computed } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useRoute } from 'vue-router'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: 'layoutIfameView', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const route = useRoute(); + const state = reactive({ + iframeDom: null as HTMLIFrameElement | null, + iframeLoading: true, + iframeUrl: '', + }); + // 初始化页面加载 loading + const initIframeLoad = () => { + state.iframeUrl = <any>route.meta.isLink; + nextTick(() => { + state.iframeLoading = true; + const iframe = state.iframeDom; + if (!iframe) return false; + iframe.onload = () => { + state.iframeLoading = false; + }; + }); + }; + // 设置 iframe 的高度 + const setIframeHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `1px`; + } else { + if (isTagsview) return `86px`; + else return `51px`; + } + }); + // 页面加载时 + onMounted(() => { + initIframeLoad(); + }); + // 监听路由变化,多个 iframe 时使用 + watch( + () => route.path, + () => { + initIframeLoad(); + } + ); + return { + setIframeHeight, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/routerView/link.vue b/src/layout/routerView/link.vue new file mode 100644 index 0000000..a48f002 --- /dev/null +++ b/src/layout/routerView/link.vue @@ -0,0 +1,61 @@ +<template> + <div class="layout-view-bg-white flex layout-view-link" :style="{ height: `calc(100vh - ${setLinkHeight}` }"> + <a :href="currentRouteMeta.isLink" target="_blank" rel="opener" class="flex-margin"> + {{ $t(currentRouteMeta.title) }}:{{ currentRouteMeta.isLink }} + </a> + </div> +</template> + +<script lang="ts"> +import { defineComponent, toRefs, reactive, computed, watch } from 'vue'; +import { useRoute, RouteMeta } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface LinkViewState { + currentRouteMeta: { + isLink: string; + title: string; + }; +} +interface LinkViewRouteMeta extends RouteMeta { + isLink: string; + title: string; +} + +export default defineComponent({ + name: 'layoutLinkView', + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive<LinkViewState>({ + currentRouteMeta: { + isLink: '', + title: '', + }, + }); + // 设置 link 的高度 + const setLinkHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsview) return `115px`; + else return `80px`; + }); + // 监听路由的变化,设置内容 + watch( + () => route.path, + () => { + state.currentRouteMeta = <LinkViewRouteMeta>route.meta; + }, + { + immediate: true, + } + ); + return { + setLinkHeight, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/routerView/parent.vue b/src/layout/routerView/parent.vue new file mode 100644 index 0000000..db22141 --- /dev/null +++ b/src/layout/routerView/parent.vue @@ -0,0 +1,88 @@ +<template> + <div class="h100"> + <router-view v-slot="{ Component }"> + <transition :name="setTransitionName" mode="out-in"> + <keep-alive :include="getKeepAliveNames"> + <component :is="Component" :key="refreshRouterViewKey" class="w100" /> + </keep-alive> + </transition> + </router-view> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent, toRefs, reactive, getCurrentInstance, onBeforeMount, onUnmounted, nextTick, watch, onMounted } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Session } from '/@/utils/storage'; + +// 定义接口来定义对象的类型 +interface ParentViewState { + refreshRouterViewKey: null | string; + keepAliveNameList: string[]; +} + +export default defineComponent({ + name: 'layoutParentView', + setup() { + const { proxy } = <any>getCurrentInstance(); + const route = useRoute(); + const storesKeepAliveNames = useKeepALiveNames(); + const storesThemeConfig = useThemeConfig(); + const { keepAliveNames, cachedViews } = storeToRefs(storesKeepAliveNames); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<ParentViewState>({ + refreshRouterViewKey: null, + keepAliveNameList: [], + }); + // 设置主界面切换动画 + const setTransitionName = computed(() => { + return themeConfig.value.animation; + }); + // 获取组件缓存列表(name值) + const getKeepAliveNames = computed(() => { + return themeConfig.value.isTagsview ? cachedViews.value : state.keepAliveNameList; + }); + // 页面加载前,处理缓存,页面刷新时路由缓存处理 + onBeforeMount(() => { + state.keepAliveNameList = keepAliveNames.value; + proxy.mittBus.on('onTagsViewRefreshRouterView', (fullPath: string) => { + state.keepAliveNameList = keepAliveNames.value.filter((name: string) => route.name !== name); + state.refreshRouterViewKey = null; + nextTick(() => { + state.refreshRouterViewKey = fullPath; + state.keepAliveNameList = keepAliveNames.value; + }); + }); + }); + // 页面加载时 + onMounted(() => { + // https://gitee.com/lyt-top/vue-next-admin/issues/I58U75 + // https://gitee.com/lyt-top/vue-next-admin/issues/I59RXK + nextTick(() => { + setTimeout(() => { + if (themeConfig.value.isCacheTagsView) cachedViews.value = Session.get('tagsViewList')?.map((item: any) => item.name); + }, 0); + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('onTagsViewRefreshRouterView', () => {}); + }); + // 监听路由变化,防止 tagsView 多标签时,切换动画消失 + watch( + () => route.fullPath, + () => { + state.refreshRouterViewKey = decodeURI(route.fullPath); + } + ); + return { + setTransitionName, + getKeepAliveNames, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..acd3d24 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,22 @@ +import { createApp } from 'vue'; +import pinia from '/@/stores/index'; +import App from './App.vue'; +import router from './router'; +import { directive } from '/@/utils/directive'; +import { i18n } from '/@/i18n/index'; +import other from '/@/utils/other'; + +import ElementPlus from 'element-plus'; +import 'element-plus/dist/index.css'; +import '/@/theme/index.scss'; +import mitt from 'mitt'; +import VueGridLayout from 'vue-grid-layout'; + +const app = createApp(App); + +directive(app); +other.elSvg(app); + +app.use(pinia).use(router).use(ElementPlus, { i18n: i18n.global.t }).use(i18n).use(VueGridLayout).mount('#app'); + +app.config.globalProperties.mittBus = mitt(); diff --git a/src/router/backEnd.ts b/src/router/backEnd.ts new file mode 100644 index 0000000..6d7f365 --- /dev/null +++ b/src/router/backEnd.ts @@ -0,0 +1,110 @@ +import { RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useRequestOldRoutes } from '/@/stores/requestOldRoutes'; +import { Session } from '/@/utils/storage'; +import { NextLoading } from '/@/utils/loading'; +import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route'; +import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useMenuApi } from '/@/api/menu/index'; +import { ElMessage } from 'element-plus'; + +const menuApi = useMenuApi(); + +const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}'); +const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}'); + + +/** + * 获取目录下的 .vue、.tsx 全部文件 + * @method import.meta.glob + * @link 参考:https://cn.vitejs.dev/guide/features.html#json + */ +const dynamicViewsModules: Record<string, Function> = Object.assign({}, { ...layouModules }, { ...viewsModules }); + + +export async function initBackEndControlRoutes() { + if (window.nextLoading === undefined) NextLoading.start(); + if (!Session.get('token')) return false; + useUserInfo().setUserInfos(); + // if(Session.get('ifMenu')) + const res = await getBackEndControlRoutes(Session.get('projectId')); + useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data.data))); + dynamicRoutes[0].children = await backEndComponent(res.data.data); + await setAddRoute(); + await setFilterMenuAndCacheTagsViewRoutes(); + } + + +export function setFilterMenuAndCacheTagsViewRoutes() { + const storesRoutesList = useRoutesList(pinia); + storesRoutesList.setRoutesList(dynamicRoutes[0].children as any); + setCacheTagsViewRoutes(); +} + + +export function setCacheTagsViewRoutes() { + const storesTagsView = useTagsViewRoutes(pinia); + storesTagsView.setTagsViewRoutes(formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children); +} + + +export function setFilterRouteEnd() { + let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)); + filterRouteEnd[0].children = [...filterRouteEnd[0].children, ...notFoundAndNoPower]; + return filterRouteEnd; +} + + +export async function setAddRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + router.addRoute(route); + }); +} + + +export async function getBackEndControlRoutes(value : string) { + const stores = useUserInfo(pinia); + const { userInfos } = storeToRefs(stores); + const auth = userInfos.value.roles[0]; + return menuApi.getMenuAdmin(value); + +} + +/** + * 重新请求后端路由菜单接口 + * @description 用于菜单管理界面刷新菜单(未进行测试) + * @description 路径:/src/views/system/menu/component/menuDialog.vue + */ +export function setBackEndControlRefreshRoutes() { + getBackEndControlRoutes(Session.get('projectId')); +} + + +export function backEndComponent(routes: any) { + if (!routes) return; + return routes.map((item: any) => { + if (item.component) item.component = dynamicImport(dynamicViewsModules, item.component as string); + item.children && backEndComponent(item.children); + return item; + }); +} + + +export function dynamicImport(dynamicViewsModules: Record<string, Function>, component: string) { + const keys = Object.keys(dynamicViewsModules); + const matchKeys = keys.filter((key) => { + const k = key.replace(/..\/views|../, ''); + return k.startsWith(`${component}`) || k.startsWith(`/${component}`); + }); + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0]; + return dynamicViewsModules[matchKey]; + } + if (matchKeys?.length > 1) { + return false; + } +} diff --git a/src/router/frontEnd.ts b/src/router/frontEnd.ts new file mode 100644 index 0000000..af8432b --- /dev/null +++ b/src/router/frontEnd.ts @@ -0,0 +1,97 @@ +import { RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index'; +import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route'; +import pinia from '/@/stores/index'; +import { Session } from '/@/utils/storage'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useRoutesList } from '/@/stores/routesList'; +import { NextLoading } from '/@/utils/loading'; + + +export async function initFrontEndControlRoutes() { + if (window.nextLoading === undefined) NextLoading.start(); + if (!Session.get('token')) return false; + useUserInfo(pinia).setUserInfos(); + await setAddRoute(); + await setFilterMenuAndCacheTagsViewRoutes(); +} + + +export async function setAddRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + router.addRoute(route); + }); +} + + +export async function frontEndsResetRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + const routeName: any = route.name; + router.hasRoute(routeName) && router.removeRoute(routeName); + }); +} + + +export function setFilterRouteEnd() { + let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)); + filterRouteEnd[0].children = [...setFilterRoute(filterRouteEnd[0].children), ...notFoundAndNoPower]; + return filterRouteEnd; +} + + +export function setFilterRoute(chil: any) { + const stores = useUserInfo(pinia); + const { userInfos } = storeToRefs(stores); + let filterRoute: any = []; + chil.forEach((route: any) => { + if (route.meta.roles) { + route.meta.roles.forEach((metaRoles: any) => { + userInfos.value.roles.forEach((roles: any) => { + if (metaRoles === roles) filterRoute.push({ ...route }); + }); + }); + } + }); + return filterRoute; +} + + +export function setCacheTagsViewRoutes() { + // 获取有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示 + const stores = useUserInfo(pinia); + const storesTagsView = useTagsViewRoutes(pinia); + const { userInfos } = storeToRefs(stores); + let rolesRoutes = setFilterHasRolesMenu(dynamicRoutes, userInfos.value.roles); + // 添加到 pinia setTagsViewRoutes 中 + storesTagsView.setTagsViewRoutes(formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes))[0].children); +} + + +export function setFilterMenuAndCacheTagsViewRoutes() { + const stores = useUserInfo(pinia); + const storesRoutesList = useRoutesList(pinia); + const { userInfos } = storeToRefs(stores); + storesRoutesList.setRoutesList(setFilterHasRolesMenu(dynamicRoutes[0].children, userInfos.value.roles)); + setCacheTagsViewRoutes(); +} + + +export function hasRoles(roles: any, route: any) { + if (route.meta && route.meta.roles) return roles.some((role: any) => route.meta.roles.includes(role)); + else return true; +} + + +export function setFilterHasRolesMenu(routes: any, roles: any) { + const menu: any = []; + routes.forEach((route: any) => { + const item = { ...route }; + if (hasRoles(roles, item)) { + if (item.children) item.children = setFilterHasRolesMenu(item.children, roles); + menu.push(item); + } + }); + return menu; +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..c789ab0 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,108 @@ +import { createRouter, createWebHashHistory } from 'vue-router'; +import NProgress from 'nprogress'; +import 'nprogress/nprogress.css'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Session } from '/@/utils/storage'; +import { staticRoutes } from '/@/router/route'; +import { initFrontEndControlRoutes } from '/@/router/frontEnd'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; + + + +// 读取 `/src/stores/themeConfig.ts` 是否开启后端控制路由配置 +const storesThemeConfig = useThemeConfig(pinia); +const { themeConfig } = storeToRefs(storesThemeConfig); +const { isRequestRoutes } = themeConfig.value; +if (isRequestRoutes) staticRoutes.splice(0, 1); + + +export const router = createRouter({ + history: createWebHashHistory(), + routes: staticRoutes, +}); + + +export function formatFlatteningRoutes(arr: any) { + if (arr.length <= 0) return false; + for (let i = 0; i < arr.length; i++) { + if (arr[i].children) { + arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1)); + } + } + return arr; +} + + +export function formatTwoStageRoutes(arr: any) { + if (arr.length <= 0) return false; + const newArr: any = []; + const cacheList: Array<string> = []; + arr.forEach((v: any) => { + if (v.path === '/') { + newArr.push({ component: v.component, name: v.name, path: v.path, redirect: v.redirect, meta: v.meta, children: [] }); + } else { + // 判断是否是动态路由(xx/:id/:name),用于 tagsView 等中使用 + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + if (v.path.indexOf('/:') > -1) { + v.meta['isDynamic'] = true; + v.meta['isDynamicPath'] = v.path; + } + newArr[0].children.push({ ...v }); + // 存 name 值,keep-alive 中 include 使用,实现路由的缓存 + // 路径:/@/layout/routerView/parent.vue + if (newArr[0].meta.isKeepAlive && v.meta.isKeepAlive) { + cacheList.push(v.name); + const stores = useKeepALiveNames(pinia); + stores.setCacheKeepAlive(cacheList); + } + } + }); + return newArr; +} + +// isRequestRoutes 为 true,则开启后端控制路由,路径:`/src/stores/themeConfig.ts` +if (!isRequestRoutes) initFrontEndControlRoutes(); + +// 路由加载前 +router.beforeEach(async (to, from, next) => { + NProgress.configure({ showSpinner: false }); + if (to.meta.title) NProgress.start(); + const token = Session.get('token'); + if (to.path === '/login' && !token) { + next(); + NProgress.done(); + } else { + if (!token) { + next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`); + Session.clear(); + NProgress.done(); + } else if (token && to.path === '/login') { + next('/home'); + NProgress.done(); + } else { + const storesRoutesList = useRoutesList(pinia); + const { routesList } = storeToRefs(storesRoutesList); + if (routesList.value.length === 0) { + // 后端控制路由:路由数据初始化,防止刷新时丢失 + await initBackEndControlRoutes(); + // 动态添加路由:防止非首页刷新时跳转回首页的问题 + // 确保 addRoute() 时动态添加的路由已经被完全加载上去 + next({ ...to, replace: true }); + } else { + next(); + } + } + } +}); + +// 路由加载后 +router.afterEach(() => { + NProgress.done(); +}); + +// 导出路由 +export default router; diff --git a/src/router/route.ts b/src/router/route.ts new file mode 100644 index 0000000..2cc9a9a --- /dev/null +++ b/src/router/route.ts @@ -0,0 +1,77 @@ +import { RouteRecordRaw } from 'vue-router'; + +export const dynamicRoutes: Array<RouteRecordRaw> = [ + + { + path: '/', + name: '/', + component: () => import('/@/layout/index.vue'), + redirect: '/home', + meta: { + isKeepAlive: true, + }, + children: [ + { + path: '/home', + name: 'home', + component: () => import('/@/views/home/index.vue'), + meta: { + title: 'message.router.home', + isLink: '', + isHide: false, + isKeepAlive: true, + isAffix: true, + isIframe: false, + roles: ['admin', 'common'], + icon: 'iconfont icon-shouye', + button:'121231' + }, + }, + ], + }, +]; + + +export const notFoundAndNoPower = [ + { + path: '/:path(.*)*', + name: 'notFound', + component: () => import('/@/views/error/404.vue'), + meta: { + title: 'message.staticRoutes.notFound', + isHide: true, + }, + }, + { + path: '/401', + name: 'noPower', + component: () => import('/@/views/error/401.vue'), + meta: { + title: 'message.staticRoutes.noPower', + isHide: true, + }, + }, +]; + +export const staticRoutes: Array<RouteRecordRaw> = [ + { + path: '/', + name: '/', + component: () => import('/@/layout/index.vue'), + meta: { + title: '布局界面', + }, + children: [ + // 请不要往这里 `children` 中添加内容,此内容为了防止 No match found for location with path "xxx" 问题 + ...notFoundAndNoPower, + ], + }, + { + path: '/login', + name: 'login', + component: () => import('/@/views/login/index.vue'), + meta: { + title: '登录', + }, + }, +]; diff --git a/src/stores/index.ts b/src/stores/index.ts new file mode 100644 index 0000000..27c377e --- /dev/null +++ b/src/stores/index.ts @@ -0,0 +1,8 @@ +// https://pinia.vuejs.org/ +import { createPinia } from 'pinia'; + +// 创建 +const pinia = createPinia(); + +// 导出 +export default pinia; diff --git a/src/stores/interface/index.ts b/src/stores/interface/index.ts new file mode 100644 index 0000000..994b9a5 --- /dev/null +++ b/src/stores/interface/index.ts @@ -0,0 +1,92 @@ +/** + * 定义接口来定义对象的类型 + * `stores` 全部类型定义在这里 + */ + +// 用户信息 +export interface UserInfosState { + authBtnList: string[]; + photo: string; + roles: string[]; + time: number; + userName: string; + sign:string; +} +export interface UserInfosStates { + userInfos: UserInfosState; +} + +// 路由缓存列表 +export interface KeepAliveNamesState { + keepAliveNames: string[]; + cachedViews: string[]; +} + +// 后端返回原始路由(未处理时) +export interface RequestOldRoutesState { + requestOldRoutes: string[]; +} + +// TagsView 路由列表 +export interface TagsViewRoutesState { + tagsViewRoutes: string[]; + isTagsViewCurrenFull: Boolean; +} + +// 路由列表 +export interface RoutesListState { + routesList: string[]; + isColumnsMenuHover: Boolean; + isColumnsNavHover: Boolean; + projectId:string, +} + +// 布局配置 +export interface ThemeConfigState { + isDrawer: boolean; + primary: string; + topBar: string; + topBarColor: string; + isTopBarColorGradual: boolean; + menuBar: string; + menuBarColor: string; + isMenuBarColorGradual: boolean; + columnsMenuBar: string; + columnsMenuBarColor: string; + isColumnsMenuBarColorGradual: boolean; + isCollapse: boolean; + isUniqueOpened: boolean; + isFixedHeader: boolean; + isFixedHeaderChange: boolean; + isClassicSplitMenu: boolean; + isLockScreen: boolean; + lockScreenTime: number; + isShowLogo: boolean; + isShowLogoChange: boolean; + isBreadcrumb: boolean; + isTagsview: boolean; + isBreadcrumbIcon: boolean; + isTagsviewIcon: boolean; + isCacheTagsView: boolean; + isSortableTagsView: boolean; + isShareTagsView: boolean; + isFooter: boolean; + isGrayscale: boolean; + isInvert: boolean; + isIsDark: boolean; + isWartermark: boolean; + wartermarkText: string; + tagsStyle: string; + animation: string; + columnsAsideStyle: string; + columnsAsideLayout: string; + layout: string; + isRequestRoutes: boolean; + globalTitle: string; + globalViceTitle: string; + globalI18n: string; + globalComponentSize: string; +} +export interface ThemeConfigStates { + themeConfig: ThemeConfigState; +} diff --git a/src/stores/keepAliveNames.ts b/src/stores/keepAliveNames.ts new file mode 100644 index 0000000..32e0389 --- /dev/null +++ b/src/stores/keepAliveNames.ts @@ -0,0 +1,37 @@ +import { defineStore } from 'pinia'; +import { KeepAliveNamesState } from './interface'; + +/** + * 路由缓存列表 + * @methods setCacheKeepAlive 设置要缓存的路由 names(开启 Tagsview) + * @methods addCachedView 添加要缓存的路由 names(关闭 Tagsview) + * @methods delCachedView 删除要缓存的路由 names(关闭 Tagsview) + * @methods delOthersCachedViews 右键菜单`关闭其它`,删除要缓存的路由 names(关闭 Tagsview) + * @methods delAllCachedViews 右键菜单`全部关闭`,删除要缓存的路由 names(关闭 Tagsview) + */ +export const useKeepALiveNames = defineStore('keepALiveNames', { + state: (): KeepAliveNamesState => ({ + keepAliveNames: [], + cachedViews: [], + }), + actions: { + async setCacheKeepAlive(data: Array<string>) { + this.keepAliveNames = data; + }, + async addCachedView(view: any) { + if (this.cachedViews.includes(view.name)) return; + if (view.meta.isKeepAlive) this.cachedViews.push(view.name); + }, + async delCachedView(view: any) { + const index = this.cachedViews.indexOf(view.name); + index > -1 && this.cachedViews.splice(index, 1); + }, + async delOthersCachedViews(view: any) { + if (view.meta.isKeepAlive) this.cachedViews = [view.name]; + else this.cachedViews = []; + }, + async delAllCachedViews() { + this.cachedViews = []; + }, + }, +}); diff --git a/src/stores/requestOldRoutes.ts b/src/stores/requestOldRoutes.ts new file mode 100644 index 0000000..be9b5cd --- /dev/null +++ b/src/stores/requestOldRoutes.ts @@ -0,0 +1,17 @@ +import { defineStore } from 'pinia'; +import { RequestOldRoutesState } from './interface'; + +/** + * 后端返回原始路由(未处理时) + * @methods setCacheKeepAlive 设置接口原始路由数据 + */ +export const useRequestOldRoutes = defineStore('requestOldRoutes', { + state: (): RequestOldRoutesState => ({ + requestOldRoutes: [], + }), + actions: { + async setRequestOldRoutes(routes: Array<string>) { + this.requestOldRoutes = routes; + }, + }, +}); diff --git a/src/stores/routesList.ts b/src/stores/routesList.ts new file mode 100644 index 0000000..5b23b15 --- /dev/null +++ b/src/stores/routesList.ts @@ -0,0 +1,28 @@ +import { defineStore } from 'pinia'; +import { RoutesListState } from './interface'; + +/** + * 路由列表 + * @methods setRoutesList 设置路由数据 + * @methods setColumnsMenuHover 设置分栏布局菜单鼠标移入 boolean + * @methods setColumnsNavHover 设置分栏布局最左侧导航鼠标移入 boolean + */ +export const useRoutesList = defineStore('routesList', { + state: (): RoutesListState => ({ + routesList: [], + isColumnsMenuHover: false, + isColumnsNavHover: false, + projectId:'', + }), + actions: { + async setRoutesList(data: Array<string>) { + this.routesList = data; + }, + async setColumnsMenuHover(bool: Boolean) { + this.isColumnsMenuHover = bool; + }, + async setColumnsNavHover(bool: Boolean) { + this.isColumnsNavHover = bool; + }, + }, +}); diff --git a/src/stores/tagsViewRoutes.ts b/src/stores/tagsViewRoutes.ts new file mode 100644 index 0000000..7a5e6f4 --- /dev/null +++ b/src/stores/tagsViewRoutes.ts @@ -0,0 +1,24 @@ +import { defineStore } from 'pinia'; +import { TagsViewRoutesState } from './interface'; +import { Session } from '/@/utils/storage'; + +/** + * TagsView 路由列表 + * @methods setTagsViewRoutes 设置 TagsView 路由列表 + * @methods setCurrenFullscreen 设置开启/关闭全屏时的 boolean 状态 + */ +export const useTagsViewRoutes = defineStore('tagsViewRoutes', { + state: (): TagsViewRoutesState => ({ + tagsViewRoutes: [], + isTagsViewCurrenFull: false, + }), + actions: { + async setTagsViewRoutes(data: Array<string>) { + this.tagsViewRoutes = data; + }, + setCurrenFullscreen(bool: Boolean) { + Session.set('isTagsViewCurrenFull', bool); + this.isTagsViewCurrenFull = bool; + }, + }, +}); diff --git a/src/stores/themeConfig.ts b/src/stores/themeConfig.ts new file mode 100644 index 0000000..198e155 --- /dev/null +++ b/src/stores/themeConfig.ts @@ -0,0 +1,146 @@ +import { defineStore } from 'pinia'; +import { ThemeConfigStates, ThemeConfigState } from './interface'; + +/** + * 布局配置 + * 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I567R1,感谢@lanbao123 + * 2020.05.28 by lyt 优化。开发时配置不生效问题 + * 修改配置时: + * 1、需要每次都清理 `window.localStorage` 浏览器永久缓存 + * 2、或者点击布局配置最底部 `一键恢复默认` 按钮即可看到效果 + */ +export const useThemeConfig = defineStore('themeConfig', { + state: (): ThemeConfigStates => ({ + themeConfig: { + // 是否开启布局配置抽屉 + isDrawer: false, + + /** + * 全局主题 + */ + // 默认 primary 主题颜色 + primary: '#409eff', + // 是否开启深色模式 + isIsDark: false, + + /** + * 菜单 / 顶栏 + * 注意:v1.0.17 版本去除设置布局切换,重置主题样式(initSetLayoutChange), + * 切换布局需手动设置样式,设置的样式自动同步各布局, + * 代码位置:/@/layout/navBars/breadcrumb/setings.vue + */ + // 默认顶栏导航背景颜色 + topBar: '#ffffff', + // 默认顶栏导航字体颜色 + topBarColor: '#606266', + // 是否开启顶栏背景颜色渐变 + isTopBarColorGradual: false, + // 默认菜单导航背景颜色 + menuBar: '#545c64', + // 默认菜单导航字体颜色 + menuBarColor: '#eaeaea', + // 是否开启菜单背景颜色渐变 + isMenuBarColorGradual: false, + // 默认分栏菜单背景颜色 + columnsMenuBar: '#545c64', + // 默认分栏菜单字体颜色 + columnsMenuBarColor: '#e6e6e6', + // 是否开启分栏菜单背景颜色渐变 + isColumnsMenuBarColorGradual: false, + + /** + * 界面设置 + */ + // 是否开启菜单水平折叠效果 + isCollapse: false, + // 是否开启菜单手风琴效果 + isUniqueOpened: false, + // 是否开启固定 Header + isFixedHeader: false, + // 初始化变量,用于更新菜单 el-scrollbar 的高度,请勿删除 + isFixedHeaderChange: false, + // 是否开启经典布局分割菜单(仅经典布局生效) + isClassicSplitMenu: false, + // 是否开启自动锁屏 + isLockScreen: false, + // 开启自动锁屏倒计时(s/秒) + lockScreenTime: 30, + + /** + * 界面显示 + */ + // 是否开启侧边栏 Logo + isShowLogo: false, + // 初始化变量,用于 el-scrollbar 的高度更新,请勿删除 + isShowLogoChange: false, + // 是否开启 Breadcrumb,强制经典、横向布局不显示 + isBreadcrumb: true, + // 是否开启 Tagsview + isTagsview: true, + // 是否开启 Breadcrumb 图标 + isBreadcrumbIcon: false, + // 是否开启 Tagsview 图标 + isTagsviewIcon: false, + // 是否开启 TagsView 缓存 + isCacheTagsView: false, + // 是否开启 TagsView 拖拽 + isSortableTagsView: true, + // 是否开启 TagsView 共用 + isShareTagsView: false, + // 是否开启 Footer 底部版权信息 + isFooter: false, + // 是否开启灰色模式 + isGrayscale: false, + // 是否开启色弱模式 + isInvert: false, + // 是否开启水印 + isWartermark: false, + // 水印文案 + wartermarkText: 'small@小柒', + + /** + * 其它设置 + */ + // Tagsview 风格:可选值"<tags-style-one|tags-style-four|tags-style-five>",默认 tags-style-five + // 定义的值与 `/src/layout/navBars/tagsView/tagsView.vue` 中的 class 同名 + tagsStyle: 'tags-style-five', + // 主页面切换动画:可选值"<slide-right|slide-left|opacitys>",默认 slide-right + animation: 'slide-right', + // 分栏高亮风格:可选值"<columns-round|columns-card>",默认 columns-round + columnsAsideStyle: 'columns-round', + // 分栏布局风格:可选值"<columns-horizontal|columns-vertical>",默认 columns-horizontal + columnsAsideLayout: 'columns-vertical', + + /** + * 布局切换 + * 注意:为了演示,切换布局时,颜色会被还原成默认,代码位置:/@/layout/navBars/breadcrumb/setings.vue + * 中的 `initSetLayoutChange(设置布局切换,重置主题样式)` 方法 + */ + // 布局切换:可选值"<defaults|classic|transverse|columns>",默认 defaults + layout: 'defaults', + + /** + * 后端控制路由 + */ + // 是否开启后端控制路由 + isRequestRoutes: true, + + /** + * 全局网站标题 / 副标题 + */ + // 网站主标题(菜单导航、浏览器当前网页标题) + globalTitle: 'vue-next-admin', + // 网站副标题(登录页顶部文字) + globalViceTitle: 'vueNextAdmin', + // 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn + globalI18n: 'zh-cn', + // 默认全局组件大小,可选值"<large|'default'|small>",默认 'large' + globalComponentSize: 'large', + }, + }), + actions: { + setThemeConfig(data: ThemeConfigState) { + this.themeConfig = data; + }, + }, +}); diff --git a/src/stores/userInfo.ts b/src/stores/userInfo.ts new file mode 100644 index 0000000..97176a8 --- /dev/null +++ b/src/stores/userInfo.ts @@ -0,0 +1,65 @@ +import { defineStore } from 'pinia'; +import Cookies from 'js-cookie'; +import { UserInfosStates } from './interface'; +import { Session } from '/@/utils/storage'; + +/** + * 用户信息 + * @methods setUserInfos 设置用户信息 + */ +export const useUserInfo = defineStore('userInfo', { + state: (): UserInfosStates => ({ + userInfos: { + userName: '', + photo: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg', + time: 0, + roles: [], + authBtnList: [], + sign:'', + }, + }), + actions: { + async setUserInfos() { + const userName = Cookies.get('userName'); + // 模拟数据 + let defaultRoles: Array<string> = []; + let defaultAuthBtnList: Array<string> = []; + // admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 + let adminRoles: Array<string> = ['admin']; + // admin 按钮权限标识 + let adminAuthBtnList: Array<string> = ['btn.add', 'btn.del', 'btn.edit', 'btn.link']; + // test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 + let testRoles: Array<string> = ['common']; + // test 按钮权限标识 + let testAuthBtnList: Array<string> = ['btn.add', 'btn.link']; + // 不同用户模拟不同的用户权限 + if (userName === 'admin') { + defaultRoles = adminRoles; + defaultAuthBtnList = adminAuthBtnList; + } else { + defaultRoles = testRoles; + defaultAuthBtnList = testAuthBtnList; + } + // 用户信息模拟数据 + const userInfos = { + userName: userName, + photo: + userName === 'admin' + ? 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg' + : 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg', + time: new Date().getTime(), + roles: defaultRoles, + authBtnList: defaultAuthBtnList, + sign:'', + }; + // 存储用户信息到浏览器缓存 + Session.set('userInfo', userInfos); + + if (Session.get('userInfo')) { + this.userInfos = Session.get('userInfo'); + } else { + this.userInfos = userInfos; + } + }, + }, +}); diff --git a/src/theme/app.scss b/src/theme/app.scss new file mode 100644 index 0000000..4c75296 --- /dev/null +++ b/src/theme/app.scss @@ -0,0 +1,281 @@ +/* 初始化样式 +------------------------------- */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + outline: none !important; +} + +:root { + --next-color-white: #ffffff; + --next-bg-main-color: #f8f8f8; + --next-bg-color: #f5f5ff; + --next-border-color-light: #f1f2f3; + --next-color-primary-lighter: #ecf5ff; + --next-color-success-lighter: #f0f9eb; + --next-color-warning-lighter: #fdf6ec; + --next-color-danger-lighter: #fef0f0; + --next-color-dark-hover: #0000001a; + --next-color-menu-hover: rgba(0, 0, 0, 0.2); + --next-color-user-hover: rgba(0, 0, 0, 0.04); + --next-color-seting-main: #e9eef3; + --next-color-seting-aside: #d3dce6; + --next-color-seting-header: #b3c0d1; +} + +html, +body, +#app { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; + font-weight: 400; + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; + background-color: var(--next-bg-main-color); + font-size: 14px; + overflow: hidden; + position: relative; +} + +/* 主布局样式 +------------------------------- */ +.layout-container { + width: 100%; + height: 100%; + .layout-aside { + background: var(--next-bg-menuBar); + box-shadow: 2px 0 6px rgb(0 21 41 / 1%); + height: inherit; + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + overflow-x: hidden !important; + .el-scrollbar__view { + overflow: hidden; + } + } + .layout-header { + padding: 0 !important; + } + .layout-main { + padding: 0 !important; + overflow: hidden; + width: 100%; + background-color: var(--next-bg-main-color); + } + .el-scrollbar { + width: 100%; + } + // 此字段多次用到,建议不删除,如需修改,请重写覆盖样式 + .layout-view-bg-white { + background: var(--el-color-white); + width: 100%; + height: 100%; + border-radius: 4px; + border: 1px solid var(--el-border-color-light, #ebeef5); + } + .layout-el-aside-br-color { + border-right: 1px solid var(--el-border-color-light, #ebeef5); + } + // pc端左侧导航样式 + .layout-aside-pc-220 { + width: 220px !important; + transition: width 0.3s ease; + } + .layout-aside-pc-64 { + width: 64px !important; + transition: width 0.3s ease; + } + .layout-aside-pc-1 { + width: 1px !important; + transition: width 0.3s ease; + } + // 手机端左侧导航样式 + .layout-aside-mobile { + position: fixed; + top: 0; + left: -220px; + width: 220px; + z-index: 9999999; + } + .layout-aside-mobile-close { + left: -220px; + transition: all 0.3s cubic-bezier(0.39, 0.58, 0.57, 1); + } + .layout-aside-mobile-open { + left: 0; + transition: all 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); + } + .layout-aside-mobile-mode { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 9999998; + animation: error-img 0.3s; + } + .layout-scrollbar { + @extend .el-scrollbar; + padding: 15px; + } + .layout-mian-height-50 { + height: calc(100vh - 50px); + } + .layout-columns-warp { + flex: 1; + display: flex; + overflow: hidden; + } + .layout-hide { + display: none; + } +} + +/* element plus 全局样式 +------------------------------- */ +.layout-breadcrumb-seting { + .el-divider { + background-color: rgb(230, 230, 230); + } +} + +/* nprogress 进度条跟随主题颜色 +------------------------------- */ +#nprogress { + .bar { + background: var(--el-color-primary) !important; + z-index: 9999999 !important; + } +} + +/* flex 弹性布局 +------------------------------- */ +.flex { + display: flex; +} +.flex-auto { + flex: 1; + overflow: hidden; +} +.flex-center { + @extend .flex; + flex-direction: column; + width: 100%; + overflow: hidden; +} +.flex-margin { + margin: auto; +} +.flex-warp { + display: flex; + flex-wrap: wrap; + align-content: flex-start; + margin: 0 -5px; + .flex-warp-item { + padding: 5px; + .flex-warp-item-box { + width: 100%; + height: 100%; + } + } +} + +/* cursor 鼠标形状 +------------------------------- */ +// 默认 +.cursor-default { + cursor: default !important; +} +// 帮助 +.cursor-help { + cursor: help !important; +} +// 手指 +.cursor-pointer { + cursor: pointer !important; +} +// 移动 +.cursor-move { + cursor: move !important; +} + +/* 宽高 100% +------------------------------- */ +.w100 { + width: 100% !important; +} +.h100 { + height: 100% !important; +} +.vh100 { + height: 100vh !important; +} +.max100vh { + max-height: 100vh !important; +} +.min100vh { + min-height: 100vh !important; +} + +/* 颜色值 +------------------------------- */ +.color-primary { + color: var(--el-color-primary); +} +.color-success { + color: var(--el-color-success); +} +.color-warning { + color: var(--el-color-warning); +} +.color-danger { + color: var(--el-color-danger); +} +.color-info { + color: var(--el-color-info); +} + +/* 字体大小全局样式 +------------------------------- */ +@for $i from 10 through 32 { + .font#{$i} { + font-size: #{$i}px !important; + } +} + +/* 外边距、内边距全局样式 +------------------------------- */ +@for $i from 1 through 35 { + .mt#{$i} { + margin-top: #{$i}px !important; + } + .mr#{$i} { + margin-right: #{$i}px !important; + } + .mb#{$i} { + margin-bottom: #{$i}px !important; + } + .ml#{$i} { + margin-left: #{$i}px !important; + } + .pt#{$i} { + padding-top: #{$i}px !important; + } + .pr#{$i} { + padding-right: #{$i}px !important; + } + .pb#{$i} { + padding-bottom: #{$i}px !important; + } + .pl#{$i} { + padding-left: #{$i}px !important; + } +} diff --git a/src/theme/common/transition.scss b/src/theme/common/transition.scss new file mode 100644 index 0000000..a03a7bb --- /dev/null +++ b/src/theme/common/transition.scss @@ -0,0 +1,94 @@ +/* 页面切换动画 +------------------------------- */ +.slide-right-enter-active, +.slide-right-leave-active, +.slide-left-enter-active, +.slide-left-leave-active { + will-change: transform; + transition: all 0.3s ease; +} +// slide-right +.slide-right-enter-from { + opacity: 0; + transform: translateX(-20px); +} +.slide-right-leave-to { + opacity: 0; + transform: translateX(20px); +} +// slide-left +.slide-left-enter-from { + @extend .slide-right-leave-to; +} +.slide-left-leave-to { + @extend .slide-right-enter-from; +} +// opacitys +.opacitys-enter-active, +.opacitys-leave-active { + will-change: transform; + transition: all 0.3s ease; +} +.opacitys-enter-from, +.opacitys-leave-to { + opacity: 0; +} + +/* Breadcrumb 面包屑过渡动画 +------------------------------- */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all 0.5s ease; +} +.breadcrumb-enter-from, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} +.breadcrumb-leave-active { + position: absolute; + z-index: -1; +} + +/* logo 过渡动画 +------------------------------- */ +@keyframes logoAnimation { + 0% { + transform: scale(0); + } + 80% { + transform: scale(1.2); + } + 100% { + transform: scale(1); + } +} + +/* 404、401 过渡动画 +------------------------------- */ +@keyframes error-num { + 0% { + transform: translateY(60px); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} +@keyframes error-img { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes error-img-two { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} diff --git a/src/theme/dark.scss b/src/theme/dark.scss new file mode 100644 index 0000000..c922da1 --- /dev/null +++ b/src/theme/dark.scss @@ -0,0 +1,236 @@ +/* 深色模式样式 +------------------------------- */ +[data-theme='dark'] { + // 变量(自定义时,只需修改这里的值) + --next-bg-main: #1f1f1f; + --next-color-white: #ffffff; + --next-color-disabled: #191919; + --next-color-bar: #dadada; + --next-color-primary: #303030; + --next-border-color: #424242; + --next-border-black: #333333; + --next-border-columns: #2a2a2a; + --next-color-seting: #505050; + --next-text-color-regular: #9b9da1; + --next-text-color-placeholder: #7a7a7a; + --next-color-hover: #3c3c3c; + --next-color-hover-rgba: rgba(0, 0, 0, 0.3); + + // root + --next-bg-main-color: var(--next-bg-main) !important; + --next-bg-topBar: var(--next-color-disabled) !important; + --next-bg-topBarColor: var(--next-color-bar) !important; + --next-bg-menuBar: var(--next-color-disabled) !important; + --next-bg-menuBarColor: var(--next-color-bar) !important; + --next-bg-columnsMenuBar: var(--next-color-disabled) !important; + --next-bg-columnsMenuBarColor: var(--next-color-bar) !important; + --next-border-color-light: var(--next-border-black) !important; + --next-color-primary-lighter: var(--next-color-primary) !important; + --next-color-success-lighter: var(--next-color-primary) !important; + --next-color-warning-lighter: var(--next-color-primary) !important; + --next-color-danger-lighter: var(--next-color-primary) !important; + --next-bg-color: var(--next-color-primary) !important; + --next-color-dark-hover: var(--next-color-hover) !important; + --next-color-menu-hover: var(--next-color-hover-rgba) !important; + --next-color-user-hover: var(--next-color-hover-rgba) !important; + --next-color-seting-main: var(--next-color-seting) !important; + --next-color-seting-aside: var(--next-color-hover) !important; + --next-color-seting-header: var(--next-color-primary) !important; + + // element plus + --el-color-white: var(--next-color-disabled) !important; + --el-text-color-primary: var(--next-color-bar) !important; + --el-border-color: var(--next-border-black) !important; + --el-border-color-light: var(--next-border-black) !important; + --el-border-color-lighter: var(--next-border-black) !important; + --el-border-color-extra-light: var(--el-color-primary-light-8) !important; + --el-text-color-regular: var(--next-text-color-regular) !important; + --el-bg-color: var(--next-color-disabled) !important; + --el-color-primary-light-9: var(--next-color-hover) !important; + --el-text-color-disabled: var(--next-text-color-placeholder) !important; + --el-text-color-disabled-base: var(--el-color-primary) !important; + --el-text-color-placeholder: var(--next-text-color-placeholder) !important; + --el-disabled-bg-color: var(--next-color-disabled) !important; + --el-fill-base: var(--next-color-white) !important; + --el-fill-colo: var(--next-color-hover-rgba) !important; + --el-fill-color: var(--next-color-hover-rgba) !important; + --el-fill-color-blank: var(--next-color-disabled) !important; + --el-fill-color-light: var(--next-color-hover-rgba) !important; + --el-bg-color-overlay: var(--el-color-primary-light-9) !important; + --el-mask-color: rgb(42 42 42 / 80%); + + // button + .el-button { + &:hover { + border-color: var(--next-border-color) !important; + } + } + .el-button--primary, + .el-button--info, + .el-button--danger, + .el-button--success, + .el-button--warning { + --el-button-text-color: var(--next-color-white) !important; + --el-button-hover-text-color: var(--next-color-white) !important; + --el-button-disabled-text-color: var(--next-color-white) !important; + &:hover { + border-color: var(--el-button-hover-border-color, var(--el-button-hover-bg-color)) !important; + } + } + + // drawer + .el-divider__text { + background-color: var(--el-color-white) !important; + } + .el-drawer { + border-left: 1px solid var(--next-border-color-light) !important; + } + + // tabs + .el-tabs--border-card { + background-color: var(--el-color-white) !important; + } + .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { + background: var(--next-color-primary-lighter); + } + + // alert / notice-bar + .home-card-item { + border: 1px solid var(--next-border-color-light) !important; + } + .el-alert, + .notice-bar { + border: 1px solid var(--next-border-color) !important; + background-color: var(--next-color-disabled) !important; + } + + // menu + .layout-aside { + border-right: 1px solid var(--next-border-color-light) !important; + } + + // colorPicker + .el-color-picker__mask { + background: unset !important; + } + .el-color-picker__trigger { + border: 1px solid var(--next-border-color-light) !important; + } + + // popper / dropdown + .el-popper { + border: 1px solid var(--next-border-color) !important; + color: var(--el-text-color-primary) !important; + .el-popper__arrow:before { + background: var(--el-color-white) !important; + border: 1px solid var(--next-border-color); + } + a { + color: var(--el-text-color-primary) !important; + } + } + .el-popper, + .el-dropdown-menu { + background: var(--el-color-white) !important; + } + .el-dropdown-menu__item:hover:not(.is-disabled) { + background: var(--el-bg-color) !important; + } + .el-dropdown-menu__item.is-disabled { + font-weight: 700 !important; + } + + // input + .el-input-group__append, + .el-input-group__prepend { + border: var(--el-input-border) !important; + border-right: none !important; + background: var(--next-color-disabled) !important; + border-left: 0 !important; + } + .el-input-number__decrease, + .el-input-number__increase { + background: var(--next-color-disabled) !important; + } + + // tag + .el-select .el-select__tags .el-tag { + background-color: var(--next-bg-color) !important; + } + + // pagination + .el-pagination.is-background .el-pager li:not(.disabled).active { + color: var(--next-color-white) !important; + } + .el-pagination.is-background .btn-next, + .el-pagination.is-background .btn-prev, + .el-pagination.is-background .el-pager li { + background-color: var(--next-bg-color); + } + + // radio + .el-radio-button:not(.is-active) .el-radio-button__inner { + border: 1px solid var(--next-border-color-light) !important; + border-left: 0 !important; + } + .el-radio-button.is-active .el-radio-button__inner { + color: var(--next-color-white) !important; + } + + // countup + .countup-card-item-flex { + color: var(--el-text-color-primary) !important; + } + + // editor + .editor-container { + .w-e-toolbar { + background: var(--el-color-white) !important; + border: 1px solid var(--next-border-color-light) !important; + .w-e-menu:hover { + background: var(--next-color-user-hover) !important; + i { + color: var(--el-text-color-primary) !important; + } + } + } + .w-e-text-container { + border: 1px solid var(--next-border-color-light) !important; + border-top: none !important; + .w-e-text { + background: var(--el-color-white) !important; + } + } + } + + // date-picker + .el-picker-panel { + background: var(--el-color-white) !important; + } + + // dialog + .el-dialog { + border: 1px solid var(--el-border-color-lighter); + .el-dialog__header { + color: var(--el-text-color-primary) !important; + } + } + + // columns + .layout-columns-aside ul .layout-columns-active { + color: var(--next-color-white) !important; + } + .layout-columns-aside { + border-right: 1px solid var(--next-border-columns); + } + + // tagsView + .tags-style-one { + .is-active { + color: var(--el-text-color-primary) !important; + } + .layout-navbars-tagsview-ul-li:hover { + border-color: var(--el-border-color-lighter) !important; + } + } +} diff --git a/src/theme/element.scss b/src/theme/element.scss new file mode 100644 index 0000000..5137cb4 --- /dev/null +++ b/src/theme/element.scss @@ -0,0 +1,282 @@ +@import 'mixins/index.scss'; + +/* Button 按钮 +------------------------------- */ +// 第三方字体图标大小 +.el-button i.el-icon, +.el-button i.iconfont, +.el-button i.fa, +.el-button--default i.iconfont, +.el-button--default i.fa { + font-size: 14px !important; + margin-right: 5px; +} +.el-button--small i.iconfont, +.el-button--small i.fa { + font-size: 12px !important; + margin-right: 5px; +} + +/* Input 输入框、InputNumber 计数器 +------------------------------- */ +.el-input { + height: 100%; +} +// 菜单搜索 +.el-autocomplete-suggestion__wrap { + max-height: 280px !important; +} + +/* Form 表单 +------------------------------- */ +.el-form { + .el-form-item:last-of-type { + margin-bottom: 0 !important; + } +} + +/* Alert 警告 +------------------------------- */ +.el-alert { + border: 1px solid; +} +.el-alert__title { + word-break: break-all; +} + +/* Message 消息提示 +------------------------------- */ +.el-message { + min-width: unset !important; + padding: 15px !important; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.02); +} + +/* NavMenu 导航菜单 +------------------------------- */ +// 鼠标 hover 时颜色 +.el-menu-hover-bg-color { + background-color: var(--next-color-menu-hover) !important; +} +// 默认样式修改 +.el-menu { + border-right: none !important; + width: 220px; +} +.el-menu-item { + height: 56px !important; + line-height: 56px !important; +} +.el-menu-item, +.el-sub-menu__title { + color: var(--next-bg-menuBarColor); +} +// 修复点击左侧菜单折叠再展开时,宽度不跟随问题 +.el-menu--collapse { + width: 64px !important; +} +// 外部链接时 +.el-menu-item a, +.el-menu-item a:hover, +.el-menu-item i, +.el-sub-menu__title i { + color: inherit; + text-decoration: none; +} +// 第三方图标字体间距/大小设置 +.el-menu-item .iconfont, +.el-sub-menu .iconfont, +.el-menu-item .fa, +.el-sub-menu .fa { + @include generalIcon; +} +// 水平菜单、横向菜单高亮 背景色,鼠标 hover 时,有子级菜单的背景色 +.el-menu-item.is-active, +.el-sub-menu.is-active .el-sub-menu__title, +.el-sub-menu:not(.is-opened):hover .el-sub-menu__title { + @extend .el-menu-hover-bg-color; +} +.el-sub-menu.is-active.is-opened .el-sub-menu__title { + background-color: unset !important; +} +// 子级菜单背景颜色 +// .el-menu--inline { +// background: var(--next-bg-menuBar-light-1); +// } +// 水平菜单、横向菜单折叠 a 标签 +.el-popper.is-dark a { + color: var(--el-color-white) !important; + text-decoration: none; +} +// 水平菜单、横向菜单折叠背景色 +.el-popper.is-pure.is-light { + // 水平菜单 + .el-menu--vertical { + background: var(--next-bg-menuBar); + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + .el-popper.is-pure.is-light { + .el-menu--vertical { + .el-sub-menu .el-sub-menu__title { + background-color: unset !important; + color: var(--next-bg-menuBarColor); + } + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } + } + } + // 横向菜单 + .el-menu--horizontal { + background: var(--next-bg-topBar); + .el-menu-item, + .el-sub-menu { + height: 50px !important; + line-height: 50px !important; + color: var(--next-bg-topBarColor); + .el-sub-menu__title { + height: 50px !important; + line-height: 50px !important; + color: var(--next-bg-topBarColor); + } + .el-popper.is-pure.is-light { + .el-menu--horizontal { + .el-sub-menu .el-sub-menu__title { + background-color: unset !important; + color: var(--next-bg-topBarColor); + } + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } + } + } + .el-menu-item.is-active, + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } +} +// 横向菜单(经典、横向)布局 +.el-menu.el-menu--horizontal { + border-bottom: none !important; + width: 100% !important; + .el-menu-item, + .el-sub-menu__title { + height: 50px !important; + color: var(--next-bg-topBarColor); + } + .el-menu-item:not(.is-active):hover, + .el-sub-menu:not(.is-active):hover .el-sub-menu__title { + color: var(--next-bg-topBarColor); + } +} + +/* Tabs 标签页 +------------------------------- */ +.el-tabs__nav-wrap::after { + height: 1px !important; +} + +/* Dropdown 下拉菜单 +------------------------------- */ +.el-dropdown-menu { + list-style: none !important; /*修复 Dropdown 下拉菜单样式问题 2022.03.04*/ +} +.el-dropdown-menu .el-dropdown-menu__item { + white-space: nowrap; + &:not(.is-disabled):hover { + background-color: var(--el-dropdown-menuItem-hover-fill); + color: var(--el-dropdown-menuItem-hover-color); + } +} + +/* Steps 步骤条 +------------------------------- */ +.el-step__icon-inner { + font-size: 30px !important; + font-weight: 400 !important; +} +.el-step__title { + font-size: 14px; +} + +/* Dialog 对话框 +------------------------------- */ +.el-overlay { + overflow: hidden; + .el-overlay-dialog { + display: flex; + align-items: center; + justify-content: center; + position: unset !important; + width: 100%; + height: 100%; + .el-dialog { + margin: 0 auto !important; + position: absolute; + .el-dialog__body { + padding: 20px !important; + } + } + } +} +.el-dialog__body { + max-height: calc(90vh - 111px) !important; + overflow-y: auto; + overflow-x: hidden; +} + +/* Card 卡片 +------------------------------- */ +.el-card__header { + padding: 15px 20px; +} + +/* Table 表格 element plus 2.2.0 版本 +------------------------------- */ +.el-table { + .el-button.is-text { + padding: 0; + } +} + +/* scrollbar +------------------------------- */ +.el-scrollbar__bar { + z-index: 4; +} +.el-scrollbar__wrap { + max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/ +} +.el-select-dropdown .el-scrollbar__wrap { + overflow-x: scroll !important; +} +.el-select-dropdown__wrap { + max-height: 274px !important; /*修复Select 选择器高度问题*/ +} +.el-cascader-menu__wrap.el-scrollbar__wrap { + height: 204px !important; /*修复Cascader 级联选择器高度问题*/ +} + +/* Drawer 抽屉 +------------------------------- */ +.el-drawer { + --el-drawer-padding-primary: unset !important; + .el-drawer__header { + padding: 0 15px !important; + height: 50px; + display: flex; + align-items: center; + margin-bottom: 0 !important; + border-bottom: 1px solid var(--el-border-color); + color: var(--el-text-color-primary); + } + .el-drawer__body { + width: 100%; + height: 100%; + overflow: auto; + } +} diff --git a/src/theme/iconSelector.scss b/src/theme/iconSelector.scss new file mode 100644 index 0000000..970201e --- /dev/null +++ b/src/theme/iconSelector.scss @@ -0,0 +1,70 @@ +/* Popover 弹出框(图标选择器) +------------------------------- */ +.icon-selector-popper { + padding: 0 !important; + .icon-selector-warp { + height: 260px; + overflow: hidden; + .icon-selector-warp-title { + height: 40px; + line-height: 40px; + padding: 0 15px; + .icon-selector-warp-title-tab { + span { + cursor: pointer; + &:hover { + color: var(--el-color-primary); + text-decoration: underline; + } + } + .span-active { + color: var(--el-color-primary); + text-decoration: underline; + } + } + } + .icon-selector-warp-row { + height: 230px; + overflow: hidden; + border-top: 1px solid var(--el-border-color); + .el-row { + padding: 15px; + } + .el-scrollbar__bar.is-horizontal { + display: none; + } + .icon-selector-warp-item { + display: flex; + border: 1px solid var(--el-border-color); + padding: 5px; + border-radius: 5px; + margin-bottom: 10px; + .icon-selector-warp-item-value { + i { + font-size: 20px; + color: var(--el-text-color-regular); + } + } + &:hover { + cursor: pointer; + background-color: var(--el-color-primary-light-9); + border: 1px solid var(--el-color-primary-light-5); + .icon-selector-warp-item-value { + i { + color: var(--el-color-primary); + } + } + } + } + .icon-selector-active { + background-color: var(--el-color-primary-light-9); + border: 1px solid var(--el-color-primary-light-5); + .icon-selector-warp-item-value { + i { + color: var(--el-color-primary); + } + } + } + } + } +} diff --git a/src/theme/index.scss b/src/theme/index.scss new file mode 100644 index 0000000..c574e00 --- /dev/null +++ b/src/theme/index.scss @@ -0,0 +1,8 @@ +@import './app.scss'; +@import 'common/transition.scss'; +@import './other.scss'; +@import './element.scss'; +@import './iconSelector.scss'; +@import './media/media.scss'; +@import './waves.scss'; +@import './dark.scss'; diff --git a/src/theme/loading.scss b/src/theme/loading.scss new file mode 100644 index 0000000..c28c7b9 --- /dev/null +++ b/src/theme/loading.scss @@ -0,0 +1,51 @@ +.loading-next { + width: 100%; + height: 100%; +} +.loading-next .loading-next-box { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +.loading-next .loading-next-box-warp { + width: 80px; + height: 80px; +} +.loading-next .loading-next-box-warp .loading-next-box-item { + width: 33.333333%; + height: 33.333333%; + background: var(--el-color-primary); + float: left; + animation: loading-next-animation 1.2s infinite ease; + border-radius: 1px; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(7) { + animation-delay: 0s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(4), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(8) { + animation-delay: 0.1s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(1), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(5), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(9) { + animation-delay: 0.2s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(2), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(6) { + animation-delay: 0.3s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(3) { + animation-delay: 0.4s; +} +@keyframes loading-next-animation { + 0%, + 70%, + 100% { + transform: scale3D(1, 1, 1); + } + 35% { + transform: scale3D(0, 0, 1); + } +} diff --git a/src/theme/media/chart.scss b/src/theme/media/chart.scss new file mode 100644 index 0000000..8485e39 --- /dev/null +++ b/src/theme/media/chart.scss @@ -0,0 +1,94 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .big-data-down-left { + width: 100% !important; + flex-direction: unset !important; + flex-wrap: wrap; + .flex-warp-item { + min-height: 196.24px; + padding: 0 7.5px 15px 15px !important; + .flex-warp-item-box { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + } + } + .big-data-down-center { + width: 100% !important; + .big-data-down-center-one, + .big-data-down-center-two { + min-height: 196.24px; + padding-left: 15px !important; + .big-data-down-center-one-content { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + .flex-warp-item-box { + @extend .big-data-down-center-one-content; + } + } + } + .big-data-down-right { + .flex-warp-item { + .flex-warp-item-box { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + &:nth-of-type(2) { + padding-left: 15px !important; + } + &:last-of-type { + .flex-warp-item-box { + border: none !important; + } + } + } + } +} + +/* 页面宽度大于768px小于1200px +------------------------------- */ +@media screen and (min-width: $sm) and (max-width: $lg) { + .chart-warp-bottom { + .big-data-down-left { + width: 50% !important; + } + .big-data-down-center { + width: 50% !important; + } + .big-data-down-right { + .flex-warp-item { + width: 50% !important; + &:nth-of-type(2) { + padding-left: 7.5px !important; + } + } + } + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .chart-warp-top { + .up-left { + display: none; + } + } + .chart-warp-bottom { + overflow-y: auto !important; + flex-wrap: wrap; + .big-data-down-right { + width: 100% !important; + flex-direction: unset !important; + flex-wrap: wrap; + .flex-warp-item { + min-height: 196.24px; + padding: 0 7.5px 15px 15px !important; + } + } + } +} diff --git a/src/theme/media/cityLinkage.scss b/src/theme/media/cityLinkage.scss new file mode 100644 index 0000000..1394156 --- /dev/null +++ b/src/theme/media/cityLinkage.scss @@ -0,0 +1,10 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-cascader__dropdown.el-popper { + overflow: auto; + max-width: 100%; + } +} diff --git a/src/theme/media/date.scss b/src/theme/media/date.scss new file mode 100644 index 0000000..1a50397 --- /dev/null +++ b/src/theme/media/date.scss @@ -0,0 +1,25 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // 时间选择器适配 + .el-date-range-picker { + width: 100vw; + .el-picker-panel__body { + min-width: 100%; + .el-date-range-picker__content { + .el-date-range-picker__header div { + margin-left: 22px; + margin-right: 0px; + } + & + .el-date-range-picker__content { + .el-date-range-picker__header div { + margin-left: 0px; + margin-right: 22px; + } + } + } + } + } +} diff --git a/src/theme/media/dialog.scss b/src/theme/media/dialog.scss new file mode 100644 index 0000000..023ccae --- /dev/null +++ b/src/theme/media/dialog.scss @@ -0,0 +1,12 @@ +@import './index.scss'; + +/* 页面宽度小于800px +------------------------------- */ +@media screen and (max-width: 800px) { + .el-dialog { + width: 90% !important; + } + .el-dialog.is-fullscreen { + width: 100% !important; + } +} diff --git a/src/theme/media/error.scss b/src/theme/media/error.scss new file mode 100644 index 0000000..f35015f --- /dev/null +++ b/src/theme/media/error.scss @@ -0,0 +1,45 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .error { + .error-flex { + flex-direction: column-reverse !important; + height: auto !important; + width: 100% !important; + } + .right, + .left { + flex: unset !important; + display: flex !important; + } + .left-item { + margin: auto !important; + } + .right img { + max-width: 450px !important; + @extend .left-item; + } + } +} + +/* 页面宽度大于768px小于992px +------------------------------- */ +@media screen and (min-width: $sm) and (max-width: $md) { + .error { + .error-flex { + padding-left: 30px !important; + } + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .error { + .error-flex { + padding: 0 30px; + } + } +} diff --git a/src/theme/media/form.scss b/src/theme/media/form.scss new file mode 100644 index 0000000..098300b --- /dev/null +++ b/src/theme/media/form.scss @@ -0,0 +1,16 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-form-item__label { + width: 100% !important; + text-align: left !important; + } + .el-form-item__content { + margin-left: 0 !important; + } + .el-form-item { + display: unset !important; + } +} diff --git a/src/theme/media/home.scss b/src/theme/media/home.scss new file mode 100644 index 0000000..5a2417e --- /dev/null +++ b/src/theme/media/home.scss @@ -0,0 +1,23 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .home-media, + .home-media-sm { + margin-top: 15px; + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .home-media-lg { + margin-top: 15px; + } + .home-monitor { + .flex-warp-item { + width: 33.33% !important; + } + } +} diff --git a/src/theme/media/index.scss b/src/theme/media/index.scss new file mode 100644 index 0000000..4761c0c --- /dev/null +++ b/src/theme/media/index.scss @@ -0,0 +1,15 @@ +/* 栅格布局(媒体查询变量) +* https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Media_queries +* $us ≥376px 响应式栅格 +* $xs ≥576px 响应式栅格 +* $sm ≥768px 响应式栅格 +* $md ≥992px 响应式栅格 +* $lg ≥1200px 响应式栅格 +* $xl ≥1920px 响应式栅格 +------------------------------- */ +$us: 376px; +$xs: 576px; +$sm: 768px; +$md: 992px; +$lg: 1200px; +$xl: 1920px; diff --git a/src/theme/media/layout.scss b/src/theme/media/layout.scss new file mode 100644 index 0000000..77cbec0 --- /dev/null +++ b/src/theme/media/layout.scss @@ -0,0 +1,55 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + // MessageBox 弹框 + .el-message-box { + width: 80% !important; + } +} + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // Breadcrumb 面包屑 + .layout-navbars-breadcrumb-hide { + display: none; + } + // 外链视图 + .layout-view-link { + a { + max-width: 80%; + text-align: center; + } + } + // 菜单搜索 + .layout-search-dialog { + .el-autocomplete { + width: 80% !important; + } + } +} + +/* 页面宽度小于1000px +------------------------------- */ +@media screen and (max-width: 1000px) { + // 布局配置 + .layout-drawer-content-flex { + position: relative; + &::after { + content: '手机版不支持切换布局'; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + text-align: center; + height: 140px; + line-height: 140px; + background: rgba(255, 255, 255, 0.9); + color: #666666; + } + } +} diff --git a/src/theme/media/login.scss b/src/theme/media/login.scss new file mode 100644 index 0000000..41a0159 --- /dev/null +++ b/src/theme/media/login.scss @@ -0,0 +1,63 @@ +@import './index.scss'; + +/* 页面宽度小于992px +------------------------------- */ +@media screen and (max-width: $lg) { + .login-container { + .login-icon-group { + &::before { + content: ''; + height: 70% !important; + transition: all 0.3s ease; + } + &::after { + content: ''; + width: 100px !important; + height: 200px !important; + transition: all 0.3s ease; + } + } + } +} + +/* 页面宽度小于992px +------------------------------- */ +@media screen and (max-width: $md) { + .login-content { + right: unset !important; + left: 50% !important; + transform: translate(-50%, -50%) translate3d(0, 0, 0) !important; + } +} + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .login-container { + .login-icon-group { + display: none !important; + } + .login-content { + width: 100% !important; + height: 100% !important; + padding: 20px 0 !important; + border-radius: 0 !important; + box-shadow: unset !important; + border: none !important; + } + .el-form-item { + display: flex !important; + } + } +} + +/* 页面宽度小于375px +------------------------------- */ +@media screen and (max-width: $us) { + .login-container { + .login-content-title { + font-size: 18px !important; + transition: all 0.3s ease; + } + } +} diff --git a/src/theme/media/media.scss b/src/theme/media/media.scss new file mode 100644 index 0000000..bed1c35 --- /dev/null +++ b/src/theme/media/media.scss @@ -0,0 +1,13 @@ +@import './login.scss'; +@import './error.scss'; +@import './layout.scss'; +@import './personal.scss'; +@import './tagsView.scss'; +@import './home.scss'; +@import './chart.scss'; +@import './form.scss'; +@import './scrollbar.scss'; +@import './pagination.scss'; +@import './dialog.scss'; +@import './cityLinkage.scss'; +@import './date.scss'; diff --git a/src/theme/media/pagination.scss b/src/theme/media/pagination.scss new file mode 100644 index 0000000..400ebaa --- /dev/null +++ b/src/theme/media/pagination.scss @@ -0,0 +1,15 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-pager, + .el-pagination__jump { + display: none !important; + } +} + +// 默认居中对齐 +.el-pagination { + text-align: center !important; +} diff --git a/src/theme/media/personal.scss b/src/theme/media/personal.scss new file mode 100644 index 0000000..7ec0d4a --- /dev/null +++ b/src/theme/media/personal.scss @@ -0,0 +1,16 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .personal-info { + padding-left: 0 !important; + margin-top: 15px; + } + .personal-recommend-col { + margin-bottom: 15px; + &:last-of-type { + margin-bottom: 0; + } + } +} diff --git a/src/theme/media/scrollbar.scss b/src/theme/media/scrollbar.scss new file mode 100644 index 0000000..968a79d --- /dev/null +++ b/src/theme/media/scrollbar.scss @@ -0,0 +1,56 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // 滚动条的宽度 + ::-webkit-scrollbar { + width: 3px !important; + height: 3px !important; + } + ::-webkit-scrollbar-track-piece { + background-color: var(--next-bg-main-color); + } + // 滚动条的设置 + ::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.3); + background-clip: padding-box; + min-height: 28px; + border-radius: 5px; + transition: 0.3s background-color; + } + ::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.5); + } + // element plus scrollbar + .el-scrollbar__bar.is-vertical { + width: 2px !important; + } + .el-scrollbar__bar.is-horizontal { + height: 2px !important; + } +} + +/* 页面宽度大于768px +------------------------------- */ +@media screen and (min-width: 769px) { + // 滚动条的宽度 + ::-webkit-scrollbar { + width: 7px; + height: 7px; + } + ::-webkit-scrollbar-track-piece { + background-color: var(--next-bg-main-color); + } + // 滚动条的设置 + ::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.3); + background-clip: padding-box; + min-height: 28px; + border-radius: 5px; + transition: 0.3s background-color; + } + ::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.5); + } +} diff --git a/src/theme/media/tagsView.scss b/src/theme/media/tagsView.scss new file mode 100644 index 0000000..b71674e --- /dev/null +++ b/src/theme/media/tagsView.scss @@ -0,0 +1,11 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .tags-view-form { + .tags-view-form-col { + margin-bottom: 20px; + } + } +} diff --git a/src/theme/mixins/index.scss b/src/theme/mixins/index.scss new file mode 100644 index 0000000..61f3c6b --- /dev/null +++ b/src/theme/mixins/index.scss @@ -0,0 +1,56 @@ +/* 第三方图标字体间距/大小设置 +------------------------------- */ +@mixin generalIcon { + font-size: 14px !important; + display: inline-block; + vertical-align: middle; + margin-right: 5px; + width: 24px; + text-align: center; + justify-content: center; +} + +/* 文本不换行 +------------------------------- */ +@mixin text-no-wrap() { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +/* 多行文本溢出 + ------------------------------- */ +@mixin text-ellipsis($line: 2) { + overflow: hidden; + word-break: break-all; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: $line; + -webkit-box-orient: vertical; +} + +/* 滚动条(页面未使用) div 中使用: + ------------------------------- */ +// .test { +// @include scrollBar; +// } +@mixin scrollBar { + // 滚动条凹槽的颜色,还可以设置边框属性 + &::-webkit-scrollbar-track-piece { + background-color: #f8f8f8; + } + // 滚动条的宽度 + &::-webkit-scrollbar { + width: 9px; + height: 9px; + } + // 滚动条的设置 + &::-webkit-scrollbar-thumb { + background-color: #dddddd; + background-clip: padding-box; + min-height: 28px; + } + &::-webkit-scrollbar-thumb:hover { + background-color: #bbb; + } +} diff --git a/src/theme/other.scss b/src/theme/other.scss new file mode 100644 index 0000000..a0451b8 --- /dev/null +++ b/src/theme/other.scss @@ -0,0 +1,36 @@ +/* wangeditor富文本编辑器 +------------------------------- */ +.editor-container { + z-index: 9999; + .w-e-toolbar { + border: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-bottom: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + z-index: 2 !important; + } + .w-e-text-container { + border: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-top: none !important; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + z-index: 1 !important; + } +} + +[data-theme='dark'] { + // textarea - css vars + --w-e-textarea-bg-color: var(--el-color-white) !important; + --w-e-textarea-color: var(--el-text-color-primary) !important; + + // toolbar - css vars + --w-e-toolbar-color: var(--el-text-color-primary) !important; + --w-e-toolbar-bg-color: var(--el-color-white) !important; + --w-e-toolbar-active-color: var(--el-text-color-primary) !important; + --w-e-toolbar-active-bg-color: var(--next-color-menu-hover) !important; + --w-e-toolbar-border-color: var(--el-border-color-light, #ebeef5) !important; + + // modal - css vars + --w-e-modal-button-bg-color: var(--el-color-primary) !important; + --w-e-modal-button-border-color: var(--el-color-primary) !important; +} diff --git a/src/theme/waves.scss b/src/theme/waves.scss new file mode 100644 index 0000000..23add2c --- /dev/null +++ b/src/theme/waves.scss @@ -0,0 +1,101 @@ +/* Waves v0.6.0 +* http://fian.my.id/Waves +* +* Copyright 2014 Alfiana E. Sibuea and other contributors +* Released under the MIT license +* https://github.com/fians/Waves/blob/master/LICENSE +*/ +.waves-effect { + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + vertical-align: middle; + z-index: 1; + will-change: opacity, transform; + transition: all 0.3s ease-out; +} +.waves-effect .waves-ripple { + position: absolute; + border-radius: 50%; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + opacity: 0; + background: rgba(0, 0, 0, 0.2); + transition: all 0.7s ease-out; + transition-property: opacity, -webkit-transform; + transition-property: transform, opacity; + transition-property: transform, opacity, -webkit-transform; + -webkit-transform: scale(0); + transform: scale(0); + pointer-events: none; +} +.waves-effect.waves-light .waves-ripple { + background-color: rgba(255, 255, 255, 0.45); +} +.waves-effect.waves-red .waves-ripple { + background-color: rgba(244, 67, 54, 0.7); +} +.waves-effect.waves-yellow .waves-ripple { + background-color: rgba(255, 235, 59, 0.7); +} +.waves-effect.waves-orange .waves-ripple { + background-color: rgba(255, 152, 0, 0.7); +} +.waves-effect.waves-purple .waves-ripple { + background-color: rgba(156, 39, 176, 0.7); +} +.waves-effect.waves-green .waves-ripple { + background-color: rgba(76, 175, 80, 0.7); +} +.waves-effect.waves-teal .waves-ripple { + background-color: rgba(0, 150, 136, 0.7); +} +.waves-effect input[type='button'], +.waves-effect input[type='reset'], +.waves-effect input[type='submit'] { + border: 0; + font-style: normal; + font-size: inherit; + text-transform: inherit; + background: none; +} +.waves-notransition { + transition: none !important; +} +.waves-circle { + -webkit-transform: translateZ(0); + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, #fff 100%, #000 100%); +} +.waves-input-wrapper { + border-radius: 0.2em; + vertical-align: bottom; +} +.waves-input-wrapper .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; +} +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; + -webkit-mask-image: none; +} +.waves-block { + display: block; +} +a.waves-effect .waves-ripple { + z-index: -1; +} diff --git a/src/utils/arrayOperation.ts b/src/utils/arrayOperation.ts new file mode 100644 index 0000000..a85deee --- /dev/null +++ b/src/utils/arrayOperation.ts @@ -0,0 +1,66 @@ +/** + * 判断两数组字符串是否相同(用于按钮权限验证),数组字符串中存在相同时会自动去重(按钮权限标识不会重复) + * @param news 新数据 + * @param old 源数据 + * @returns 两数组相同返回 `true`,反之则反 + */ +export function judementSameArr(newArr: unknown[] | string[], oldArr: string[]): boolean { + const news = removeDuplicate(newArr); + const olds = removeDuplicate(oldArr); + let count = 0; + const leng = olds.length; + for (let i in olds) { + for (let j in news) { + if (olds[i] === news[j]) count++; + } + } + return count === leng ? true : false; +} + +/** + * 判断两个对象是否相同 + * @param a 要比较的对象一 + * @param b 要比较的对象二 + * @returns 相同返回 true,反之则反 + */ +export function isObjectValueEqual(a: { [key: string]: any }, b: { [key: string]: any }) { + if (!a || !b) return false; + let aProps = Object.getOwnPropertyNames(a); + let bProps = Object.getOwnPropertyNames(b); + if (aProps.length != bProps.length) return false; + for (let i = 0; i < aProps.length; i++) { + let propName = aProps[i]; + let propA = a[propName]; + let propB = b[propName]; + if (!b.hasOwnProperty(propName)) return false; + if (propA instanceof Object) { + if (!isObjectValueEqual(propA, propB)) return false; + } else if (propA !== propB) { + return false; + } + } + return true; +} + +/** + * 数组、数组对象去重 + * @param arr 数组内容 + * @param attr 需要去重的键值(数组对象) + * @returns + */ +export function removeDuplicate(arr: any, attr?: string) { + if (!arr && !arr.length) { + return arr; + } else { + if (attr) { + const obj: any = {}; + const newArr = arr.reduce((cur: any, item: any) => { + obj[item[attr]] ? '' : (obj[item[attr]] = true && item[attr] && cur.push(item)); + return cur; + }, []); + return newArr; + } else { + return Array.from(new Set([...arr])); + } + } +} diff --git a/src/utils/authDirective.ts b/src/utils/authDirective.ts new file mode 100644 index 0000000..5971e64 --- /dev/null +++ b/src/utils/authDirective.ts @@ -0,0 +1,40 @@ +import type { App } from 'vue'; +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +/** + * 用户权限指令 + * @directive 单个权限验证(v-auth="xxx") + * @directive 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]") + * @directive 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]") + */ +export function authDirective(app: App) { + // 单个权限验证(v-auth="xxx") + app.directive('auth', { + mounted(el, binding) { + const stores = useUserInfo(); + if (!stores.userInfos.authBtnList.some((v: string) => v === binding.value)) el.parentNode.removeChild(el); + }, + }); + // 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]") + app.directive('auths', { + mounted(el, binding) { + let flag = false; + const stores = useUserInfo(); + stores.userInfos.authBtnList.map((val: string) => { + binding.value.map((v: string) => { + if (val === v) flag = true; + }); + }); + if (!flag) el.parentNode.removeChild(el); + }, + }); + // 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]") + app.directive('auth-all', { + mounted(el, binding) { + const stores = useUserInfo(); + const flag = judementSameArr(binding.value, stores.userInfos.authBtnList); + if (!flag) el.parentNode.removeChild(el); + }, + }); +} diff --git a/src/utils/authFunction.ts b/src/utils/authFunction.ts new file mode 100644 index 0000000..84c0ab4 --- /dev/null +++ b/src/utils/authFunction.ts @@ -0,0 +1,38 @@ +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +/** + * 单个权限验证 + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function auth(value: string): boolean { + const stores = useUserInfo(); + return stores.userInfos.authBtnList.some((v: string) => v === value); +} + +/** + * 多个权限验证,满足一个则为 true + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function auths(value: Array<string>): boolean { + let flag = false; + const stores = useUserInfo(); + stores.userInfos.authBtnList.map((val: string) => { + value.map((v: string) => { + if (val === v) flag = true; + }); + }); + return flag; +} + +/** + * 多个权限验证,全部满足则为 true + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function authAll(value: Array<string>): boolean { + const stores = useUserInfo(); + return judementSameArr(value, stores.userInfos.authBtnList); +} diff --git a/src/utils/commonFunction.ts b/src/utils/commonFunction.ts new file mode 100644 index 0000000..1c069e6 --- /dev/null +++ b/src/utils/commonFunction.ts @@ -0,0 +1,65 @@ +// 通用函数 +import useClipboard from 'vue-clipboard3'; +import { ElMessage } from 'element-plus'; +import { formatDate } from '/@/utils/formatTime'; +import { useI18n } from 'vue-i18n'; + +export default function () { + const { t } = useI18n(); + const { toClipboard } = useClipboard(); + //百分比格式化 + const percentFormat = (row: any, column: number, cellValue: any) => { + return cellValue ? `${cellValue}%` : '-'; + }; + //列表日期时间格式化 + const dateFormatYMD = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + return formatDate(new Date(cellValue), 'YYYY-mm-dd'); + }; + //列表日期时间格式化 + const dateFormatYMDHMS = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + return formatDate(new Date(cellValue), 'YYYY-mm-dd HH:MM:SS'); + }; + //列表日期时间格式化 + const dateFormatHMS = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + let time = 0; + if (typeof row === 'number') time = row; + if (typeof cellValue === 'number') time = cellValue; + return formatDate(new Date(time * 1000), 'HH:MM:SS'); + }; + // 小数格式化 + const scaleFormat = (value: any = 0, scale: number = 4) => { + return Number.parseFloat(value).toFixed(scale); + }; + // 小数格式化 + const scale2Format = (value: any = 0) => { + return Number.parseFloat(value).toFixed(2); + }; + // 点击复制文本 + const copyText = (text: string) => { + return new Promise((resolve, reject) => { + try { + //复制 + toClipboard(text); + //下面可以设置复制成功的提示框等操作 + ElMessage.success(t('message.layout.copyTextSuccess')); + resolve(text); + } catch (e) { + //复制失败 + ElMessage.error(t('message.layout.copyTextError')); + reject(e); + } + }); + }; + return { + percentFormat, + dateFormatYMD, + dateFormatYMDHMS, + dateFormatHMS, + scaleFormat, + scale2Format, + copyText, + }; +} diff --git a/src/utils/customDirective.ts b/src/utils/customDirective.ts new file mode 100644 index 0000000..c67350f --- /dev/null +++ b/src/utils/customDirective.ts @@ -0,0 +1,178 @@ +import type { App } from 'vue'; + +/** + * 按钮波浪指令 + * @directive 默认方式:v-waves,如 `<div v-waves></div>` + * @directive 参数方式:v-waves=" |light|red|orange|purple|green|teal",如 `<div v-waves="'light'"></div>` + */ +export function wavesDirective(app: App) { + app.directive('waves', { + mounted(el, binding) { + el.classList.add('waves-effect'); + binding.value && el.classList.add(`waves-${binding.value}`); + function setConvertStyle(obj: { [key: string]: unknown }) { + let style: string = ''; + for (let i in obj) { + if (obj.hasOwnProperty(i)) style += `${i}:${obj[i]};`; + } + return style; + } + function onCurrentClick(e: { [key: string]: unknown }) { + let elDiv = document.createElement('div'); + elDiv.classList.add('waves-ripple'); + el.appendChild(elDiv); + let styles = { + left: `${e.layerX}px`, + top: `${e.layerY}px`, + opacity: 1, + transform: `scale(${(el.clientWidth / 100) * 10})`, + 'transition-duration': `750ms`, + 'transition-timing-function': `cubic-bezier(0.250, 0.460, 0.450, 0.940)`, + }; + elDiv.setAttribute('style', setConvertStyle(styles)); + setTimeout(() => { + elDiv.setAttribute( + 'style', + setConvertStyle({ + opacity: 0, + transform: styles.transform, + left: styles.left, + top: styles.top, + }) + ); + setTimeout(() => { + elDiv && el.removeChild(elDiv); + }, 750); + }, 450); + } + el.addEventListener('mousedown', onCurrentClick, false); + }, + unmounted(el) { + el.addEventListener('mousedown', () => {}); + }, + }); +} + +/** + * 自定义拖动指令 + * @description 使用方式:v-drag="[dragDom,dragHeader]",如 `<div v-drag="['.drag-container .el-dialog', '.drag-container .el-dialog__header']"></div>` + * @description dragDom 要拖动的元素,dragHeader 要拖动的 Header 位置 + * @link 注意:https://github.com/element-plus/element-plus/issues/522 + * @lick 参考:https://blog.csdn.net/weixin_46391323/article/details/105228020?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-10&spm=1001.2101.3001.4242 + */ +export function dragDirective(app: App) { + app.directive('drag', { + mounted(el, binding) { + if (!binding.value) return false; + + const dragDom = document.querySelector(binding.value[0]) as HTMLElement; + const dragHeader = document.querySelector(binding.value[1]) as HTMLElement; + + dragHeader.onmouseover = () => (dragHeader.style.cursor = `move`); + + function down(e: any, type: string) { + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = type === 'pc' ? e.clientX - dragHeader.offsetLeft : e.touches[0].clientX - dragHeader.offsetLeft; + const disY = type === 'pc' ? e.clientY - dragHeader.offsetTop : e.touches[0].clientY - dragHeader.offsetTop; + + // body当前宽度 + const screenWidth = document.body.clientWidth; + // 可见区域高度(应为body高度,可某些环境下无法获取) + const screenHeight = document.documentElement.clientHeight; + + // 对话框宽度 + const dragDomWidth = dragDom.offsetWidth; + // 对话框高度 + const dragDomheight = dragDom.offsetHeight; + + const minDragDomLeft = dragDom.offsetLeft; + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; + + const minDragDomTop = dragDom.offsetTop; + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight; + + // 获取到的值带px 正则匹配替换 + let styL: any = getComputedStyle(dragDom).left; + let styT: any = getComputedStyle(dragDom).top; + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (styL.includes('%')) { + styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100); + styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100); + } else { + styL = +styL.replace(/\px/g, ''); + styT = +styT.replace(/\px/g, ''); + } + + return { + disX, + disY, + minDragDomLeft, + maxDragDomLeft, + minDragDomTop, + maxDragDomTop, + styL, + styT, + }; + } + + function move(e: any, type: string, obj: any) { + let { disX, disY, minDragDomLeft, maxDragDomLeft, minDragDomTop, maxDragDomTop, styL, styT } = obj; + + // 通过事件委托,计算移动的距离 + let left = type === 'pc' ? e.clientX - disX : e.touches[0].clientX - disX; + let top = type === 'pc' ? e.clientY - disY : e.touches[0].clientY - disY; + + // 边界处理 + if (-left > minDragDomLeft) { + left = -minDragDomLeft; + } else if (left > maxDragDomLeft) { + left = maxDragDomLeft; + } + + if (-top > minDragDomTop) { + top = -minDragDomTop; + } else if (top > maxDragDomTop) { + top = maxDragDomTop; + } + + // 移动当前元素 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`; + } + + /** + * pc端 + * onmousedown 鼠标按下触发事件 + * onmousemove 鼠标按下时持续触发事件 + * onmouseup 鼠标抬起触发事件 + */ + dragHeader.onmousedown = (e) => { + const obj = down(e, 'pc'); + document.onmousemove = (e) => { + move(e, 'pc', obj); + }; + document.onmouseup = () => { + document.onmousemove = null; + document.onmouseup = null; + }; + }; + + /** + * 移动端 + * ontouchstart 当按下手指时,触发ontouchstart + * ontouchmove 当移动手指时,触发ontouchmove + * ontouchend 当移走手指时,触发ontouchend + */ + dragHeader.ontouchstart = (e) => { + const obj = down(e, 'app'); + document.ontouchmove = (e) => { + move(e, 'app', obj); + }; + document.ontouchend = () => { + document.ontouchmove = null; + document.ontouchend = null; + }; + }; + }, + }); +} diff --git a/src/utils/directive.ts b/src/utils/directive.ts new file mode 100644 index 0000000..a75b187 --- /dev/null +++ b/src/utils/directive.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue'; +import { authDirective } from '/@/utils/authDirective'; +import { wavesDirective, dragDirective } from '/@/utils/customDirective'; + +/** + * 导出指令方法:v-xxx + * @methods authDirective 用户权限指令,用法:v-auth + * @methods wavesDirective 按钮波浪指令,用法:v-waves + * @methods dragDirective 自定义拖动指令,用法:v-drag + */ +export function directive(app: App) { + // 用户权限指令 + authDirective(app); + // 按钮波浪指令 + wavesDirective(app); + // 自定义拖动指令 + dragDirective(app); +} diff --git a/src/utils/formatTime.ts b/src/utils/formatTime.ts new file mode 100644 index 0000000..441e30c --- /dev/null +++ b/src/utils/formatTime.ts @@ -0,0 +1,137 @@ +/** + * 时间日期转换 + * @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 { + let we = date.getDay(); // 星期 + let z = getWeek(date); // 周 + let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度 + const opt: { [key: string]: string } = { + 'Y+': date.getFullYear().toString(), // 年 + 'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始,要+1) + 'd+': date.getDate().toString(), // 日 + 'H+': date.getHours().toString(), // 时 + 'M+': date.getMinutes().toString(), // 分 + 'S+': date.getSeconds().toString(), // 秒 + 'q+': qut, // 季度 + }; + // 中文数字 (星期) + const week: { [key: string]: string } = { + '0': '日', + '1': '一', + '2': '二', + '3': '三', + '4': '四', + '5': '五', + '6': '六', + }; + // 中文数字(季度) + const quarter: { [key: string]: string } = { + '1': '一', + '2': '二', + '3': '三', + '4': '四', + }; + if (/(W+)/.test(format)) + format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]); + if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]); + if (/(Z+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 3 ? '第' + z + '周' : z + ''); + for (let k in opt) { + let r = new RegExp('(' + k + ')').exec(format); + // 若输入的长度不为1,则前面补零 + if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0')); + } + return format; +} + +/** + * 获取当前日期是第几周 + * @param dateTime 当前传入的日期值 + * @returns 返回第几周数字值 + */ +export function getWeek(dateTime: Date): number { + let temptTime = new Date(dateTime.getTime()); + // 周几 + let weekday = temptTime.getDay() || 7; + // 周1+5天=周六 + temptTime.setDate(temptTime.getDate() - weekday + 1 + 5); + let firstDay = new Date(temptTime.getFullYear(), 0, 1); + let dayOfWeek = firstDay.getDay(); + let spendDay = 1; + if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1; + firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay); + let d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000); + let result = Math.ceil(d / 7); + return result; +} + +/** + * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前` + * @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: string = 'YYYY-mm-dd'): 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天 + let 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 { + let 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 '夜里好'; +} diff --git a/src/utils/getStyleSheets.ts b/src/utils/getStyleSheets.ts new file mode 100644 index 0000000..90252c3 --- /dev/null +++ b/src/utils/getStyleSheets.ts @@ -0,0 +1,101 @@ +import { nextTick } from 'vue'; +import * as svg from '@element-plus/icons-vue'; + +// 获取阿里字体图标 +const getAlicdnIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const styles: any = document.styleSheets; + let sheetsList = []; + let sheetsIconList = []; + for (let i = 0; i < styles.length; i++) { + if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) { + sheetsList.push(styles[i]); + } + } + for (let i = 0; i < sheetsList.length; i++) { + for (let j = 0; j < sheetsList[i].cssRules.length; j++) { + if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) { + sheetsIconList.push( + `${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}` + ); + } + } + } + if (sheetsIconList.length > 0) resolve(sheetsIconList); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 ele- 前缀,使用时:ele-Aim +const getElementPlusIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const icons = svg as any; + const sheetsIconList = []; + for (const i in icons) { + sheetsIconList.push(`ele-${icons[i].name}`); + } + if (sheetsIconList.length > 0) resolve(sheetsIconList); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +// 初始化获取 css 样式,这里使用 fontawesome 的图标 +const getAwesomeIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const styles: any = document.styleSheets; + let sheetsList = []; + let sheetsIconList = []; + for (let i = 0; i < styles.length; i++) { + if (styles[i].href && styles[i].href.indexOf('netdna.bootstrapcdn.com') > -1) { + sheetsList.push(styles[i]); + } + } + for (let i = 0; i < sheetsList.length; i++) { + for (let j = 0; j < sheetsList[i].cssRules.length; j++) { + if ( + sheetsList[i].cssRules[j].selectorText && + sheetsList[i].cssRules[j].selectorText.indexOf('.fa-') === 0 && + sheetsList[i].cssRules[j].selectorText.indexOf(',') === -1 + ) { + if (/::before/.test(sheetsList[i].cssRules[j].selectorText)) { + sheetsIconList.push( + `${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}` + ); + } + } + } + } + if (sheetsIconList.length > 0) resolve(sheetsIconList.reverse()); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +/** + * 获取字体图标 `document.styleSheets` + * @method ali 获取阿里字体图标 `<i class="iconfont 图标类名"></i>` + * @method ele 获取 element plus 自带图标 `<i class="图标类名"></i>` + * @method ali 获取 fontawesome 的图标 `<i class="fa 图标类名"></i>` + */ +const initIconfont = { + // iconfont + ali: () => { + return getAlicdnIconfont(); + }, + // element plus + ele: () => { + return getElementPlusIconfont(); + }, + // fontawesome + awe: () => { + return getAwesomeIconfont(); + }, +}; + +// 导出方法 +export default initIconfont; diff --git a/src/utils/loading.ts b/src/utils/loading.ts new file mode 100644 index 0000000..c23fb77 --- /dev/null +++ b/src/utils/loading.ts @@ -0,0 +1,42 @@ +import { nextTick } from 'vue'; +import '/@/theme/loading.scss'; + +/** + * 页面全局 Loading + * @method start 创建 loading + * @method done 移除 loading + */ +export const NextLoading = { + // 创建 loading + start: () => { + const bodys: Element = document.body; + const div = <HTMLElement>document.createElement('div'); + div.setAttribute('class', 'loading-next'); + const htmls = ` + <div class="loading-next-box"> + <div class="loading-next-box-warp"> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + </div> + </div> + `; + div.innerHTML = htmls; + bodys.insertBefore(div, bodys.childNodes[0]); + window.nextLoading = true; + }, + // 移除 loading + done: () => { + nextTick(() => { + window.nextLoading = false; + const el = <HTMLElement>document.querySelector('.loading-next'); + el?.parentNode?.removeChild(el); + }); + }, +}; diff --git a/src/utils/other.ts b/src/utils/other.ts new file mode 100644 index 0000000..6bb4fbd --- /dev/null +++ b/src/utils/other.ts @@ -0,0 +1,200 @@ +import { nextTick } from 'vue'; +import type { App } from 'vue'; +import * as svg from '@element-plus/icons-vue'; +import router from '/@/router/index'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { i18n } from '/@/i18n/index'; +import { Local } from '/@/utils/storage'; +import SvgIcon from '/@/components/svgIcon/index.vue'; + +/** + * 导出全局注册 element plus svg 图标 + * @param app vue 实例 + * @description 使用:https://element-plus.gitee.io/zh-CN/component/icon.html + */ +export function elSvg(app: App) { + const icons = svg as any; + for (const i in icons) { + app.component(`ele-${icons[i].name}`, icons[i]); + } + app.component('SvgIcon', SvgIcon); +} + +/** + * 设置浏览器标题国际化 + * @method const title = useTitle(); ==> title() + */ +export function useTitle() { + const stores = useThemeConfig(pinia); + const { themeConfig } = storeToRefs(stores); + nextTick(() => { + let webTitle = ''; + let globalTitle: string = themeConfig.value.globalTitle; + const { path, meta } = router.currentRoute.value; + if (path === '/login') { + webTitle = <any>meta.title; + } else { + webTitle = setTagsViewNameI18n(router.currentRoute.value); + } + document.title = `${webTitle} - ${globalTitle}` || globalTitle; + }); +} + +/** + * 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + * @param params 路由 query、params 中的 tagsViewName + * @returns 返回当前 tagsViewName 名称 + */ +export function setTagsViewNameI18n(item: any) { + let tagsViewName: any = ''; + const { query, params, meta } = item; + if (query?.tagsViewName || params?.tagsViewName) { + if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/(zh-cn|en|zh-tw)\//.test(params?.tagsViewName)) { + // 国际化 + const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName)); + tagsViewName = urlTagsParams[i18n.global.locale]; + } else { + // 非国际化 + tagsViewName = query?.tagsViewName || params?.tagsViewName; + } + } else { + // 非自定义 tagsView 名称 + tagsViewName = i18n.global.t(<any>meta.title); + } + return tagsViewName; +} + +/** + * 图片懒加载 + * @param el dom 目标元素 + * @param arr 列表数据 + * @description data-xxx 属性用于存储页面或应用程序的私有自定义数据 + */ +export const lazyImg = (el: any, arr: any) => { + const io = new IntersectionObserver((res) => { + res.forEach((v: any) => { + if (v.isIntersecting) { + const { img, key } = v.target.dataset; + v.target.src = img; + v.target.onload = () => { + io.unobserve(v.target); + arr[key]['loading'] = false; + }; + } + }); + }); + nextTick(() => { + document.querySelectorAll(el).forEach((img) => io.observe(img)); + }); +}; + +/** + * 全局组件大小 + * @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize` + */ +export const globalComponentSize = (): string => { + const stores = useThemeConfig(pinia); + const { themeConfig } = storeToRefs(stores); + return Local.get('themeConfig')?.globalComponentSize || themeConfig.value?.globalComponentSize; +}; + +/** + * 对象深克隆 + * @param obj 源对象 + * @returns 克隆后的对象 + */ +export function deepClone(obj: any) { + let newObj: any; + try { + newObj = obj.push ? [] : {}; + } catch (error) { + newObj = {}; + } + for (let attr in obj) { + if (obj[attr] && typeof obj[attr] === 'object') { + newObj[attr] = deepClone(obj[attr]); + } else { + newObj[attr] = obj[attr]; + } + } + return newObj; +} + +/** + * 判断是否是移动端 + */ +export function isMobile() { + if ( + navigator.userAgent.match( + /('phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')/i + ) + ) { + return true; + } else { + return false; + } +} + +/** + * 判断数组对象中所有属性是否为空,为空则删除当前行对象 + * @description @感谢大黄 + * @param list 数组对象 + * @returns 删除空值后的数组对象 + */ +export function handleEmpty(list: any) { + const arr = []; + for (const i in list) { + const d = []; + for (const j in list[i]) { + d.push(list[i][j]); + } + const leng = d.filter((item) => item === '').length; + if (leng !== d.length) { + arr.push(list[i]); + } + } + return arr; +} + +/** + * 统一批量导出 + * @method elSvg 导出全局注册 element plus svg 图标 + * @method useTitle 设置浏览器标题国际化 + * @method setTagsViewNameI18n 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + * @method lazyImg 图片懒加载 + * @method globalComponentSize() element plus 全局组件大小 + * @method deepClone 对象深克隆 + * @method isMobile 判断是否是移动端 + * @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象 + */ +const other = { + elSvg: (app: App) => { + elSvg(app); + }, + useTitle: () => { + useTitle(); + }, + setTagsViewNameI18n(route: any) { + return setTagsViewNameI18n(route); + }, + lazyImg: (el: any, arr: any) => { + lazyImg(el, arr); + }, + globalComponentSize: () => { + return globalComponentSize(); + }, + deepClone: (obj: any) => { + return deepClone(obj); + }, + isMobile: () => { + return isMobile(); + }, + handleEmpty: (list: any) => { + return handleEmpty(list); + }, +}; + +// 统一批量导出 +export default other; diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..146e09b --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,72 @@ +import axios from 'axios'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import { Session } from '/@/utils/storage'; + +// 配置新建一个 axios 实例 +const service = axios.create({ + baseURL: import.meta.env.VITE_API_URL as any, + timeout: 50000, + headers: { 'Content-Type': 'application/json' }, +}); + +service.interceptors.request.use( + (config) => { + // 在发送请求之前做些什么 token + if (Session.get('token')) { + (<any>config.headers).common['Authorization'] = `${Session.get('token')}`; + (<any>config.headers).common['uid'] = `${Session.get('sign')}`; + } + return config; + }, + (error) => { + // 对请求错误做些什么 + return Promise.reject(error); + } +); + +service.interceptors.response.use( + + (response) => { + // 对响应数据做点什么 + if(response.data.code && (response.data.code ==='A0215' || response.data.code === 'A0214')){ + Session.clear() + window.location.href = '/' + return Promise.reject(response) + } + // if(response.data.code && response.data.code !== '200'){ + return Promise.resolve(response) + // } + // Session.clear() + // window.location.href = '/' + // return Promise.reject(response) + // const res = response.data; + // debugger + // if (res.code && res.code !== 0) { + // // `token` 过期或者账号已在别处登录 + // if (res.code === 401 || res.code === 4001) { + // Session.clear(); // 清除浏览器全部临时缓存 + // window.location.href = '/'; // 去登录页 + // ElMessageBox.alert('你已被登出,请重新登录', '提示', {}) + // .then(() => {}) + // .catch(() => {}); + // } + // return Promise.reject(service.interceptors.response); + // } else { + // return response.data; + // } + }, + (error) => { + // 对响应错误做点什么 + if (error.message.indexOf('timeout') != -1) { + ElMessage.error('网络超时'); + } else if (error.message == 'Network Error') { + ElMessage.error('网络连接错误'); + } else { + if (error.response.data) ElMessage.error(error.response.statusText); + else ElMessage.error('接口路径找不到'); + } + return Promise.reject(error); + } +); + +export default service; diff --git a/src/utils/setIconfont.ts b/src/utils/setIconfont.ts new file mode 100644 index 0000000..a6acf68 --- /dev/null +++ b/src/utils/setIconfont.ts @@ -0,0 +1,48 @@ +// 字体图标 url +const cssCdnUrlList: Array<string> = [ + '//at.alicdn.com/t/font_2298093_y6u00apwst.css', + '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css', +]; +// 第三方 js url +const jsCdnUrlList: Array<string> = []; + +// 动态批量设置字体图标 +export function setCssCdn() { + if (cssCdnUrlList.length <= 0) return false; + cssCdnUrlList.map((v) => { + let link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = v; + link.crossOrigin = 'anonymous'; + document.getElementsByTagName('head')[0].appendChild(link); + }); +} + +// 动态批量设置第三方js +export function setJsCdn() { + if (jsCdnUrlList.length <= 0) return false; + jsCdnUrlList.map((v) => { + let link = document.createElement('script'); + link.src = v; + document.body.appendChild(link); + }); +} + +/** + * 批量设置字体图标、动态js + * @method cssCdn 动态批量设置字体图标 + * @method jsCdn 动态批量设置第三方js + */ +const setIntroduction = { + // 设置css + cssCdn: () => { + setCssCdn(); + }, + // 设置js + jsCdn: () => { + setJsCdn(); + }, +}; + +// 导出函数方法 +export default setIntroduction; diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..a983f80 --- /dev/null +++ b/src/utils/storage.ts @@ -0,0 +1,59 @@ +import Cookies from 'js-cookie'; + +/** + * window.localStorage 浏览器永久缓存 + * @method set 设置永久缓存 + * @method get 获取永久缓存 + * @method remove 移除永久缓存 + * @method clear 移除全部永久缓存 + */ +export const Local = { + // 设置永久缓存 + set(key: string, val: any) { + window.localStorage.setItem(key, JSON.stringify(val)); + }, + // 获取永久缓存 + get(key: string) { + let json: any = window.localStorage.getItem(key); + return JSON.parse(json); + }, + // 移除永久缓存 + remove(key: string) { + window.localStorage.removeItem(key); + }, + // 移除全部永久缓存 + clear() { + window.localStorage.clear(); + }, +}; + +/** + * window.sessionStorage 浏览器临时缓存 + * @method set 设置临时缓存 + * @method get 获取临时缓存 + * @method remove 移除临时缓存 + * @method clear 移除全部临时缓存 + */ +export const Session = { + // 设置临时缓存 + set(key: string, val: any) { + if (key === 'token') return Cookies.set(key, val); + window.sessionStorage.setItem(key, JSON.stringify(val)); + }, + // 获取临时缓存 + get(key: string) { + if (key === 'token') return Cookies.get(key); + let json: any = window.sessionStorage.getItem(key); + return JSON.parse(json); + }, + // 移除临时缓存 + remove(key: string) { + if (key === 'token') return Cookies.remove(key); + window.sessionStorage.removeItem(key); + }, + // 移除全部临时缓存 + clear() { + Cookies.remove('token'); + window.sessionStorage.clear(); + }, +}; diff --git a/src/utils/theme.ts b/src/utils/theme.ts new file mode 100644 index 0000000..5561e64 --- /dev/null +++ b/src/utils/theme.ts @@ -0,0 +1,59 @@ +import { ElMessage } from 'element-plus'; + +/** + * hex颜色转rgb颜色 + * @param str 颜色值字符串 + * @returns 返回处理后的颜色值 + */ +export function hexToRgb(str: any) { + let hexs: any = ''; + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(str)) return ElMessage.warning('输入错误的hex'); + str = str.replace('#', ''); + hexs = str.match(/../g); + for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16); + return hexs; +} + +/** + * rgb颜色转Hex颜色 + * @param r 代表红色 + * @param g 代表绿色 + * @param b 代表蓝色 + * @returns 返回处理后的颜色值 + */ +export function rgbToHex(r: any, g: any, b: any) { + let reg = /^\d{1,3}$/; + if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage.warning('输入错误的rgb颜色值'); + let hexs = [r.toString(16), g.toString(16), b.toString(16)]; + for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`; + return `#${hexs.join('')}`; +} + +/** + * 加深颜色值 + * @param color 颜色值字符串 + * @param level 加深的程度,限0-1之间 + * @returns 返回处理后的颜色值 + */ +export function getDarkColor(color: string, level: number) { + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值'); + let rgb = hexToRgb(color); + for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level)); + return rgbToHex(rgb[0], rgb[1], rgb[2]); +} + +/** + * 变浅颜色值 + * @param color 颜色值字符串 + * @param level 加深的程度,限0-1之间 + * @returns 返回处理后的颜色值 + */ +export function getLightColor(color: string, level: number) { + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值'); + let rgb = hexToRgb(color); + for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]); + return rgbToHex(rgb[0], rgb[1], rgb[2]); +} diff --git a/src/utils/toolsValidate.ts b/src/utils/toolsValidate.ts new file mode 100644 index 0000000..f2cb9d6 --- /dev/null +++ b/src/utils/toolsValidate.ts @@ -0,0 +1,370 @@ +/** + * 2020.11.29 lyt 整理 + * 工具类集合,适用于平时开发 + * 新增多行注释信息,鼠标放到方法名即可查看 + */ + +/** + * 验证百分比(不可以小数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberPercentage(val: string): string { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 只能是数字和小数点,不能是其他输入 + v = v.replace(/[^\d]/g, ''); + // 不能以0开始 + v = v.replace(/^0/g, ''); + // 数字超过100,赋值成最大值100 + v = v.replace(/^[1-9]\d\d{1,3}$/, '100'); + // 返回结果 + return v; +} + +/** + * 验证百分比(可以小数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberPercentageFloat(val: string): string { + let v = verifyNumberIntegerAndFloat(val); + // 数字超过100,赋值成最大值100 + v = v.replace(/^[1-9]\d\d{1,3}$/, '100'); + // 超过100之后不给再输入值 + v = v.replace(/^100\.$/, '100'); + // 返回结果 + return v; +} + +/** + * 小数或整数(不可以负数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberIntegerAndFloat(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 只能是数字和小数点,不能是其他输入 + v = v.replace(/[^\d.]/g, ''); + // 以0开始只能输入一个 + v = v.replace(/^0{2}$/g, '0'); + // 保证第一位只能是数字,不能是点 + v = v.replace(/^\./g, ''); + // 小数只能出现1位 + v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.'); + // 小数点后面保留2位 + v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3'); + // 返回结果 + return v; +} + +/** + * 正整数验证 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifiyNumberInteger(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12 + v = v.replace(/[\.]*/g, ''); + // 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323 + v = v.replace(/(^0[\d]*)$/g, '0'); + // 首位是0,只能出现一次 + v = v.replace(/^0\d$/g, '0'); + // 只匹配数字 + v = v.replace(/[^\d]/g, ''); + // 返回结果 + return v; +} + +/** + * 去掉中文及空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyCnAndSpace(val: string) { + // 匹配中文与空格 + let v = val.replace(/[\u4e00-\u9fa5\s]+/g, ''); + // 匹配空格 + v = v.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 去掉英文及空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyEnAndSpace(val: string) { + // 匹配英文与空格 + let v = val.replace(/[a-zA-Z]+/g, ''); + // 匹配空格 + v = v.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 禁止输入空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyAndSpace(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 金额用 `,` 区分开 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberComma(val: string) { + // 调用小数或整数(不可以负数)方法 + let v: any = verifyNumberIntegerAndFloat(val); + // 字符串转成数组 + v = v.toString().split('.'); + // \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符 + v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); + // 数组转字符串 + v = v.join('.'); + // 返回结果 + return v; +} + +/** + * 匹配文字变色(搜索时) + * @param val 当前值字符串 + * @param text 要处理的字符串值 + * @param color 搜索到时字体高亮颜色 + * @returns 返回处理后的字符串 + */ +export function verifyTextColor(val: string, text = '', color = 'red') { + // 返回内容,添加颜色 + let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`); + // 返回结果 + return v; +} + +/** + * 数字转中文大写 + * @param val 当前值字符串 + * @param unit 默认:仟佰拾亿仟佰拾万仟佰拾元角分 + * @returns 返回处理后的字符串 + */ +export function verifyNumberCnUppercase(val: any, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') { + // 当前内容字符串添加 2个0,为什么?? + val += '00'; + // 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1 + let lookup = val.indexOf('.'); + // substring:不包含结束下标内容,substr:包含结束下标内容 + if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2); + // 根据内容 val 的长度,截取返回对应大写 + unit = unit.substr(unit.length - val.length); + // 循环截取拼接大写 + for (let i = 0; i < val.length; i++) { + v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1); + } + // 正则处理 + v = v + .replace(/零角零分$/, '整') + .replace(/零[仟佰拾]/g, '零') + .replace(/零{2,}/g, '零') + .replace(/零([亿|万])/g, '$1') + .replace(/零+元/, '元') + .replace(/亿零{0,3}万/, '亿') + .replace(/^元/, '零元'); + // 返回结果 + return v; +} + +/** + * 手机号码 + * @param val 当前值字符串 + * @returns 返回 true: 手机号码正确 + */ +export function verifyPhone(val: string) { + // false: 手机号码不正确 + if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0|1,5-9]))\d{8}$/.test(val)) return false; + // true: 手机号码正确 + else return true; +} + +/** + * 国内电话号码 + * @param val 当前值字符串 + * @returns 返回 true: 国内电话号码正确 + */ +export function verifyTelPhone(val: string) { + // false: 国内电话号码不正确 + if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false; + // true: 国内电话号码正确 + else return true; +} + +/** + * 登录账号 (字母开头,允许5-16字节,允许字母数字下划线) + * @param val 当前值字符串 + * @returns 返回 true: 登录账号正确 + */ +export function verifyAccount(val: string) { + // false: 登录账号不正确 + if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false; + // true: 登录账号正确 + else return true; +} + +/** + * 密码 (以字母开头,长度在6~16之间,只能包含字母、数字和下划线) + * @param val 当前值字符串 + * @returns 返回 true: 密码正确 + */ +export function verifyPassword(val: string) { + // false: 密码不正确 + if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false; + // true: 密码正确 + else return true; +} + +/** + * 强密码 (字母+数字+特殊字符,长度在6-16之间) + * @param val 当前值字符串 + * @returns 返回 true: 强密码正确 + */ +export function verifyPasswordPowerful(val: string) { + // false: 强密码不正确 + if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) + return false; + // true: 强密码正确 + else return true; +} + +/** + * 密码强度 + * @param val 当前值字符串 + * @description 弱:纯数字,纯字母,纯特殊字符 + * @description 中:字母+数字,字母+特殊字符,数字+特殊字符 + * @description 强:字母+数字+特殊字符 + * @returns 返回处理后的字符串:弱、中、强 + */ +export function verifyPasswordStrength(val: string) { + let v = ''; + // 弱:纯数字,纯字母,纯特殊字符 + if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱'; + // 中:字母+数字,字母+特殊字符,数字+特殊字符 + if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中'; + // 强:字母+数字+特殊字符 + if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) + v = '强'; + // 返回结果 + return v; +} + +/** + * IP地址 + * @param val 当前值字符串 + * @returns 返回 true: IP地址正确 + */ +export function verifyIPAddress(val: string) { + // false: IP地址不正确 + if ( + !/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test( + val + ) + ) + return false; + // true: IP地址正确 + else return true; +} + +/** + * 邮箱 + * @param val 当前值字符串 + * @returns 返回 true: 邮箱正确 + */ +export function verifyEmail(val: string) { + // false: 邮箱不正确 + if ( + !/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test( + val + ) + ) + return false; + // true: 邮箱正确 + else return true; +} + +/** + * 身份证 + * @param val 当前值字符串 + * @returns 返回 true: 身份证正确 + */ +export function verifyIdCard(val: string) { + // false: 身份证不正确 + if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false; + // true: 身份证正确 + else return true; +} + +/** + * 姓名 + * @param val 当前值字符串 + * @returns 返回 true: 姓名正确 + */ +export function verifyFullName(val: string) { + // false: 姓名不正确 + if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false; + // true: 姓名正确 + else return true; +} + +/** + * 邮政编码 + * @param val 当前值字符串 + * @returns 返回 true: 邮政编码正确 + */ +export function verifyPostalCode(val: string) { + // false: 邮政编码不正确 + if (!/^[1-9][0-9]{5}$/.test(val)) return false; + // true: 邮政编码正确 + else return true; +} + +/** + * url 处理 + * @param val 当前值字符串 + * @returns 返回 true: url 正确 + */ +export function verifyUrl(val: string) { + // false: url不正确 + if ( + !/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( + val + ) + ) + return false; + // true: url正确 + else return true; +} + +/** + * 车牌号 + * @param val 当前值字符串 + * @returns 返回 true:车牌号正确 + */ +export function verifyCarNum(val: string) { + // false: 车牌号不正确 + if ( + !/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test( + val + ) + ) + return false; + // true:车牌号正确 + else return true; +} diff --git a/src/utils/wartermark.ts b/src/utils/wartermark.ts new file mode 100644 index 0000000..b897ed1 --- /dev/null +++ b/src/utils/wartermark.ts @@ -0,0 +1,47 @@ +// 页面添加水印效果 +const setWatermark = (str: string) => { + const id = '1.23452384164.123412416'; + if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id)); + const can = document.createElement('canvas'); + can.width = 200; + can.height = 130; + const cans: any = can.getContext('2d'); + cans.rotate((-20 * Math.PI) / 180); + cans.font = '12px Vedana'; + cans.fillStyle = 'rgba(200, 200, 200, 0.30)'; + cans.textBaseline = 'Middle'; + cans.fillText(str, can.width / 10, can.height / 2); + const div = document.createElement('div'); + div.id = id; + div.style.pointerEvents = 'none'; + div.style.top = '15px'; + div.style.left = '0px'; + div.style.position = 'fixed'; + div.style.zIndex = '10000000'; + 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`; + document.body.appendChild(div); + return id; +}; + +/** + * 页面添加水印效果 + * @method set 设置水印 + * @method del 删除水印 + */ +const watermark = { + // 设置水印 + set: (str: string) => { + let id = setWatermark(str); + if (document.getElementById(id) === null) id = setWatermark(str); + }, + // 删除水印 + del: () => { + let id = '1.23452384164.123412416'; + if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id)); + }, +}; + +// 导出方法 +export default watermark; diff --git a/src/views/error/401.vue b/src/views/error/401.vue new file mode 100644 index 0000000..3ca649d --- /dev/null +++ b/src/views/error/401.vue @@ -0,0 +1,117 @@ +<template> + <div class="error layout-view-bg-white" :style="{ height: `calc(100vh - ${initTagViewHeight}` }"> + <div class="error-flex"> + <div class="left"> + <div class="left-item"> + <div class="left-item-animation left-item-num">401</div> + <div class="left-item-animation left-item-title">{{ $t('message.noAccess.accessTitle') }}</div> + <div class="left-item-animation left-item-msg">{{ $t('message.noAccess.accessMsg') }}</div> + <div class="left-item-animation left-item-btn"> + <el-button type="primary" round @click="onSetAuth">{{ $t('message.noAccess.accessBtn') }}</el-button> + </div> + </div> + </div> + <div class="right"> + <img + src="https://img-blog.csdnimg.cn/3333f265772a4fa89287993500ecbf96.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_16,color_FFFFFF,t_70,g_se,x_16" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, computed } from 'vue'; +import { useRouter } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { Session } from '/@/utils/storage'; + +export default defineComponent({ + name: '401', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const router = useRouter(); + const onSetAuth = () => { + Session.clear(); + router.push('/login'); + }; + // 设置主内容的高度 + const initTagViewHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `30px`; + } else { + if (isTagsview) return `114px`; + else return `80px`; + } + }); + return { + onSetAuth, + initTagViewHeight, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.error { + height: 100%; + background-color: var(--el-color-white); + display: flex; + .error-flex { + margin: auto; + display: flex; + height: 350px; + width: 900px; + .left { + flex: 1; + height: 100%; + align-items: center; + display: flex; + .left-item { + .left-item-animation { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + } + .left-item-num { + color: var(--el-color-info); + font-size: 55px; + } + .left-item-title { + font-size: 20px; + color: var(--el-text-color-primary); + margin: 15px 0 5px 0; + animation-delay: 0.1s; + } + .left-item-msg { + color: var(--el-text-color-secondary); + font-size: 12px; + margin-bottom: 30px; + animation-delay: 0.2s; + } + .left-item-btn { + animation-delay: 0.2s; + } + } + } + .right { + flex: 1; + opacity: 0; + animation-name: error-img; + animation-duration: 2s; + animation-fill-mode: forwards; + img { + width: 100%; + height: 100%; + } + } + } +} +</style> diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..3a7ce22 --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,115 @@ +<template> + <div class="error layout-view-bg-white" :style="{ height: `calc(100vh - ${initTagViewHeight}` }"> + <div class="error-flex"> + <div class="left"> + <div class="left-item"> + <div class="left-item-animation left-item-num">404</div> + <div class="left-item-animation left-item-title">{{ $t('message.notFound.foundTitle') }}</div> + <div class="left-item-animation left-item-msg">{{ $t('message.notFound.foundMsg') }}</div> + <div class="left-item-animation left-item-btn"> + <el-button type="primary" round @click="onGoHome">{{ $t('message.notFound.foundBtn') }}</el-button> + </div> + </div> + </div> + <div class="right"> + <img + src="https://img-blog.csdnimg.cn/9eb1d85a417f4ed1ba7107f149ce3da1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_16,color_FFFFFF,t_70,g_se,x_16" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, computed } from 'vue'; +import { useRouter } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: '404', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const router = useRouter(); + const onGoHome = () => { + router.push('/'); + }; + // 设置主内容的高度 + const initTagViewHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `30px`; + } else { + if (isTagsview) return `114px`; + else return `80px`; + } + }); + return { + onGoHome, + initTagViewHeight, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.error { + height: 100%; + background-color: var(--el-color-white); + display: flex; + .error-flex { + margin: auto; + display: flex; + height: 350px; + width: 900px; + .left { + flex: 1; + height: 100%; + align-items: center; + display: flex; + .left-item { + .left-item-animation { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + } + .left-item-num { + color: var(--el-color-info); + font-size: 55px; + } + .left-item-title { + font-size: 20px; + color: var(--el-text-color-primary); + margin: 15px 0 5px 0; + animation-delay: 0.1s; + } + .left-item-msg { + color: var(--el-text-color-secondary); + font-size: 12px; + margin-bottom: 30px; + animation-delay: 0.2s; + } + .left-item-btn { + animation-delay: 0.2s; + } + } + } + .right { + flex: 1; + opacity: 0; + animation-name: error-img; + animation-duration: 2s; + animation-fill-mode: forwards; + img { + width: 100%; + height: 100%; + } + } + } +} +</style> diff --git a/src/views/home/index.vue b/src/views/home/index.vue new file mode 100644 index 0000000..45dd9ce --- /dev/null +++ b/src/views/home/index.vue @@ -0,0 +1,191 @@ +<template> + <div class="home-container"> + <el-row :gutter="15" class="home-card-one mb15"> + <el-col + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + v-for="(v, k) in homeOne" + :key="k" + :class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }" + > + <div class="home-card-item flex" > + <el-button @click="renderMenu(v.id)">{{v.name}}</el-button> + </div> + </el-col> + </el-row> + <el-row :gutter="15" class="home-card-two mb15"> + <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('6')">{{'应急管理系统'}}</el-button> + </div> + </div> + </el-col> + <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-media"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('7')">{{'目标责任管理系统'}}</el-button> + </div> + </div> + </el-col> + </el-row> + <el-row :gutter="15" class="home-card-three"> + <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8"> + <div class="home-card-item"> + <el-button @click="renderMenu('8')">{{'事故管理系统'}}</el-button> + </div> + </el-col> + <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-media"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('9')">{{'设备综合管控系统'}}</el-button> + </div> + </div> + </el-col> + </el-row> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, onMounted, ref, watch, nextTick, onActivated } from 'vue'; +import * as echarts from 'echarts'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import {Session} from "/@/utils/storage"; +import {useRoutesList} from "/@/stores/routesList"; +import pinia from "/@/stores"; + +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined], +}; + +interface stateType { + projectId:string, + homeOne: Array <type> +} +interface type { + id:number, + name: string +} +export default defineComponent({ + name: 'home', + setup() { + const storesRoutesList = useRoutesList(pinia); + const { routesList } = storeToRefs(storesRoutesList); + // const storesTagsViewRoutes = useTagsViewRoutes(); + // const storesThemeConfig = useThemeConfig(); + const state = reactive<stateType>({ + projectId:'', + homeOne:[{id:1,name:'基础数据权限管理系统'},{id:2,name:'系统1'},{id:3,name:'系统2'},{id:4,name:'系统3'},{id:5,name:'系统4'}], + }); + // 折线图 + const renderMenu = async (value: string) => { + state.projectId = value + Session.set('projectId',value) + await initBackEndControlRoutes(); + }; + return { + renderMenu, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + overflow: hidden; + .home-card-one, + .home-card-two, + .home-card-three { + .home-card-item { + width: 100%; + height: 130px; + border-radius: 4px; + transition: all ease 0.3s; + padding: 20px; + overflow: hidden; + background: var(--el-color-white); + color: var(--el-text-color-primary); + border: 1px solid var(--next-border-color-light); + &:hover { + box-shadow: 0 2px 12px var(--next-color-dark-hover); + transition: all ease 0.3s; + } + &-icon { + width: 70px; + height: 70px; + border-radius: 100%; + flex-shrink: 1; + i { + color: var(--el-text-color-placeholder); + } + } + &-title { + font-size: 15px; + font-weight: bold; + height: 30px; + } + } + } + .home-card-one { + @for $i from 0 through 3 { + .home-one-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + } + .home-card-two, + .home-card-three { + .home-card-item { + height: 400px; + width: 100%; + overflow: hidden; + .home-monitor { + height: 100%; + .flex-warp-item { + width: 25%; + height: 111px; + display: flex; + .flex-warp-item-box { + margin: auto; + text-align: center; + color: var(--el-text-color-primary); + display: flex; + border-radius: 5px; + background: var(--next-bg-color); + cursor: pointer; + transition: all 0.3s ease; + &:hover { + background: var(--el-color-primary-light-9); + transition: all 0.3s ease; + } + } + @for $i from 0 through $homeNavLengh { + .home-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + } + } + } + } +} +</style> diff --git a/src/views/login/component/account.vue b/src/views/login/component/account.vue new file mode 100644 index 0000000..29b40dd --- /dev/null +++ b/src/views/login/component/account.vue @@ -0,0 +1,196 @@ +<template> + <el-form size="large" class="login-content-form"> + <el-form-item class="login-animation1"> + <el-input type="text" :placeholder="$t('message.account.accountPlaceholder1')" v-model="ruleForm.username" clearable autocomplete="off"> + <template #prefix> + <el-icon class="el-input__icon"><ele-User /></el-icon> + </template> + </el-input> + </el-form-item> + <el-form-item class="login-animation2"> + <el-input + :type="isShowPassword ? 'text' : 'password'" + :placeholder="$t('message.account.accountPlaceholder2')" + v-model="ruleForm.password" + autocomplete="off" + > + <template #prefix> + <el-icon class="el-input__icon"><ele-Unlock /></el-icon> + </template> + <template #suffix> + <i + class="iconfont el-input__icon login-content-password" + :class="isShowPassword ? 'icon-yincangmima' : 'icon-xianshimima'" + @click="isShowPassword = !isShowPassword" + > + </i> + </template> + </el-input> + </el-form-item> + <el-form-item class="login-animation3"> + <el-col :span="15"> + <el-input + type="text" + maxlength="4" + :placeholder="$t('message.account.accountPlaceholder3')" + v-model="ruleForm.code" + clearable + autocomplete="off" + > + <template #prefix> + <el-icon class="el-input__icon"><ele-Position /></el-icon> + </template> + </el-input> + </el-col> + <el-col :span="1"></el-col> + <el-col :span="8"> + <el-button class="login-content-code">1234</el-button> + </el-col> + </el-form-item> + <el-form-item class="login-animation4"> + <el-button type="primary" class="login-content-submit" round @click="onSignIn" :loading="loading.signIn"> + <span>{{ $t('message.account.accountBtnText') }}</span> + </el-button> + </el-form-item> + </el-form> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, computed } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { ElMessage } from 'element-plus'; +import { useI18n } from 'vue-i18n'; +import Cookies from 'js-cookie'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { initFrontEndControlRoutes } from '/@/router/frontEnd'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { Session } from '/@/utils/storage'; +import { formatAxis } from '/@/utils/formatTime'; +import { NextLoading } from '/@/utils/loading'; +import { useLoginApi } from '/@/api/login'; +import {useUserInfo} from "/@/stores/userInfo"; + +export default defineComponent({ + name: 'loginAccount', + setup() { + const { t } = useI18n(); + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const router = useRouter(); + const state = reactive({ + isShowPassword: false, + ruleForm: { + username: 'admin', + password: '123456', + }, + loading: { + signIn: false, + }, + }); + // 时间获取 + const currentTime = computed(() => { + return formatAxis(new Date()); + }); + // 登录 + const onSignIn = async () => { + state.loading.signIn = true; + // 存储 token 到浏览器缓存 + let res = await useLoginApi().signIn(state.ruleForm) + if(res.data.code === '200'){ + Session.set('ifMenu',false) + Session.set('projectId','') + Session.set('token', res.data.data.accessToken); + Session.set('sign',res.data.data.id) + await initFrontEndControlRoutes(); + signInSuccess(); + }else{ + state.loading.signIn = false + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + // Session.set('token', Math.random().toString(36).substr(0)); + // // 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据) + // Cookies.set('userName', state.ruleForm.username); + // if (!themeConfig.value.isRequestRoutes) { + // // 前端控制路由,2、请注意执行顺序 + // await initFrontEndControlRoutes(); + // signInSuccess(); + // } else { + // // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 + // // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/" + // await initBackEndControlRoutes(); + // // 执行完 initBackEndControlRoutes,再执行 signInSuccess + // signInSuccess(); + // } + }; + // 登录成功后的跳转 + const signInSuccess = async () => { + // 初始化登录成功时间问候语 + let currentTimeInfo = currentTime.value; + // 登录成功,跳到转首页 + // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中 + if (route.query?.redirect) { + router.push('/'); + // router.push({ + // path: <string>route.query?.redirect, + // query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '', + // }); + } else { + router.push('/login'); + } + state.loading.signIn = true; + const signInText = t('message.signInText'); + ElMessage.success(`${currentTimeInfo},${signInText}`); + // 登录成功提示 + // 关闭 loading + // 添加 loading,防止第一次进入界面时出现短暂空白 + // NextLoading.start(); + }; + return { + onSignIn, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.login-content-form { + margin-top: 20px; + @for $i from 1 through 4 { + .login-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + .login-content-password { + display: inline-block; + width: 20px; + cursor: pointer; + &:hover { + color: #909399; + } + } + .login-content-code { + width: 100%; + padding: 0; + font-weight: bold; + letter-spacing: 5px; + } + .login-content-submit { + width: 100%; + letter-spacing: 2px; + font-weight: 300; + margin-top: 15px; + } +} +</style> diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..3ded06e --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,190 @@ +<template> + <div class="login-container"> + <div class="login-icon-group"> + <img :src="loginIconTwo" class="login-icon-group-icon" /> + </div> + <div class="login-content"> + <div class="login-content-main"> + <h4 class="login-content-title ml15"></h4> + <div v-if="!isScan"> + <el-tabs v-model="tabsActiveName"> + <el-tab-pane :label="$t('message.label.one1')" name="account"> + <Account /> + </el-tab-pane> + </el-tabs> + </div> + <Scan v-if="isScan" /> + <div class="login-content-main-sacn" @click="isScan = !isScan"> + <div class="login-content-main-sacn-delta"></div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import logoMini from '/@/assets/logo-mini.svg'; +import loginIconTwo from '/@/assets/login-icon-two.svg'; +import { NextLoading } from '/@/utils/loading'; +import Account from '/@/views/login/component/account.vue'; + +// 定义接口来定义对象的类型 +interface LoginState { + tabsActiveName: string; + isScan: boolean; +} + +export default defineComponent({ + name: 'loginIndex', + components: { Account, }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<LoginState>({ + tabsActiveName: 'account', + isScan: false, + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 页面加载时 + onMounted(() => { + NextLoading.done(); + }); + return { + logoMini, + loginIconTwo, + getThemeConfig, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.login-container { + width: 100%; + height: 100%; + position: relative; + background: var(--el-color-white); + .login-icon-group { + width: 100%; + height: 100%; + position: relative; + .login-icon-group-title { + position: absolute; + top: 50px; + left: 80px; + display: flex; + align-items: center; + img { + width: 30px; + height: 30px; + } + &-text { + padding-left: 15px; + color: var(--el-color-primary); + } + } + &::before { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 60%; + overflow: hidden; + height: 80%; + -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='1200' height='770' xmlns='http://www.w3.org/2000/svg' fill='none'%3E%3Cg%3E%3Cpath id='svg_1' d='M58.4 47.77C104.6 59.51 135.26 67.37 162.11 78.04C188.97 88.72 226.33 102.69 265.92 123.55C305.51 144.4 366.96 167.09 441.43 121.52C515.9 75.95 546.48 61.01 577.69 46.27C608.9 31.53 625.86 23.69 680.26 12.28C734.65 0.87 837.29 10.7 867.29 21.8C897.29 32.9 935.51 51.9 962.21 95.45C988.9 139.01 972.91 177.36 951.37 221.39C929.83 265.43 883.49 306 890.44 337.33C897.4 368.66 974.73 412.18 974.73 411.47C974.73 412.18 1066.36 457.62 1106.36 491.06C1146.36 524.5 1178.8 563.36 1184.03 579.63C1189.26 595.9 1200.4 622.49 1181.55 676.88C1162.71 731.26 1127.16 764.32 1115.31 778.64C1103.45 792.96 5.34 783.61 4.32 784.63C3.3 785.65 -172.34 2.38 1.13 35.04L58.4 47.77L58.4 47.77Z' fill='%23409eff'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + background: var(--el-color-primary-light-5); + transition: all 0.3s ease; + } + &::after { + content: ''; + width: 150px; + height: 300px; + position: absolute; + right: 0; + top: 0; + -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='150' height='300' xmlns='http://www.w3.org/2000/svg' fill='none'%3E%3Cg%3E%3Cpath id='svg_1' d='M-0.56 -0.28C41.94 36.17 67.73 18.94 93.33 33.96C118.93 48.98 107.58 73.56 101.94 89.76C96.29 105.96 50.09 217.83 47.87 231.18C45.64 244.52 46.02 255.2 64.4 270.05C82.79 284.91 121.99 292.31 111.98 289.81C101.97 287.32 153.96 301.48 151.83 299.9C149.69 298.32 149.98 -1.36 149.71 -1.18C149.98 -1.36 -43.06 -36.74 -0.56 -0.28L-0.56 -0.28Z' fill='%23409eff'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + background: var(--el-color-primary-light-5); + transition: all 0.3s ease; + } + &-icon { + width: 60%; + height: 70%; + position: absolute; + left: 0; + bottom: 0; + } + } + .login-content { + width: 500px; + padding: 20px; + position: absolute; + right: 200px; + top: 50%; + transform: translateY(-50%) translate3d(0, 0, 0); + background-color: var(--el-color-white); + border: 5px solid var(--el-color-primary-light-8); + border-radius: 5px; + overflow: hidden; + z-index: 1; + height: 460px; + .login-content-main { + margin: 0 auto; + width: 80%; + .login-content-title { + color: var(--el-text-color-primary); + font-weight: 500; + font-size: 22px; + text-align: center; + letter-spacing: 4px; + margin: 15px 0 30px; + white-space: nowrap; + z-index: 5; + position: relative; + transition: all 0.3s ease; + } + } + .login-content-main-sacn { + position: absolute; + top: 0; + right: 0; + width: 50px; + height: 50px; + overflow: hidden; + cursor: pointer; + transition: all ease 0.3s; + color: var(--el-text-color-primary); + &-delta { + position: absolute; + width: 35px; + height: 70px; + z-index: 2; + top: 2px; + right: 21px; + background: var(--el-color-white); + transform: rotate(-45deg); + } + &:hover { + opacity: 1; + transition: all ease 0.3s; + color: var(--el-color-primary) !important; + } + i { + width: 47px; + height: 50px; + display: inline-block; + font-size: 48px; + position: absolute; + right: 2px; + top: -1px; + } + } + } +} +</style> diff --git a/src/views/system/department/component/deptDialog.vue b/src/views/system/department/component/deptDialog.vue new file mode 100644 index 0000000..0477317 --- /dev/null +++ b/src/views/system/department/component/deptDialog.vue @@ -0,0 +1,161 @@ +<template> + <div class="system-add-dept-container"> + <el-dialog :title="title" v-model="isShowDialog" width="600px"> + <el-form :model="departmentForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上级部门"> + <el-cascader + :options="deptData" + :props="{ checkStrictly: true, value: 'id', label: 'name' }" + placeholder="请选择部门" + clearable + class="w100" + v-model="departmentForm.struct" + > + </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门名称"> + <el-input v-model="departmentForm.name" placeholder="请输入部门名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门描述"> + <el-input v-model="departmentForm.info" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">新 增</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { ElMessage } from 'element-plus'; +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { departmentApi } from "/@/api/department"; + +// 定义接口来定义对象的类型 +interface TableDataRow { + struct: Array<string>; + name:string, + info:string, + parentId:string, + id:number, +} +interface DeptSate { + title:string; + isShowDialog: boolean; + departmentForm: { + struct: Array<string>; + name:string, + info:string, + parentId:string + }; + deptData: Array<TableDataRow>; +} + +export default defineComponent({ + name: 'systemAddDept', + setup(prop,context) { + const state = reactive<DeptSate>({ + title:'', + isShowDialog: false, + departmentForm: { + name:'', + parentId:'', + info:'', + struct:[] + }, + deptData: [], // 部门数据 + }); + // 打开弹窗 + const openDialog = (type:string, value: any,departmentList: []) => { + state.isShowDialog = true; + state.deptData = JSON.parse(JSON.stringify(departmentList)) + if(type === '新增'){ + state.title = '新增部门' + state.departmentForm = { + name:'', + parentId:'', + info:'', + struct:[] + } + }else{ + state.title = '编辑部门' + } + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = async () => { + if(state.departmentForm.struct && state.departmentForm.struct !== []){ + let departmentId = JSON.parse(JSON.stringify(state.departmentForm.struct)) + state.departmentForm.parentId = departmentId[departmentId.length - 1] + } + if(state.title === '新增部门'){ + let res = await departmentApi().addDepartment(state.departmentForm) + if(res.data.code === '200'){ + ElMessage({ + type:'success', + message:'菜单新增成功', + duration:2000 + }) + closeDialog(); + context.emit('getMenuList') + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await departmentApi().modDepartment(state.departmentForm) + if(res.data.code === '200'){ + ElMessage({ + type:'success', + message:'菜单修改成功', + duration:2000 + }) + closeDialog(); + context.emit('getMenuList') + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } + }; + // 初始化部门数据 + const initTableData = () => { + + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/department/component/editDept.vue b/src/views/system/department/component/editDept.vue new file mode 100644 index 0000000..7b16f44 --- /dev/null +++ b/src/views/system/department/component/editDept.vue @@ -0,0 +1,179 @@ +<template> + <div class="system-edit-dept-container"> + <el-dialog title="修改部门" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上级部门"> + <el-cascader + :options="deptData" + :props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }" + placeholder="请选择部门" + clearable + class="w100" + v-model="ruleForm.deptLevel" + > + <template #default="{ node, data }"> + <span>{{ data.deptName }}</span> + <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> + </template> + </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="部门名称"> + <el-input v-model="ruleForm.deptName" placeholder="请输入部门名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责人"> + <el-input v-model="ruleForm.person" placeholder="请输入负责人" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="手机号"> + <el-input v-model="ruleForm.phone" placeholder="请输入手机号" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="邮箱"> + <el-input v-model="ruleForm.email" placeholder="请输入" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="排序"> + <el-input-number v-model="ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="部门状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">修 改</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + deptName: string; + createTime: string; + status: boolean; + sort: number; + describe: string; + id: number; + children?: TableDataRow[]; +} +interface RuleFormState { + deptLevel: Array<string>; + deptName: string; + person: string; + phone: string | number; + email: string; + sort: number; + status: boolean; + describe: string; +} +interface DeptSate { + isShowDialog: boolean; + ruleForm: RuleFormState; + deptData: Array<TableDataRow>; +} + +export default defineComponent({ + name: 'systemEditDept', + setup() { + const state = reactive<DeptSate>({ + isShowDialog: false, + ruleForm: { + deptLevel: [], // 上级部门 + deptName: '', // 部门名称 + person: '', // 负责人 + phone: '', // 手机号 + email: '', // 邮箱 + sort: 0, // 排序 + status: true, // 部门状态 + describe: '', // 部门描述 + }, + deptData: [], // 部门数据 + }); + // 打开弹窗 + const openDialog = (row: RuleFormState) => { + row.deptLevel = ['vueNextAdmin']; + row.person = 'lyt'; + row.phone = '12345678910'; + row.email = 'vueNextAdmin@123.com'; + state.ruleForm = row; + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 初始化部门数据 + const initTableData = () => { + state.deptData.push({ + deptName: 'vueNextAdmin', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '顶级部门', + id: Math.random(), + children: [ + { + deptName: 'IT外包服务', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '总部', + id: Math.random(), + }, + { + deptName: '资本控股', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '分部', + id: Math.random(), + }, + ], + }); + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/department/index.vue b/src/views/system/department/index.vue new file mode 100644 index 0000000..4f33400 --- /dev/null +++ b/src/views/system/department/index.vue @@ -0,0 +1,121 @@ +<template> + <div class="system-dept-container"> + <el-card shadow="hover"> + <div class="system-dept-search mb15"> + <el-input size="default" placeholder="请输入部门名称" style="max-width: 180px"> </el-input> + <el-button size="default" type="primary" class="ml10"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDeptDialog('新增','')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增部门 + </el-button> + </div> + <el-table + :data="tableData.data" + style="width: 100%" + row-key="id" + default-expand-all + :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" + > + <el-table-column prop="name" label="部门名称" show-overflow-tooltip> </el-table-column> + <el-table-column prop="status" label="部门状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status">启用</el-tag> + <el-tag type="info" v-else>禁用</el-tag> + </template> + </el-table-column> + <el-table-column prop="info" label="部门描述" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" show-overflow-tooltip width="140"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenDeptDialog('新增','')">新增</el-button> + <el-button size="small" text type="primary" @click="onOpenDeptDialog('修改',scope.row)">修改</el-button> + <el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + <deptDialog ref="deptDialog" /> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import deptDialog from '/@/views/system/department/component/deptDialog.vue'; +import {departmentApi} from "/@/api/department"; + +// 定义接口来定义对象的类型 +interface TableDataRow { + name: string; + status: boolean; + parentId: number; + info: string; + id: number; + children?: TableDataRow[]; +} +interface TableDataState { + tableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + }; +} + +export default defineComponent({ + name: 'systemDept', + components: { deptDialog }, + setup() { + const deptDialog = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + }, + }); + // 初始化表格数据 + const initTableData = async () => { + let res = await departmentApi().getDepartmentList() + if(res.data.code === '200'){ + state.tableData.data = res.data.data + state.tableData.total = state.tableData.data.length; + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }; + // 打开新增菜单弹窗 + const onOpenDeptDialog = (type: string,value: any) => { + deptDialog.value.openDialog(type,value,state.tableData.data); + }; + // 删除当前行 + const onTabelRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除部门:${row.id}, 是否继续?`, '提示', { + confirmButtonText: '删除', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + ElMessage.success('删除成功'); + }).catch(() => {}); + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + deptDialog, + onOpenDeptDialog, + onTabelRowDel, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/dic/component/addDic.vue b/src/views/system/dic/component/addDic.vue new file mode 100644 index 0000000..c964dd9 --- /dev/null +++ b/src/views/system/dic/component/addDic.vue @@ -0,0 +1,129 @@ +<template> + <div class="system-add-dic-container"> + <el-dialog title="新增字典" v-model="isShowDialog" width="769px"> + <el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字典名称"> + <el-input v-model="ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字段名"> + <el-input v-model="ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-row :gutter="35" v-for="(v, k) in ruleForm.list" :key="k"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item :prop="`list[${k}].label`"> + <template #label> + <el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0"> + <el-icon> + <ele-Plus /> + </el-icon> + </el-button> + <el-button type="danger" circle size="small" @click="onDelRow(k)" v-else> + <el-icon> + <ele-Delete /> + </el-icon> + </el-button> + <span class="ml10">字段</span> + </template> + <el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="属性" :prop="`list[${k}].value`"> + <el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">新 增</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'systemAddDic', + setup() { + const state = reactive({ + isShowDialog: false, + ruleForm: { + dicName: '', // 字典名称 + fieldName: '', // 字段名 + status: true, // 字典状态 + list: [ + // 子集字段 + 属性值 + { + id: Math.random(), + label: '', + value: '', + }, + ], + describe: '', // 字典描述 + fieldNameList: [], // 字段名: [{子集字段 + 属性值}] + }, + }); + // 打开弹窗 + const openDialog = () => { + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 新增行 + const onAddRow = () => { + state.ruleForm.list.push({ + id: Math.random(), + label: '', + value: '', + }); + }; + // 删除行 + const onDelRow = (k: number) => { + state.ruleForm.list.splice(k, 1); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + onAddRow, + onDelRow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/dic/component/editDic.vue b/src/views/system/dic/component/editDic.vue new file mode 100644 index 0000000..66b0365 --- /dev/null +++ b/src/views/system/dic/component/editDic.vue @@ -0,0 +1,162 @@ +<template> + <div class="system-edit-dic-container"> + <el-dialog title="修改字典" v-model="isShowDialog" width="769px"> + <el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字典名称"> + <el-input v-model="ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字段名"> + <el-input v-model="ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-row :gutter="35" v-for="(v, k) in ruleForm.list" :key="k"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item :prop="`list[${k}].label`"> + <template #label> + <el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0"> + <el-icon> + <ele-Plus /> + </el-icon> + </el-button> + <el-button type="danger" circle size="small" @click="onDelRow(k)" v-else> + <el-icon> + <ele-Delete /> + </el-icon> + </el-button> + <span class="ml10">字段</span> + </template> + <el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="属性" :prop="`list[${k}].value`"> + <el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">修 改</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface RuleFormList { + id: number; + label: string; + value: string; +} +interface RuleFormState { + dicName: string; + fieldName: string; + status: boolean; + list: RuleFormList[]; + describe: string; + fieldNameList: Array<any>; +} +interface DicState { + isShowDialog: boolean; + ruleForm: RuleFormState; +} + +export default defineComponent({ + name: 'systemEditDic', + setup() { + const state = reactive<DicState>({ + isShowDialog: false, + ruleForm: { + dicName: '', // 字典名称 + fieldName: '', // 字段名 + status: true, // 字典状态 + list: [ + // 子集字段 + 属性值 + { + id: Math.random(), + label: '', + value: '', + }, + ], + describe: '', // 字典描述 + fieldNameList: [], // 字段名: [{子集字段 + 属性值}] + }, + }); + // 打开弹窗 + const openDialog = (row: RuleFormState) => { + if (row.fieldName === 'SYS_UERINFO') { + row.list = [ + { id: Math.random(), label: 'sex', value: '1' }, + { id: Math.random(), label: 'sex', value: '0' }, + ]; + } else { + row.list = [ + { id: Math.random(), label: 'role', value: 'admin' }, + { id: Math.random(), label: 'role', value: 'common' }, + { id: Math.random(), label: 'roleName', value: '超级管理员' }, + { id: Math.random(), label: 'roleName', value: '普通用户' }, + ]; + } + state.ruleForm = row; + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 新增行 + const onAddRow = () => { + state.ruleForm.list.push({ + id: Math.random(), + label: '', + value: '', + }); + }; + // 删除行 + const onDelRow = (k: number) => { + state.ruleForm.list.splice(k, 1); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + onAddRow, + onDelRow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/dic/index.vue b/src/views/system/dic/index.vue new file mode 100644 index 0000000..034140c --- /dev/null +++ b/src/views/system/dic/index.vue @@ -0,0 +1,159 @@ +<template> + <div class="system-dic-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" placeholder="请输入字典名称" style="max-width: 180px"> </el-input> + <el-button size="default" type="primary" class="ml10"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenAddDic"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增字典 + </el-button> + </div> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="50" /> + <el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column> + <el-table-column prop="status" label="字典状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status">启用</el-tag> + <el-tag type="info" v-else>禁用</el-tag> + </template> + </el-table-column> + <el-table-column prop="describe" label="字典描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="mt15" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:current-page="tableData.param.pageNum" + background + v-model:page-size="tableData.param.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="tableData.total" + > + </el-pagination> + </el-card> + <AddDic ref="addDicRef" /> + <EditDic ref="editDicRef" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import AddDic from '/@/views/system/dic/component/addDic.vue'; +import EditDic from '/@/views/system/dic/component/editDic.vue'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + dicName: string; + fieldName: string; + describe: string; + status: boolean; + createTime: string; +} +interface TableDataState { + tableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + }; + }; +} + +export default defineComponent({ + name: 'systemDic', + components: { AddDic, EditDic }, + setup() { + const addDicRef = ref(); + const editDicRef = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + param: { + pageNum: 1, + pageSize: 10, + }, + }, + }); + // 初始化表格数据 + const initTableData = () => { + const data: Array<TableDataRow> = []; + for (let i = 0; i < 2; i++) { + data.push({ + dicName: i === 0 ? '角色标识' : '用户性别', + fieldName: i === 0 ? 'SYS_ROLE' : 'SYS_UERINFO', + describe: i === 0 ? '这是角色字典' : '这是用户性别字典', + status: true, + createTime: new Date().toLocaleString(), + }); + } + state.tableData.data = data; + state.tableData.total = state.tableData.data.length; + }; + // 打开新增字典弹窗 + const onOpenAddDic = () => { + addDicRef.value.openDialog(); + }; + // 打开修改字典弹窗 + const onOpenEditDic = (row: TableDataRow) => { + editDicRef.value.openDialog(row); + }; + // 删除字典 + const onRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除字典名称:“${row.dicName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + ElMessage.success('删除成功'); + }) + .catch(() => {}); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.param.pageSize = val; + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.param.pageNum = val; + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + addDicRef, + editDicRef, + onOpenAddDic, + onOpenEditDic, + onRowDel, + onHandleSizeChange, + onHandleCurrentChange, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/menu/component/menuDialog.vue b/src/views/system/menu/component/menuDialog.vue new file mode 100644 index 0000000..8b2f441 --- /dev/null +++ b/src/views/system/menu/component/menuDialog.vue @@ -0,0 +1,271 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="80px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上级菜单"> + <el-cascader + :options="menuData" + :props="{ checkStrictly: true, value: 'id', label: 'title' }" + placeholder="请选择上级菜单" + clearable + class="w100" + v-model="ruleForm.menuSuperior" + > + </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单名称"> + <el-input v-model="ruleForm.meta.title" placeholder="格式:message.router.xxx" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="路由名称"> + <el-input v-model="ruleForm.name" placeholder="路由中的 name 值" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="路由路径"> + <el-input v-model="ruleForm.path" placeholder="路由中的 path 值" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="重定向"> + <el-input v-model="ruleForm.redirect" placeholder="请输入路由重定向" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单图标"> + <IconSelector placeholder="请输入菜单图标" v-model="ruleForm.meta.icon" type="all" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="组件路径"> + <el-input v-model="ruleForm.component" placeholder="组件路径" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="权限标识"> + <el-select v-model="ruleForm.meta.roles" multiple placeholder="取角色管理" clearable class="w100"> + <el-option label="admin" value="admin"></el-option> + <el-option label="common" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="项目名"> + <el-select v-model="ruleForm.projectId" controls-position="right" placeholder="请输入排序" class="w100"> + <el-option + v-for="item in projectList" + :key="item.key" + :value="item.id" + :label="item.name" + > + </el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单排序"> + <el-input-number v-model="ruleForm.priority" controls-position="right" placeholder="请输入排序" class="w100"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="是否隐藏"> + <el-radio-group v-model="ruleForm.meta.isHide"> + <el-radio :label="true">隐藏</el-radio> + <el-radio :label="false">不隐藏</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">{{ buttonName }}</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { i18n } from '/@/i18n/index'; +import IconSelector from '/@/components/iconSelector/index.vue'; +import { useMenuApi } from '/@/api/menu/index' +import { ElMessageBox, ElMessage } from 'element-plus'; +import {Session} from "/@/utils/storage"; +// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd"; + +export default defineComponent({ + name: 'systemAddMenu', + components: { IconSelector }, + setup(props,context) { + const stores = useRoutesList(); + const { routesList } = storeToRefs(stores); + const state = reactive({ + isShowDialog: false, + title:'', + buttonName:'', + // 参数请参考 `/src/router/route.ts` 中的 `dynamicRoutes` 路由菜单格式 + ruleForm: { + projectId:'', + parentId:0, + menuSuperior: [], // 上级菜单 + menuType: 'menu', // 菜单类型 + name: '', // 路由名称 + component: '', // 组件路径 + priority: 0, // 菜单排序 + path: '', // 路由路径 + redirect: '', // 路由重定向,有子集 children 时 + meta: { + title: '', // 菜单名称 + icon: '', // 菜单图标 + isHide: false, // 是否隐藏 + isKeepAlive: true, // 是否缓存 + isAffix: false, // 是否固定 + isLink: '', // 外链/内嵌时链接地址(http:xxx.com),开启外链条件,`1、isLink: 链接地址不为空` + isIframe: false, // 是否内嵌,开启条件,`1、isIframe:true 2、isLink:链接地址不为空` + roles: '', // 权限标识,取角色管理 + }, + btnPower: '', // 菜单类型为按钮时,权限标识 + }, + menuData: [], // 上级菜单数据 + projectList:[ + {id:'1',name:'基础数据权限管理系统',key:0}, + {id:'2',name:'系统1',key:1}, + {id:'3',name:'系统2',key:2}, + {id:'4',name:'系统3',key:3}, + {id:'5',name:'系统4',key:4}, + {id:'6',name:'应急管理系统',key:5}, + {id:'7',name:'目标责任管理系统',key:6}, + {id:'8',name:'事故管理系统',key:7}, + {id:'9',name:'设备综合管控系统',key:8}, + ], + }); + // 获取 vuex 中的路由 + const getMenuList = (routes: any) => { + const arr: any = []; + routes.map((val: any) => { + val['title'] = val.meta.title; + val['id'] = val.id + arr.push(val); + if (val.children) getMenuList(val.children); + }); + return arr; + }; + // 打开弹窗 + const openDialog = (type:string,value:any) => { + state.isShowDialog = true; + if(type === '新增'){ + state.buttonName = '新增' + state.title = '新增菜单' + state.ruleForm = { + projectId:'', + parentId:0, + menuSuperior: [], + menuType: 'menu', + name: '', + component: '', + priority: 0, + path: '', + redirect: '', + meta: { + title: '', + icon: '', + isHide: false, + isKeepAlive: true, + isAffix: false, + isLink: '', + isIframe: false, + roles: '', + }, + btnPower: '', + } + }else{ + state.buttonName = '修改' + state.title = '修改菜单' + state.ruleForm = JSON.parse(JSON.stringify(value)) + } + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 是否内嵌下拉改变 + // const onSelectIframeChange = () => { + // if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true; + // else state.ruleForm.isLink = false; + // }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = async () => { + if(state.ruleForm.menuSuperior && state.ruleForm.menuSuperior !== []){ + let menuId = JSON.parse(JSON.stringify(state.ruleForm.menuSuperior)) + state.ruleForm.parentId = menuId[menuId.length - 1] + } + if(state.title === '新增菜单'){ + let res = await useMenuApi().addMenu(state.ruleForm) + if(res.data.code === '200'){ + ElMessage({ + type:'success', + message:'菜单新增成功', + duration:2000 + }) + closeDialog(); + context.emit('getMenuList') + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await useMenuApi().modMenu(state.ruleForm) + if(res.data.code === '200'){ + ElMessage({ + type:'success', + message:'菜单修改成功', + duration:2000 + }) + closeDialog(); + context.emit('getMenuList') + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } + + // closeDialog(); // 关闭弹窗 + // setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试 + }; + + const show = () => { + console.log(JSON.parse(JSON.stringify(state.ruleForm.menuSuperior))); + } + // 页面加载时 + onMounted(async () => { + let res = await useMenuApi().getMenuAdmin(Session.get('projectId')) + state.menuData = JSON.parse(JSON.stringify(getMenuList(res.data.data))) + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..2197f6a --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,128 @@ +<template> + <div class="system-menu-container"> + <el-card shadow="hover"> + <div class="system-menu-search mb15"> + <el-input size="default" placeholder="请输入菜单名称" style="max-width: 180px"> </el-input> + <el-button size="default" type="primary" class="ml10"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenMenuDialog('新增')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增菜单 + </el-button> + </div> + <el-table :data="menuTableData" style="width: 100%" row-key="path" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"> + <el-table-column label="菜单名称" show-overflow-tooltip> + <template #default="scope"> + <SvgIcon :name="scope.row.meta.icon" /> + <span class="ml10">{{ scope.row.meta.title }}</span> + </template> + </el-table-column> + <el-table-column prop="path" label="路由路径" show-overflow-tooltip></el-table-column> + <el-table-column label="组件路径" show-overflow-tooltip> + <template #default="scope"> + <span>{{ scope.row.component }}</span> + </template> + </el-table-column> + <el-table-column label="权限标识" show-overflow-tooltip> + <template #default="scope"> + <span>{{ scope.row.meta.roles }}</span> + </template> + </el-table-column> + <el-table-column label="排序" show-overflow-tooltip width="80"> + <template #default="scope"> + {{ scope.$index }} + </template> + </el-table-column> + <el-table-column label="类型" show-overflow-tooltip width="80"> + <template #default="scope"> + <el-tag type="success" size="small">{{ scope.row.xx }}菜单</el-tag> + </template> + </el-table-column> + <el-table-column label="操作" show-overflow-tooltip width="140"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenMenuDialog('新增')">新增</el-button> + <el-button size="small" text type="primary" @click="onOpenMenuDialog('修改',scope.row)">修改</el-button> + <el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + <menuDialog ref="menuDialog" @getMenuList="getMenuList"/> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, computed, onMounted, defineComponent } from 'vue'; +import { RouteRecordRaw } from 'vue-router'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import menuDialog from '/@/views/system/menu/component/menuDialog.vue'; +import {useMenuApi} from "/@/api/menu"; +import {Session} from "/@/utils/storage"; +import pinia from "/@/stores"; +import {dynamicRoutes} from "/@/router/route"; + +export default defineComponent({ + name: 'systemMenu', + components: { menuDialog }, + setup() { + const stores = useRoutesList(); + const { routesList } = storeToRefs(stores); + const menuDialog = ref(); + const state = reactive({ + menuData:[], + }); + // 获取 vuex 中的路由 + const menuTableData = computed(() => { + return routesList.value; + }); + // 打开新增菜单弹窗 + const onOpenMenuDialog = (type: string,value: any) => { + debugger + menuDialog.value.openDialog(type,value); + }; + // 打开编辑菜单弹窗 + // 删除当前行 + const onTabelRowDel = (row: RouteRecordRaw) => { + ElMessageBox.confirm(`此操作将永久删除路由:${row.path}, 是否继续?`, '提示', { + confirmButtonText: '删除', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + ElMessage.success('删除成功'); + }).catch(() => {}); + }; + const getMenuList = async () => { + let res = await useMenuApi().getMenuAdmin(Session.get('projectId')) + if(res.data.code === '200'){ + // state.menuData = res.data.data + const storesRoutesList = useRoutesList(pinia); + storesRoutesList.setRoutesList(res.data.data); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }; + onMounted( () => { + getMenuList() + }); + return { + getMenuList, + menuDialog, + onOpenMenuDialog, + menuTableData, + onTabelRowDel, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/role/component/addRole.vue b/src/views/system/role/component/addRole.vue new file mode 100644 index 0000000..adb0e83 --- /dev/null +++ b/src/views/system/role/component/addRole.vue @@ -0,0 +1,240 @@ +<template> + <div class="system-add-role-container"> + <el-dialog title="新增角色" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色名称"> + <el-input v-model="ruleForm.roleName" placeholder="请输入角色名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色标识"> + <template #label> + <el-tooltip effect="dark" content="用于 `router/route.ts` meta.roles" placement="top-start"> + <span>角色标识</span> + </el-tooltip> + </template> + <el-input v-model="ruleForm.roleSign" placeholder="请输入角色标识" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="排序"> + <el-input-number v-model="ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="角色描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="菜单权限"> + <el-tree :data="menuData" :props="menuProps" show-checkbox class="menu-data-tree" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">新 增</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface MenuDataTree { + id: number; + label: string; + children?: MenuDataTree[]; +} +interface RoleState { + isShowDialog: boolean; + ruleForm: { + roleName: string; + roleSign: string; + sort: number; + status: boolean; + describe: string; + }; + menuData: Array<MenuDataTree>; + menuProps: { + children: string; + label: string; + }; +} + +export default defineComponent({ + name: 'systemAddRole', + setup() { + const state = reactive<RoleState>({ + isShowDialog: false, + ruleForm: { + roleName: '', // 角色名称 + roleSign: '', // 角色标识 + sort: 0, // 排序 + status: true, // 角色状态 + describe: '', // 角色描述 + }, + menuData: [], + menuProps: { + children: 'children', + label: 'label', + }, + }); + // 打开弹窗 + const openDialog = () => { + state.isShowDialog = true; + getMenuData(); + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 获取菜单结构数据 + const getMenuData = () => { + state.menuData = [ + { + id: 1, + label: '系统管理', + children: [ + { + id: 11, + label: '菜单管理', + children: [ + { + id: 111, + label: '菜单新增', + }, + { + id: 112, + label: '菜单修改', + }, + { + id: 113, + label: '菜单删除', + }, + { + id: 114, + label: '菜单查询', + }, + ], + }, + { + id: 12, + label: '角色管理', + children: [ + { + id: 121, + label: '角色新增', + }, + { + id: 122, + label: '角色修改', + }, + { + id: 123, + label: '角色删除', + }, + { + id: 124, + label: '角色查询', + }, + ], + }, + { + id: 13, + label: '用户管理', + children: [ + { + id: 131, + label: '用户新增', + }, + { + id: 132, + label: '用户修改', + }, + { + id: 133, + label: '用户删除', + }, + { + id: 134, + label: '用户查询', + }, + ], + }, + ], + }, + { + id: 2, + label: '权限管理', + children: [ + { + id: 21, + label: '前端控制', + children: [ + { + id: 211, + label: '页面权限', + }, + { + id: 212, + label: '页面权限', + }, + ], + }, + { + id: 22, + label: '后端控制', + children: [ + { + id: 221, + label: '页面权限', + }, + ], + }, + ], + }, + ]; + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.system-add-role-container { + .menu-data-tree { + width: 100%; + border: 1px solid var(--el-border-color); + border-radius: var(--el-input-border-radius, var(--el-border-radius-base)); + padding: 5px; + } +} +</style> diff --git a/src/views/system/role/component/editRole.vue b/src/views/system/role/component/editRole.vue new file mode 100644 index 0000000..fc6fe29 --- /dev/null +++ b/src/views/system/role/component/editRole.vue @@ -0,0 +1,242 @@ +<template> + <div class="system-edit-role-container"> + <el-dialog title="修改角色" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色名称"> + <el-input v-model="ruleForm.roleName" placeholder="请输入角色名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色标识"> + <template #label> + <el-tooltip effect="dark" content="用于 `router/route.ts` meta.roles" placement="top-start"> + <span>角色标识</span> + </el-tooltip> + </template> + <el-input v-model="ruleForm.roleSign" placeholder="请输入角色标识" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="排序"> + <el-input-number v-model="ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="角色描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="菜单权限"> + <el-tree :data="menuData" :props="menuProps" :default-checked-keys="[112, 113]" node-key="id" show-checkbox class="menu-data-tree" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">修 改</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface MenuDataTree { + id: number; + label: string; + children?: MenuDataTree[]; +} +interface DialogRow { + roleName: string; + roleSign: string; + sort: number; + status: boolean; + describe: string; +} +interface RoleState { + isShowDialog: boolean; + ruleForm: DialogRow; + menuData: Array<MenuDataTree>; + menuProps: { + children: string; + label: string; + }; +} + +export default defineComponent({ + name: 'systemEditRole', + setup() { + const state = reactive<RoleState>({ + isShowDialog: false, + ruleForm: { + roleName: '', // 角色名称 + roleSign: '', // 角色标识 + sort: 0, // 排序 + status: true, // 角色状态 + describe: '', // 角色描述 + }, + menuData: [], + menuProps: { + children: 'children', + label: 'label', + }, + }); + // 打开弹窗 + const openDialog = (row: DialogRow) => { + state.ruleForm = row; + state.isShowDialog = true; + getMenuData(); + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 获取菜单结构数据 + const getMenuData = () => { + state.menuData = [ + { + id: 1, + label: '系统管理', + children: [ + { + id: 11, + label: '菜单管理', + children: [ + { + id: 111, + label: '菜单新增', + }, + { + id: 112, + label: '菜单修改', + }, + { + id: 113, + label: '菜单删除', + }, + { + id: 114, + label: '菜单查询', + }, + ], + }, + { + id: 12, + label: '角色管理', + children: [ + { + id: 121, + label: '角色新增', + }, + { + id: 122, + label: '角色修改', + }, + { + id: 123, + label: '角色删除', + }, + { + id: 124, + label: '角色查询', + }, + ], + }, + { + id: 13, + label: '用户管理', + children: [ + { + id: 131, + label: '用户新增', + }, + { + id: 132, + label: '用户修改', + }, + { + id: 133, + label: '用户删除', + }, + { + id: 134, + label: '用户查询', + }, + ], + }, + ], + }, + { + id: 2, + label: '权限管理', + children: [ + { + id: 21, + label: '前端控制', + children: [ + { + id: 211, + label: '页面权限', + }, + { + id: 212, + label: '页面权限', + }, + ], + }, + { + id: 22, + label: '后端控制', + children: [ + { + id: 221, + label: '页面权限', + }, + ], + }, + ], + }, + ]; + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.system-edit-role-container { + .menu-data-tree { + width: 100%; + border: 1px solid var(--el-border-color); + border-radius: var(--el-input-border-radius, var(--el-border-radius-base)); + padding: 5px; + } +} +</style> diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..7835197 --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,167 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" placeholder="请输入角色名称" style="max-width: 180px"> </el-input> + <el-button size="default" type="primary" class="ml10" @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenAddRole"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增角色 + </el-button> + </div> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="name" label="角色名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="code" label="角色标识" show-overflow-tooltip></el-table-column> + <el-table-column prop="sort" label="排序" show-overflow-tooltip></el-table-column> + <el-table-column prop="status" label="角色状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status">启用</el-tag> + <el-tag type="info" v-else>禁用</el-tag> + </template> + </el-table-column> + <el-table-column prop="info" label="角色描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onOpenEditRole(scope.row)" + >修改</el-button + > + <el-button :disabled="scope.row.roleName === '超级管理员'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="mt15" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:current-page="tableData.param.pageNum" + background + v-model:page-size="tableData.param.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="tableData.total" + > + </el-pagination> + </el-card> + <AddRole ref="addRoleRef" /> + <EditRole ref="editRoleRef" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import AddRole from '/@/views/system/role/component/addRole.vue'; +import EditRole from '/@/views/system/role/component/editRole.vue'; +import {useRoleApi} from "/@/api/role"; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + tableData: { + data: Array<TableData>; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + }; + }; +} + +export default defineComponent({ + name: 'systemRole', + components: { AddRole, EditRole }, + setup() { + const addRoleRef = ref(); + const editRoleRef = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + param: { + pageNum: 1, + pageSize: 10, + }, + }, + }); + // 初始化表格数据 + const initTableData = async () => { + let res = await useRoleApi().getRoleList() + if(res.data.code === '200'){ + state.tableData.data = res.data.data; + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + + }; + // 打开新增角色弹窗 + const onOpenAddRole = () => { + addRoleRef.value.openDialog(); + }; + // 打开修改角色弹窗 + const onOpenEditRole = (row: Object) => { + editRoleRef.value.openDialog(row); + }; + // 删除角色 + const onRowDel = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除角色名称:“${row.roleName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + ElMessage.success('删除成功'); + }) + .catch(() => {}); + }; + const handleSearch = () => { + debugger + initTableData() + } + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.param.pageSize = val; + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.param.pageNum = val; + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + addRoleRef, + editRoleRef, + onOpenAddRole, + onOpenEditRole, + onRowDel, + onHandleSizeChange, + onHandleCurrentChange, + handleSearch, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/user/component/addUser.vue b/src/views/system/user/component/addUser.vue new file mode 100644 index 0000000..4a78153 --- /dev/null +++ b/src/views/system/user/component/addUser.vue @@ -0,0 +1,200 @@ +<template> + <div class="system-add-user-container"> + <el-dialog title="新增用户" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户名称"> + <el-input v-model="ruleForm.userName" placeholder="请输入账户名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="用户昵称"> + <el-input v-model="ruleForm.userNickname" placeholder="请输入用户昵称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="关联角色"> + <el-select v-model="ruleForm.roleSign" placeholder="请选择" clearable class="w100"> + <el-option label="超级管理员" value="admin"></el-option> + <el-option label="普通用户" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="部门"> + <el-cascader + :options="deptData" + :props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }" + placeholder="请选择部门" + clearable + class="w100" + v-model="ruleForm.department" + > + <template #default="{ node, data }"> + <span>{{ data.deptName }}</span> + <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> + </template> + </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="手机号"> + <el-input v-model="ruleForm.phone" placeholder="请输入手机号" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="邮箱"> + <el-input v-model="ruleForm.email" placeholder="请输入" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="性别"> + <el-select v-model="ruleForm.sex" placeholder="请选择" clearable class="w100"> + <el-option label="男" value="男"></el-option> + <el-option label="女" value="女"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户密码"> + <el-input v-model="ruleForm.password" placeholder="请输入" type="password" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户过期"> + <el-date-picker v-model="ruleForm.overdueTime" type="date" placeholder="请选择" class="w100"> </el-date-picker> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="用户状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="用户描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入用户描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">新 增</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface DeptData { + deptName: string; + createTime: string; + status: boolean; + sort: number | string; + describe: string; + id: number; + children?: DeptData[]; +} +interface UserState { + isShowDialog: boolean; + ruleForm: { + userName: string; + userNickname: string; + roleSign: string; + department: any; + phone: string; + email: string; + sex: string; + password: string; + overdueTime: string; + status: boolean; + describe: string; + }; + deptData: Array<DeptData>; +} + +export default defineComponent({ + name: 'systemAddUser', + setup() { + const state = reactive<UserState>({ + isShowDialog: false, + ruleForm: { + userName: '', // 账户名称 + userNickname: '', // 用户昵称 + roleSign: '', // 关联角色 + department: [], // 部门 + phone: '', // 手机号 + email: '', // 邮箱 + sex: '', // 性别 + password: '', // 账户密码 + overdueTime: '', // 账户过期 + status: true, // 用户状态 + describe: '', // 用户描述 + }, + deptData: [], // 部门数据 + }); + // 打开弹窗 + const openDialog = () => { + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 初始化部门数据 + const initTableData = () => { + state.deptData.push({ + deptName: 'vueNextAdmin', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '顶级部门', + id: Math.random(), + children: [ + { + deptName: 'IT外包服务', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '总部', + id: Math.random(), + }, + { + deptName: '资本控股', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '分部', + id: Math.random(), + }, + ], + }); + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/user/component/editUser.vue b/src/views/system/user/component/editUser.vue new file mode 100644 index 0000000..b7a0793 --- /dev/null +++ b/src/views/system/user/component/editUser.vue @@ -0,0 +1,202 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="修改用户" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户名称"> + <el-input v-model="ruleForm.userName" placeholder="请输入账户名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="用户昵称"> + <el-input v-model="ruleForm.userNickname" placeholder="请输入用户昵称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="关联角色"> + <el-select v-model="ruleForm.roleSign" placeholder="请选择" clearable class="w100"> + <el-option label="超级管理员" value="admin"></el-option> + <el-option label="普通用户" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="部门"> + <el-cascader + :options="deptData" + :props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }" + placeholder="请选择部门" + clearable + class="w100" + v-model="ruleForm.department" + > + <template #default="{ node, data }"> + <span>{{ data.deptName }}</span> + <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> + </template> + </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="手机号"> + <el-input v-model="ruleForm.phone" placeholder="请输入手机号" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="邮箱"> + <el-input v-model="ruleForm.email" placeholder="请输入" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="性别"> + <el-select v-model="ruleForm.sex" placeholder="请选择" clearable class="w100"> + <el-option label="男" value="男"></el-option> + <el-option label="女" value="女"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户密码"> + <el-input v-model="ruleForm.password" placeholder="请输入" type="password" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户过期"> + <el-date-picker v-model="ruleForm.overdueTime" type="date" placeholder="请选择" class="w100"> </el-date-picker> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="用户状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="用户描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入用户描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">修 改</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface DeptData { + deptName: string; + createTime: string; + status: boolean; + sort: number | string; + describe: string; + id: number; + children?: DeptData[]; +} +interface RuleFormRow { + userName: string; + userNickname: string; + roleSign: string; + department: any; + phone: string; + email: string; + sex: string; + password: string; + overdueTime: string; + status: boolean; + describe: string; +} +interface UserState { + isShowDialog: boolean; + ruleForm: RuleFormRow; + deptData: Array<DeptData>; +} + +export default defineComponent({ + name: 'systemEditUser', + setup() { + const state = reactive<UserState>({ + isShowDialog: false, + ruleForm: { + userName: '', // 账户名称 + userNickname: '', // 用户昵称 + roleSign: '', // 关联角色 + department: [], // 部门 + phone: '', // 手机号 + email: '', // 邮箱 + sex: '', // 性别 + password: '', // 账户密码 + overdueTime: '', // 账户过期 + status: true, // 用户状态 + describe: '', // 用户描述 + }, + deptData: [], // 部门数据 + }); + // 打开弹窗 + const openDialog = (row: RuleFormRow) => { + state.ruleForm = row; + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 初始化部门数据 + const initTableData = () => { + state.deptData.push({ + deptName: 'vueNextAdmin', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '顶级部门', + id: Math.random(), + children: [ + { + deptName: 'IT外包服务', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '总部', + id: Math.random(), + }, + { + deptName: '资本控股', + createTime: new Date().toLocaleString(), + status: true, + sort: Math.random(), + describe: '分部', + id: Math.random(), + }, + ], + }); + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..a120c59 --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,177 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" placeholder="请输入用户名称" style="max-width: 180px"> </el-input> + <el-button size="default" type="primary" class="ml10"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenAddUser"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增用户 + </el-button> + </div> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="userName" label="账户名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="userNickname" label="用户昵称" show-overflow-tooltip></el-table-column> + <el-table-column prop="roleSign" label="关联角色" show-overflow-tooltip></el-table-column> + <el-table-column prop="department" label="部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="phone" label="手机号" show-overflow-tooltip></el-table-column> + <el-table-column prop="email" label="邮箱" show-overflow-tooltip></el-table-column> + <el-table-column prop="status" label="用户状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status">启用</el-tag> + <el-tag type="info" v-else>禁用</el-tag> + </template> + </el-table-column> + <el-table-column prop="describe" label="用户描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser(scope.row)">修改</el-button> + <el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="mt15" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:current-page="tableData.param.pageNum" + background + v-model:page-size="tableData.param.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="tableData.total" + > + </el-pagination> + </el-card> + <AddUer ref="addUserRef" /> + <EditUser ref="editUserRef" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import AddUer from '/@/views/system/user/component/addUser.vue'; +import EditUser from '/@/views/system/user/component/editUser.vue'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + userName: string; + userNickname: string; + roleSign: string; + department: string[]; + phone: string; + email: string; + sex: string; + password: string; + overdueTime: Date; + status: boolean; + describe: string; + createTime: string; +} +interface TableDataState { + tableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + }; + }; +} + +export default defineComponent({ + name: 'systemUser', + components: { AddUer, EditUser }, + setup() { + const addUserRef = ref(); + const editUserRef = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + param: { + pageNum: 1, + pageSize: 10, + }, + }, + }); + // 初始化表格数据 + const initTableData = () => { + const data: Array<TableDataRow> = []; + for (let i = 0; i < 2; i++) { + data.push({ + userName: i === 0 ? 'admin' : 'test', + userNickname: i === 0 ? '我是管理员' : '我是普通用户', + roleSign: i === 0 ? 'admin' : 'common', + department: i === 0 ? ['vueNextAdmin', 'IT外包服务'] : ['vueNextAdmin', '资本控股'], + phone: '12345678910', + email: 'vueNextAdmin@123.com', + sex: '女', + password: '123456', + overdueTime: new Date(), + status: true, + describe: i === 0 ? '不可删除' : '测试用户', + createTime: new Date().toLocaleString(), + }); + } + state.tableData.data = data; + state.tableData.total = state.tableData.data.length; + }; + // 打开新增用户弹窗 + const onOpenAddUser = () => { + addUserRef.value.openDialog(); + }; + // 打开修改用户弹窗 + const onOpenEditUser = (row: TableDataRow) => { + editUserRef.value.openDialog(row); + }; + // 删除用户 + const onRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.userName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + ElMessage.success('删除成功'); + }) + .catch(() => {}); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.param.pageSize = val; + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.param.pageNum = val; + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + addUserRef, + editUserRef, + onOpenAddUser, + onOpenEditUser, + onRowDel, + onHandleSizeChange, + onHandleCurrentChange, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9d62054 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,72 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "lib": ["esnext", "dom", "dom.iterable", "scripthost"] /* Specify library files to be included in the compilation. */, + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, + // "declaration": true /* Generates corresponding '.d.ts' file. */, + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true /* Import emit helpers from 'tslib'. */, + // "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, + // "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "baseUrl": "." /* Base directory to resolve non-absolute module names. */, + "paths": { + "/@/*": ["src/*"] + } /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */, + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "types": ["vite/client"] /* Type declaration files to be included in compilation. */, + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..cf7bc27 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,79 @@ +import vue from '@vitejs/plugin-vue'; +import { resolve } from 'path'; +import { defineConfig, loadEnv, ConfigEnv } from 'vite'; + +const pathResolve = (dir: string): any => { + return resolve(__dirname, '.', dir); +}; + +const alias: Record<string, string> = { + '/@': pathResolve('./src/'), + 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js', +}; + +const viteConfig = defineConfig((mode: ConfigEnv) => { + const env = loadEnv(mode.mode, process.cwd()); + return { + plugins: [vue()], + root: process.cwd(), + resolve: { alias }, + base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH, + hmr: true, + optimizeDeps: { + include: ['element-plus/lib/locale/lang/zh-cn', 'element-plus/lib/locale/lang/en', 'element-plus/lib/locale/lang/zh-tw'], + }, + server: { + host: '0.0.0.0', + port: env.VITE_PORT as unknown as number, + open: env.VITE_OPEN, + proxy: { + '/gitee': { + target: 'https://gitee.com', + ws: true, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/gitee/, ''), + }, + }, + }, + build: { + outDir: 'dist', + sourcemap: false, + chunkSizeWarningLimit: 1500, + rollupOptions: { + output: { + entryFileNames: `assets/[name].${new Date().getTime()}.js`, + chunkFileNames: `assets/[name].${new Date().getTime()}.js`, + assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`, + compact: true, + manualChunks: { + vue: ['vue', 'vue-router', 'pinia'], + echarts: ['echarts'], + }, + }, + }, + }, + css: { + postcss: { + plugins: [ + { + postcssPlugin: 'internal:charset-removal', + AtRule: { + charset: (atRule) => { + if (atRule.name === 'charset') { + atRule.remove(); + } + }, + }, + }, + ], + }, + }, + define: { + __VUE_I18N_LEGACY_API__: JSON.stringify(false), + __VUE_I18N_FULL_INSTALL__: JSON.stringify(false), + __INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false), + }, + }; +}); + +export default viteConfig; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..9c75e08 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2236 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/parser@^7.16.4": + version "7.18.4" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" + integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== + +"@babel/runtime@^7.12.0": + version "7.18.3" + resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" + integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== + dependencies: + regenerator-runtime "^0.13.4" + +"@ctrl/tinycolor@^3.4.1": + version "3.4.1" + resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32" + integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw== + +"@element-plus/icons-vue@^2.0.3": + version "2.0.4" + resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.4.tgz#98fb9680c814a2a4f231b8bdabc8cd59b1b79d86" + integrity sha512-UeBVBU3fuBsYa9mzM7DgkRztQ1Aftw3sMTI/1gZsqXq2NWiCOi16ZYXXGIc0jFDIu+k6SojzdlxOjv+rN/Y6FQ== + +"@element-plus/icons-vue@^2.0.5": + version "2.0.5" + resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.5.tgz#8eb4143a7b5e4d8468d2e72af99eefee446f5ea0" + integrity sha512-jvNWyKcdvPvMDLTWjghrPY+bYHKqh7hbAFIPe+HWR073zilzt33csREzmKx3VwhdlJUW5u0nCqN+0rwI8jlH+w== + +"@eslint/eslintrc@^1.3.0": + version "1.3.0" + resolved "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f" + integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.2" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@floating-ui/core@^0.7.2": + version "0.7.2" + resolved "https://registry.npmmirror.com/@floating-ui/core/-/core-0.7.2.tgz#f7af9613d080dc29360e77c970965b79b524d45a" + integrity sha512-FRVAkSNU/vGXLIsgbggcs70GkXKEOXgBBbNpYPNHSaKsCAMMd00NrjbtKTesxkdv9xm9N3+XiDlcFGY6WnatBg== + +"@floating-ui/dom@^0.5.2": + version "0.5.2" + resolved "https://registry.npmmirror.com/@floating-ui/dom/-/dom-0.5.2.tgz#908f3febbfc0d6696d70921616ec194fe07af183" + integrity sha512-z1DnEa7F3d8Fm/eXSbii8UEGpcjZGkQaYYUI0WpEVgD3vBfebDW8j/3ysusxonuMexoigA+A3b/fYH7sEqiwyg== + dependencies: + "@floating-ui/core" "^0.7.2" + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@interactjs/actions@1.10.13", "@interactjs/actions@^1.10.2": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/actions/-/actions-1.10.13.tgz#278891ce7cfdc03124f1993cd45c434d43b71ef9" + integrity sha512-WRFfZKJ57Iwmn3w8nMvsOaryaRBBxYIWSX8iKTKsaqwHerQkd3el9yKp2miXsdsGkzabofqp5GDuB6Dwbq7Uew== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/auto-scroll@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/auto-scroll/-/auto-scroll-1.10.13.tgz#f01599bc6b15b86027256c8dadf04349b28c4fb5" + integrity sha512-YfeMKjFtassTzFThDZPwZnzwGyHzELC+npzjjtb8AHcaMagYE89mZ+c61gSSDHJKpbp6YAEyU+F4uXuuhwwKsQ== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/auto-start@1.10.13", "@interactjs/auto-start@^1.10.2": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/auto-start/-/auto-start-1.10.13.tgz#195a86f861820f3f6d3ff7d873e463fa164259ff" + integrity sha512-bZPL+aJd3YT9wlha7k7fcjjU8cXGUTAZN2G/eSds32pxhpjvlpKJMNvH0h2z7Mcnipyq9eRHVj0Q9oc1Zjy3qg== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/core@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/core/-/core-1.10.13.tgz#62d7f9f98b047ab5046e8fe0fab58afd06f961cb" + integrity sha512-hHiY0yZ+vvmhGkJ4C3KhK3fFPh/ModRqdyqFMrlJ5djLCsilkA1SM+0WL6ckBwlIwKu2z+fHXLZuXt7v+7/Azw== + +"@interactjs/dev-tools@1.10.13", "@interactjs/dev-tools@^1.10.2": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/dev-tools/-/dev-tools-1.10.13.tgz#6ac1ab3e369476321fc299b742b11ff1ccc3d4f1" + integrity sha512-niQ7k4xAr8vpgmYhv3aBjddNZjqvAvn57YWCR7YCrfnH+o72mDLnrYg5rcvXF88qr7Rv+xl22V1wBkTX6JOEzA== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/inertia@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/inertia/-/inertia-1.10.13.tgz#57115d9b3d6f1d070b8a3013661f522926be50b4" + integrity sha512-9RRR92EsUjlMPQ5LH9SgP2Litcluk24VOqwm+LZP74w6+9SuApuVd0W+aZcXBGrOaUdm42KrywPU7801A0eomw== + dependencies: + "@interactjs/offset" "1.10.13" + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/interact@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/interact/-/interact-1.10.13.tgz#505724af99f46036bcfb2760de6788535a02d90b" + integrity sha512-ctz3CXpoxd4Z7FhayGERx6ufWNUjeP8Xim1KpdSrfpVv8SF0PDtgcYn3HHhL4ImeJtdn+yZFhdMc/x01MjvHHg== + dependencies: + "@interactjs/core" "1.10.13" + "@interactjs/types" "1.10.13" + "@interactjs/utils" "1.10.13" + +"@interactjs/interactjs@^1.10.2": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/interactjs/-/interactjs-1.10.13.tgz#bd9d67755eadcd66459c12e96691e45982da00e3" + integrity sha512-RfSYrttHQkfj+hqkJb86upjcoUtmD0FVWr62xsAwJy0sCWKzk34n/ofXlBFPM1kl/d+LqpyINbZEKaaJDE6BOw== + dependencies: + "@interactjs/actions" "1.10.13" + "@interactjs/auto-scroll" "1.10.13" + "@interactjs/auto-start" "1.10.13" + "@interactjs/core" "1.10.13" + "@interactjs/dev-tools" "1.10.13" + "@interactjs/inertia" "1.10.13" + "@interactjs/interact" "1.10.13" + "@interactjs/modifiers" "1.10.13" + "@interactjs/offset" "1.10.13" + "@interactjs/pointer-events" "1.10.13" + "@interactjs/reflow" "1.10.13" + "@interactjs/utils" "1.10.13" + +"@interactjs/modifiers@1.10.13", "@interactjs/modifiers@^1.10.2": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/modifiers/-/modifiers-1.10.13.tgz#09e0a8044909ef2c977873d7925ea165ba0370bd" + integrity sha512-WeIxPOtV/eZg23B95Z3dazy5Y6Kq5+1MQ2msnHJ22JBrJZ2nfNttXT6X9NNmXTPq1t5vqwoBsdlQ9YIwj78siQ== + dependencies: + "@interactjs/snappers" "1.10.13" + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/offset@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/offset/-/offset-1.10.13.tgz#8ca249ac6a0c6284765b3fd91ef657ea39adb5ed" + integrity sha512-fVZ5XAOHjafXzFTqt53bgwL5v4u6LgrYmx0/8ApMPLbrxX0W4IckETtAMx//3PUIOJ3Y6XhdKKKAOmPe8+LpiQ== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/pointer-events@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/pointer-events/-/pointer-events-1.10.13.tgz#9b9032b3a07855f417473d85231cddcdf0c14c85" + integrity sha512-bIbajHzmQb6+ab53Apk9VzaSXXC03miuwuMXSn/jq9JvkVMgRaoCHjTXq8UI8eGyq5Pi4AT5kqnWhB3x9FqwEw== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/reflow@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/reflow/-/reflow-1.10.13.tgz#ed2301d42873438c9f6d374b70331d20cc9edf8b" + integrity sha512-nTo0l6qEYlcWRmg3V+ko7HNDcsy/HljVc7F8LoJyRpgrE/ZXMKM8w7SPMdU3iGaQXGVNw6lPVXqJowPfS+LhIw== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/snappers@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/snappers/-/snappers-1.10.13.tgz#bcc0985938145eb39020449daee6cd9050dea0e2" + integrity sha512-UT8IrFaZsLEMfiZn99o+X/7ixbhjo8+O/YqdlmHUJ3E/Ac+bVQmb1Qfz5VgiRNKgsjmTCi4uCj72Ikf7nf9kDg== + optionalDependencies: + "@interactjs/interact" "1.10.13" + +"@interactjs/types@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/types/-/types-1.10.13.tgz#0ebcc9ab582cb27e84ccdd2a7a33c87076cd511e" + integrity sha512-VdsUBs2YSdrgB2ZuL2UL0WW3fH6XuINjdk7XE9K+r64X9k2IC3nQm7pIg7HjO3iiLtuBNUVEGy+eJwU1G8t/Lg== + +"@interactjs/utils@1.10.13": + version "1.10.13" + resolved "https://registry.npmmirror.com/@interactjs/utils/-/utils-1.10.13.tgz#dbdc8a15ed2470919b56f0e849d18da0c667ae95" + integrity sha512-WWgG2NmGIdPudytNaF5KhqnAZ/2JPpnUs9mX0AKwdbLSuG2n5kOYJv4t8IOHkXhPDuoY/PZ5r19ODHWUXkCVlQ== + +"@intlify/core-base@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.1.10.tgz#cbd3099f375c789a1b974f3ea79b6efb8bb148fa" + integrity sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw== + dependencies: + "@intlify/devtools-if" "9.1.10" + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + +"@intlify/devtools-if@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.1.10.tgz#8704852a4fa547df43df71a16b1cc4b27e758aa3" + integrity sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ== + dependencies: + "@intlify/shared" "9.1.10" + +"@intlify/message-compiler@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.1.10.tgz#271f5e1cb65f3cec4b1fb243e50615747613f4be" + integrity sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg== + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + source-map "0.6.1" + +"@intlify/message-resolver@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/message-resolver/-/message-resolver-9.1.10.tgz#fb1dabdec2e29942df26f47e19444278a6e2f070" + integrity sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w== + +"@intlify/runtime@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/runtime/-/runtime-9.1.10.tgz#70582a16810f68953d1cbf7183c8107a9137b580" + integrity sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA== + dependencies: + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + +"@intlify/shared@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-9.1.10.tgz#9e2527276b43ae3f354c4015eb04f855d9d7a707" + integrity sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA== + +"@intlify/vue-devtools@9.1.10": + version "9.1.10" + resolved "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz#c62535d86742bcd16593806a4fcae49f6fc8ae6d" + integrity sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ== + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": + version "2.11.7" + resolved "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671" + integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + +"@transloadit/prettier-bytes@0.0.7": + version "0.0.7" + resolved "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b" + integrity sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + +"@types/event-emitter@^0.3.3": + version "0.3.3" + resolved "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.3.tgz#727032a9fc67565f96bbd78b2e2809275c97d7e7" + integrity sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q== + +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/lodash-es@^4.17.6": + version "4.17.6" + resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz#c2ed4c8320ffa6f11b43eb89e9eaeec65966a0a0" + integrity sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.182": + version "4.14.182" + resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + +"@types/node@^17.0.39": + version "17.0.41" + resolved "https://registry.npmmirror.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b" + integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw== + +"@types/nprogress@^0.2.0": + version "0.2.0" + resolved "https://registry.npmmirror.com/@types/nprogress/-/nprogress-0.2.0.tgz#86c593682d4199212a0509cc3c4d562bbbd6e45f" + integrity sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A== + +"@types/sortablejs@^1.13.0": + version "1.13.0" + resolved "https://registry.npmmirror.com/@types/sortablejs/-/sortablejs-1.13.0.tgz#870223438f8f2cd81157b128a4c0261adbcaa946" + integrity sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ== + +"@typescript-eslint/eslint-plugin@^5.27.0": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz#fdf59c905354139046b41b3ed95d1609913d0758" + integrity sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw== + dependencies: + "@typescript-eslint/scope-manager" "5.27.1" + "@typescript-eslint/type-utils" "5.27.1" + "@typescript-eslint/utils" "5.27.1" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.27.0": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.27.1.tgz#3a4dcaa67e45e0427b6ca7bb7165122c8b569639" + integrity sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ== + dependencies: + "@typescript-eslint/scope-manager" "5.27.1" + "@typescript-eslint/types" "5.27.1" + "@typescript-eslint/typescript-estree" "5.27.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz#4d1504392d01fe5f76f4a5825991ec78b7b7894d" + integrity sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg== + dependencies: + "@typescript-eslint/types" "5.27.1" + "@typescript-eslint/visitor-keys" "5.27.1" + +"@typescript-eslint/type-utils@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz#369f695199f74c1876e395ebea202582eb1d4166" + integrity sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw== + dependencies: + "@typescript-eslint/utils" "5.27.1" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.27.1.tgz#34e3e629501349d38be6ae97841298c03a6ffbf1" + integrity sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg== + +"@typescript-eslint/typescript-estree@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz#7621ee78607331821c16fffc21fc7a452d7bc808" + integrity sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw== + dependencies: + "@typescript-eslint/types" "5.27.1" + "@typescript-eslint/visitor-keys" "5.27.1" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.27.1.tgz#b4678b68a94bc3b85bf08f243812a6868ac5128f" + integrity sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.27.1" + "@typescript-eslint/types" "5.27.1" + "@typescript-eslint/typescript-estree" "5.27.1" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.27.1": + version "5.27.1" + resolved "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz#05a62666f2a89769dac2e6baa48f74e8472983af" + integrity sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ== + dependencies: + "@typescript-eslint/types" "5.27.1" + eslint-visitor-keys "^3.3.0" + +"@uppy/companion-client@^2.2.1": + version "2.2.1" + resolved "https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.1.tgz#cef4b15185dd8ee6024386c8aae809e8e05dcd53" + integrity sha512-Y3E10NJLMfp/wjgthNhx3gJtT67fzFCPNPFwpNNRs5iJsW6PANhJ420eyMUFzfmEZ56ZzGYxr5pzJZx8YxHICQ== + dependencies: + "@uppy/utils" "^4.1.0" + namespace-emitter "^2.0.1" + +"@uppy/core@^2.1.1": + version "2.3.1" + resolved "https://registry.npmmirror.com/@uppy/core/-/core-2.3.1.tgz#1d7a40f0a0b96a2709115bf7d087b4e6ab1403f4" + integrity sha512-KV04X7ueYbYX1p37/i3QsoQSw8IDP8Yb+Bh9KNN0X2Vcun6K2VnNjhVtPmPXtyjDZooK7lVIqhRX8TZWcSfgSQ== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/store-default" "^2.1.0" + "@uppy/utils" "^4.1.0" + lodash.throttle "^4.1.1" + mime-match "^1.0.2" + namespace-emitter "^2.0.1" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/store-default@^2.1.0": + version "2.1.0" + resolved "https://registry.npmmirror.com/@uppy/store-default/-/store-default-2.1.0.tgz#3fbcac626dd515668b88762d812017bd4f9b75d4" + integrity sha512-BkcR1wGw6Kwbvr8m1tKF9EDDWSTJoTGnVseBF/iW4bzR22assbtxZIE1iroo68UMqYEG4rv63SX4BUEtNvVjdA== + +"@uppy/utils@^4.1.0": + version "4.1.0" + resolved "https://registry.npmmirror.com/@uppy/utils/-/utils-4.1.0.tgz#19f3f08cd21b383cdcdf95adbec76d9c1a694b68" + integrity sha512-C47DUl4uLzmQZdW+VmetIgGRurXuPsvb+/pyYqh9DJn0Phep8u7AOj/tlJA5CHv4pefNHsFjXpaWfSUG3HtW3A== + dependencies: + lodash.throttle "^4.1.1" + +"@uppy/xhr-upload@^2.0.3": + version "2.1.2" + resolved "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.2.tgz#0f644e3371b611b10cd5ddbd7d799ab9f88a3786" + integrity sha512-VCsb7J5yHsof49nnUa+Y1n27UMtqHPttQmmoCa5hmjqa9R7ZISpBkXKOQmZo526eopKNuAKSAdkHWfCm8efJTA== + dependencies: + "@uppy/companion-client" "^2.2.1" + "@uppy/utils" "^4.1.0" + nanoid "^3.1.25" + +"@vitejs/plugin-vue@^2.3.3": + version "2.3.3" + resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz#fbf80cc039b82ac21a1acb0f0478de8f61fbf600" + integrity sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw== + +"@vue/compiler-core@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz#b3c42e04c0e0f2c496ff1784e543fbefe91e215a" + integrity sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + source-map "^0.6.1" + +"@vue/compiler-dom@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5" + integrity sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ== + dependencies: + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/compiler-sfc@3.2.37", "@vue/compiler-sfc@^3.2.36": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4" + integrity sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-ssr" "3.2.37" + "@vue/reactivity-transform" "3.2.37" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + magic-string "^0.25.7" + postcss "^8.1.10" + source-map "^0.6.1" + +"@vue/compiler-ssr@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff" + integrity sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw== + dependencies: + "@vue/compiler-dom" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/devtools-api@^6.0.0", "@vue/devtools-api@^6.0.0-beta.7", "@vue/devtools-api@^6.1.4": + version "6.1.4" + resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.1.4.tgz#b4aec2f4b4599e11ba774a50c67fa378c9824e53" + integrity sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ== + +"@vue/reactivity-transform@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz#0caa47c4344df4ae59f5a05dde2a8758829f8eca" + integrity sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + estree-walker "^2.0.2" + magic-string "^0.25.7" + +"@vue/reactivity@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848" + integrity sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A== + dependencies: + "@vue/shared" "3.2.37" + +"@vue/runtime-core@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz#7ba7c54bb56e5d70edfc2f05766e1ca8519966e3" + integrity sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ== + dependencies: + "@vue/reactivity" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/runtime-dom@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz#002bdc8228fa63949317756fb1e92cdd3f9f4bbd" + integrity sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw== + dependencies: + "@vue/runtime-core" "3.2.37" + "@vue/shared" "3.2.37" + csstype "^2.6.8" + +"@vue/server-renderer@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz#840a29c8dcc29bddd9b5f5ffa22b95c0e72afdfc" + integrity sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA== + dependencies: + "@vue/compiler-ssr" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/shared@3.2.37": + version "3.2.37" + resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" + integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw== + +"@vueuse/core@^8.6.0": + version "8.6.0" + resolved "https://registry.npmmirror.com/@vueuse/core/-/core-8.6.0.tgz#a8f80363cc63d17382423f16beae57696f376e67" + integrity sha512-VirzExCm/N+QdrEWT7J4uSrvJ5hquKIAU9alQ37kUvIJk9XxCLxmfRnmekYc1kz2+6BnoyuKYXVmrMV351CB4w== + dependencies: + "@vueuse/metadata" "8.6.0" + "@vueuse/shared" "8.6.0" + vue-demi "*" + +"@vueuse/metadata@8.6.0": + version "8.6.0" + resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.6.0.tgz#34771443a72ee891ae001a70aa05dd9a1d799372" + integrity sha512-F+CKPvaExsm7QgRr8y+ZNJFwXasn89rs5wth/HeX9lJ1q8XEt+HJ16Q5Sxh4rfG5YSKXrStveVge8TKvPjMjFA== + +"@vueuse/shared@8.6.0": + version "8.6.0" + resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.6.0.tgz#63dad9fc4b73a7fccbe5d6b97adeacf73d4fec41" + integrity sha512-Y/IVywZo7IfEoSSEtCYpkVEmPV7pU35mEIxV7PbD/D3ly18B3mEsBaPbtDkNM/QP3zAZ5mn4nEkOfddX4uwuIA== + dependencies: + vue-demi "*" + +"@wangeditor/basic-modules@^1.1.1": + version "1.1.1" + resolved "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.1.tgz#1ae0b11202b2ac319b4883e46f4d069ffce2f78d" + integrity sha512-tQl2Pw8M2g3CM+ESx2phzr9zSKeuFCM1AMBoPdnlbatU7Dnae0CsEB/b3C+gI0dIQzM2jh34yTmqgbbhrwuRLg== + dependencies: + is-url "^1.2.4" + +"@wangeditor/code-highlight@^1.0.2": + version "1.0.2" + resolved "https://registry.npmmirror.com/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz#df6bf7ac8d232c6afb0cb8189baa9f8d52feeded" + integrity sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ== + dependencies: + prismjs "^1.23.0" + +"@wangeditor/core@^1.1.1": + version "1.1.1" + resolved "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.1.tgz#f749a7d65ad95dbffccdf4d6f11272be8134eb88" + integrity sha512-SrbvOGlONMNMOeFIJI7fC9x0/6T6LvQHTITPCqjgbCm2QF+POcrHzRKGQOqKCsyKi9UJz9hLsjsvJnvP10rxjQ== + dependencies: + "@types/event-emitter" "^0.3.3" + event-emitter "^0.3.5" + html-void-elements "^2.0.0" + i18next "^20.4.0" + scroll-into-view-if-needed "^2.2.28" + slate-history "^0.66.0" + +"@wangeditor/editor@^5.1.1": + version "5.1.1" + resolved "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.1.tgz#009b11277de86a4052087d0428934e7d2dd30147" + integrity sha512-BtccuHFm0QvYunIhIu7tllQWkwppkmEkD3OJ5Mn+F0REPQ/Z3HiEXbtlss2t9c/kHO4CtiFwv2XD/k/VEg7taA== + dependencies: + "@uppy/core" "^2.1.1" + "@uppy/xhr-upload" "^2.0.3" + "@wangeditor/basic-modules" "^1.1.1" + "@wangeditor/code-highlight" "^1.0.2" + "@wangeditor/core" "^1.1.1" + "@wangeditor/list-module" "^1.0.2" + "@wangeditor/table-module" "^1.1.0" + "@wangeditor/upload-image-module" "^1.0.1" + "@wangeditor/video-module" "^1.1.0" + 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" + +"@wangeditor/list-module@^1.0.2": + version "1.0.2" + resolved "https://registry.npmmirror.com/@wangeditor/list-module/-/list-module-1.0.2.tgz#c9e57c4c34bbcc32df3a9030df2fda0bb4f77a39" + integrity sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg== + +"@wangeditor/table-module@^1.1.0": + version "1.1.0" + resolved "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.0.tgz#5cd4ebdd0500915c51793efd6227c43b5e185d77" + integrity sha512-QpjCXSzsXcsR0pEI5Pu28e8aYh9+lHcVV4TTmGV6lRGE/etQF3PHUZNGUlfhkCgmGPq+E7n/Whb4RpAM3PJVhw== + +"@wangeditor/upload-image-module@^1.0.1": + version "1.0.1" + resolved "https://registry.npmmirror.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz#a074518d73ce9c5cfd3e8ee56d1adf831996f142" + integrity sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w== + +"@wangeditor/video-module@^1.1.0": + version "1.1.0" + resolved "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.0.tgz#664405b1eeef1e9ab09f84a50270a4394f885355" + integrity sha512-VR6x7Vk9ebvXtxCPwobiNiTGZGgqEzCVc6ViWlNH3v4jlDIeo/s7N7OCgpvELR7X/X7GHecBu7wySDkHIskB5w== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.7.1: + version "8.7.1" + resolved "https://registry.npmmirror.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +async-validator@^4.1.1: + version "4.1.1" + resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.1.1.tgz#3cd1437faa2de64743f7d56649dd904c946a18fe" + integrity sha512-p4DO/JXwjs8klJyJL8Q2oM4ks5fUTze/h5k10oPPKMiLe1fj3G1QMzPHNmN1Py4ycOk7WlO2DcGXv1qiESJCZA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +batch-processor@1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" + integrity sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +claygl@^1.2.1: + version "1.3.0" + resolved "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz#7a6e2903210519ac358848f5d78070ed211685f3" + integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ== + +clipboard@^2.0.6: + version "2.0.11" + resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5" + integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compute-scroll-into-view@^1.0.17: + version "1.0.17" + resolved "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" + integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +countup.js@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/countup.js/-/countup.js-2.2.0.tgz#e20e247abf801190056c5eeed51ceb13cef6ea0c" + integrity sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g== + +cropperjs@^1.5.12: + version "1.5.12" + resolved "https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.12.tgz#d9c0db2bfb8c0d769d51739e8f916bbc44e10f50" + integrity sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^2.6.8: + version "2.6.20" + resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda" + integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA== + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dayjs@^1.11.3: + version "1.11.3" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258" + integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A== + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom7@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz#b861ce5d67a6becd7aaa3ad02942ff14b1240331" + integrity sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g== + dependencies: + ssr-window "^3.0.0-alpha.1" + +dotenv@^16.0.1: + version "16.0.1" + resolved "https://registry.npmmirror.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" + integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== + +echarts-gl@^2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz#ee228a6c7520a6fb7bbb71ea94394f3637ade033" + integrity sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA== + dependencies: + claygl "^1.2.1" + zrender "^5.1.1" + +echarts-wordcloud@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz#52ef817895801ffe9e99dd1bacab7686b2dec04a" + integrity sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g== + +echarts@^5.3.2: + version "5.3.2" + resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.2.tgz#0a7b3be8c48a48b2e7cb1b82121df0c208d42d2c" + integrity sha512-LWCt7ohOKdJqyiBJ0OGBmE9szLdfA9sGcsMEi+GGoc6+Xo75C+BkcT/6NNGRHAWtnQl2fNow05AQjznpap28TQ== + dependencies: + tslib "2.3.0" + zrender "5.3.1" + +element-plus@^2.2.2: + version "2.2.5" + resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.5.tgz#2bb889660c9bcb9bb71e18619915b35e0f48d569" + integrity sha512-Kl0yn/PQca5YQo3M3NPBP4Xl71NQuMtDx5zNXZGVyl5FjdMujXiFB9SXKYGDUCgFU3d/Rl14vB4Fpmcl2Iz+Hw== + dependencies: + "@ctrl/tinycolor" "^3.4.1" + "@element-plus/icons-vue" "^2.0.5" + "@floating-ui/dom" "^0.5.2" + "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" + "@types/lodash" "^4.14.182" + "@types/lodash-es" "^4.17.6" + "@vueuse/core" "^8.6.0" + async-validator "^4.1.1" + dayjs "^1.11.3" + escape-html "^1.0.3" + lodash "^4.17.21" + lodash-es "^4.17.21" + lodash-unified "^1.0.2" + memoize-one "^6.0.0" + normalize-wheel-es "^1.1.2" + +element-resize-detector@^1.2.1: + version "1.2.4" + resolved "https://registry.npmmirror.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" + integrity sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg== + dependencies: + batch-processor "1.0.0" + +es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14: + version "0.10.61" + resolved "https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.61.tgz#311de37949ef86b6b0dcea894d1ffedb909d3269" + integrity sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +esbuild-android-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.43.tgz#59bf3edad6863c27aa92bbb5c1d83a9a5c981495" + integrity sha512-kqFXAS72K6cNrB6RiM7YJ5lNvmWRDSlpi7ZuRZ1hu1S3w0zlwcoCxWAyM23LQUyZSs1PbjHgdbbfYAN8IGh6xg== + +esbuild-android-arm64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.43.tgz#0258704edf92ce2463af6d2900b844b5423bed63" + integrity sha512-bKS2BBFh+7XZY9rpjiHGRNA7LvWYbZWP87pLehggTG7tTaCDvj8qQGOU/OZSjCSKDYbgY7Q+oDw8RlYQ2Jt2BA== + +esbuild-darwin-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.43.tgz#72a47295678d4aa0656979baa8cf6d5c8c92656f" + integrity sha512-/3PSilx011ttoieRGkSZ0XV8zjBf2C9enV4ScMMbCT4dpx0mFhMOpFnCHkOK0pWGB8LklykFyHrWk2z6DENVUg== + +esbuild-darwin-arm64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.43.tgz#5f5823170b8d85b888957f0794e186caac447aca" + integrity sha512-1HyFUKs8DMCBOvw1Qxpr5Vv/ThNcVIFb5xgXWK3pyT40WPvgYIiRTwJCvNs4l8i5qWF8/CK5bQxJVDjQvtv0Yw== + +esbuild-freebsd-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.43.tgz#e4a48b08181053837e6cd9bda19ae0af94d493b0" + integrity sha512-FNWc05TPHYgaXjbPZO5/rJKSBslfG6BeMSs8GhwnqAKP56eEhvmzwnIz1QcC9cRVyO+IKqWNfmHFkCa1WJTULA== + +esbuild-freebsd-arm64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.43.tgz#386e780d36c1dedf3a1cdab79e0bbacd873274e6" + integrity sha512-amrYopclz3VohqisOPR6hA3GOWA3LZC1WDLnp21RhNmoERmJ/vLnOpnrG2P/Zao+/erKTCUqmrCIPVtj58DRoA== + +esbuild-linux-32@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.43.tgz#040ed6b9ebf06d73acdf2acce7f1cd0c12fbc6a5" + integrity sha512-KoxoEra+9O3AKVvgDFvDkiuddCds6q71owSQEYwjtqRV7RwbPzKxJa6+uyzUulHcyGVq0g15K0oKG5CFBcvYDw== + +esbuild-linux-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.43.tgz#8abbb7594ab6a008f2aae72d95d8a4fdc59d9000" + integrity sha512-EwINwGMyiJMgBby5/SbMqKcUhS5AYAZ2CpEBzSowsJPNBJEdhkCTtEjk757TN/wxgbu3QklqDM6KghY660QCUw== + +esbuild-linux-arm64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.43.tgz#4e8e9ce77cbf7efec65e79e512b3d2fbd2da398f" + integrity sha512-UlSpjMWllAc70zYbHxWuDS3FJytyuR/gHJYBr8BICcTNb/TSOYVBg6U7b3jZ3mILTrgzwJUHwhEwK18FZDouUQ== + +esbuild-linux-arm@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.43.tgz#9e41ee5e099c0ffdfd150da154330c2c0226cc96" + integrity sha512-e6YzQUoDxxtyamuF12eVzzRC7bbEFSZohJ6igQB9tBqnNmIQY3fI6Cns3z2wxtbZ3f2o6idkD2fQnlvs2902Dg== + +esbuild-linux-mips64le@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.43.tgz#4b41f465a787f91cc4fe7dffa0dcabf655935a1a" + integrity sha512-f+v8cInPEL1/SDP//CfSYzcDNgE4CY3xgDV81DWm3KAPWzhvxARrKxB1Pstf5mB56yAslJDxu7ryBUPX207EZA== + +esbuild-linux-ppc64le@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.43.tgz#ca15934f5b46728dd9ac05270e783e7feaca9eaf" + integrity sha512-5wZYMDGAL/K2pqkdIsW+I4IR41kyfHr/QshJcNpUfK3RjB3VQcPWOaZmc+74rm4ZjVirYrtz+jWw0SgxtxRanA== + +esbuild-linux-riscv64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.43.tgz#70fce2b5a0605a67e58b5a357b0e00be1029836d" + integrity sha512-lYcAOUxp85hC7lSjycJUVSmj4/9oEfSyXjb/ua9bNl8afonaduuqtw7hvKMoKuYnVwOCDw4RSfKpcnIRDWq+Bw== + +esbuild-linux-s390x@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.43.tgz#318d03b4f4ccc7fa44ac7562121cf4a4529e477a" + integrity sha512-27e43ZhHvhFE4nM7HqtUbMRu37I/4eNSUbb8FGZWszV+uLzMIsHDwLoBiJmw7G9N+hrehNPeQ4F5Ujad0DrUKQ== + +esbuild-netbsd-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.43.tgz#86130ce204ef0162a96e863b55851efecc92f423" + integrity sha512-2mH4QF6hHBn5zzAfxEI/2eBC0mspVsZ6UVo821LpAJKMvLJPBk3XJO5xwg7paDqSqpl7p6IRrAenW999AEfJhQ== + +esbuild-openbsd-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.43.tgz#0229dc2db2ded97b03bb93bba7646b30ffdf5d0d" + integrity sha512-ZhQpiZjvqCqO8jKdGp9+8k9E/EHSA+zIWOg+grwZasI9RoblqJ1QiZqqi7jfd6ZrrG1UFBNGe4m0NFxCFbMVbg== + +esbuild-sunos-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.43.tgz#17e316216eb9f1de25d52a9000356ae5b869e736" + integrity sha512-DgxSi9DaHReL9gYuul2rrQCAapgnCJkh3LSHPKsY26zytYppG0HgkgVF80zjIlvEsUbGBP/GHQzBtrezj/Zq1Q== + +esbuild-windows-32@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.43.tgz#a173757bc6dfd0f2656ff40b64f7f9290745778e" + integrity sha512-Ih3+2O5oExiqm0mY6YYE5dR0o8+AspccQ3vIAtRodwFvhuyGLjb0Hbmzun/F3Lw19nuhPMu3sW2fqIJ5xBxByw== + +esbuild-windows-64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.43.tgz#c447b23126aad158c4fe6a394342cafd97926ed1" + integrity sha512-8NsuNfI8xwFuJbrCuI+aBqNTYkrWErejFO5aYM+yHqyHuL8mmepLS9EPzAzk8rvfaJrhN0+RvKWAcymViHOKEw== + +esbuild-windows-arm64@0.14.43: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.43.tgz#3caed1b430d394d7a7836407b9d36c4750246e76" + integrity sha512-7ZlD7bo++kVRblJEoG+cepljkfP8bfuTPz5fIXzptwnPaFwGS6ahvfoYzY7WCf5v/1nX2X02HDraVItTgbHnKw== + +esbuild@^0.14.27: + version "0.14.43" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.43.tgz#c227d585c512d3e0f23b88f50b8e16501147f647" + integrity sha512-Uf94+kQmy/5jsFwKWiQB4hfo/RkM9Dh7b79p8yqd1tshULdr25G2szLz631NoH3s2ujnKEKVD16RmOxvCNKRFA== + optionalDependencies: + esbuild-android-64 "0.14.43" + esbuild-android-arm64 "0.14.43" + esbuild-darwin-64 "0.14.43" + esbuild-darwin-arm64 "0.14.43" + esbuild-freebsd-64 "0.14.43" + esbuild-freebsd-arm64 "0.14.43" + esbuild-linux-32 "0.14.43" + esbuild-linux-64 "0.14.43" + esbuild-linux-arm "0.14.43" + esbuild-linux-arm64 "0.14.43" + esbuild-linux-mips64le "0.14.43" + esbuild-linux-ppc64le "0.14.43" + esbuild-linux-riscv64 "0.14.43" + esbuild-linux-s390x "0.14.43" + esbuild-netbsd-64 "0.14.43" + esbuild-openbsd-64 "0.14.43" + esbuild-sunos-64 "0.14.43" + esbuild-windows-32 "0.14.43" + esbuild-windows-64 "0.14.43" + esbuild-windows-arm64 "0.14.43" + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-plugin-vue@^9.1.0: + version "9.1.0" + resolved "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz#b528941325e26a24bc5d5c5030c0a8996c36659c" + integrity sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g== + dependencies: + eslint-utils "^3.0.0" + natural-compare "^1.4.0" + nth-check "^2.0.1" + postcss-selector-parser "^6.0.9" + semver "^7.3.5" + vue-eslint-parser "^9.0.1" + xml-name-validator "^4.0.0" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^8.17.0: + version "8.17.0" + resolved "https://registry.npmmirror.com/eslint/-/eslint-8.17.0.tgz#1cfc4b6b6912f77d24b874ca1506b0fe09328c21" + integrity sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw== + dependencies: + "@eslint/eslintrc" "^1.3.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.2" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + 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.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^9.3.1, espree@^9.3.2: + version "9.3.2" + resolved "https://registry.npmmirror.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== + dependencies: + acorn "^8.7.1" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.npmmirror.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.npmmirror.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +follow-redirects@^1.14.9: + version "1.15.1" + resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.15.0: + version "13.15.0" + resolved "https://registry.npmmirror.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw== + dependencies: + delegate "^3.1.2" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" + integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + +i18next@^20.4.0: + version "20.6.1" + resolved "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz#535e5f6e5baeb685c7d25df70db63bf3cc0aa345" + integrity sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== + dependencies: + "@babel/runtime" "^7.12.0" + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.npmmirror.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immer@^9.0.6: + version "9.0.14" + resolved "https://registry.npmmirror.com/immer/-/immer-9.0.14.tgz#e05b83b63999d26382bb71676c9d827831248a48" + integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw== + +immutable@^4.0.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" + integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.8.1: + version "2.9.0" + resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hotkey@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz#1835a68171a91e5c9460869d96336947c8340cef" + integrity sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414" + integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +jsplumb@^2.15.6: + version "2.15.6" + resolved "https://registry.npmmirror.com/jsplumb/-/jsplumb-2.15.6.tgz#16d97a195a52cc8e4227d9e29971ff82b83e8faf" + integrity sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg== + +klona@^2.0.4: + version "2.0.5" + resolved "https://registry.npmmirror.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash-unified@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.2.tgz#bb2694db3533781e5cce984af60cfaea318b83c1" + integrity sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.25.7: + version "0.25.9" + resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + dependencies: + sourcemap-codec "^1.4.8" + +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-match@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz#3f87c31e9af1a5fd485fb9db134428b23bbb7ba8" + integrity sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg== + dependencies: + wildcard "^1.1.0" + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mitt@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230" + integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg== + +mitt@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" + integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +namespace-emitter@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz#978d51361c61313b4e6b8cf6f3853d08dfa2b17c" + integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + +nanoid@^3.1.25, nanoid@^3.2.0, nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-wheel-es@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz#285e43676a62d687bf145e33452ea6be435162d0" + integrity sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png== + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.npmmirror.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pinia@^2.0.14: + version "2.0.14" + resolved "https://registry.npmmirror.com/pinia/-/pinia-2.0.14.tgz#0837898c20291ebac982bbfca95c8d3c6099925f" + integrity sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA== + dependencies: + "@vue/devtools-api" "^6.1.4" + vue-demi "*" + +postcss-selector-parser@^6.0.9: + version "6.0.10" + resolved "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss@^8.1.10, postcss@^8.4.13: + version "8.4.14" + resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +preact@^10.5.13: + version "10.7.3" + resolved "https://registry.npmmirror.com/preact/-/preact-10.7.3.tgz#f98c09a29cb8dbb22e5fc824a1edcc377fc42b5a" + integrity sha512-giqJXP8VbtA1tyGa3f1n9wiN7PrHtONrDyE3T+ifjr/tTkg+2N4d/6sjC9WyJKv8wM7rOYDveqy5ZoFmYlwo4w== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^2.6.2: + version "2.6.2" + resolved "https://registry.npmmirror.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + +print-js@^1.6.0: + version "1.6.0" + resolved "https://registry.npmmirror.com/print-js/-/print-js-1.6.0.tgz#692b046cf31992b46afa6c6d8a9db1c69d431d1f" + integrity sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg== + +prismjs@^1.23.0: + version "1.28.0" + resolved "https://registry.npmmirror.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qrcodejs2-fixes@^0.0.2: + version "0.0.2" + resolved "https://registry.npmmirror.com/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz#a2f5d7816100073d1c09088ac75a34404d025b30" + integrity sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.22.0: + version "1.22.0" + resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^2.59.0: + version "2.75.6" + resolved "https://registry.npmmirror.com/rollup/-/rollup-2.75.6.tgz#ac4dc8600f95942a0180f61c7c9d6200e374b439" + integrity sha512-OEf0TgpC9vU6WGROJIk1JA3LR5vk/yvqlzxqdrE2CzzXnqKXNzbAwlWUXis8RS3ZPe7LAq+YUxsRa0l3r27MLA== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sass-loader@^13.0.0: + version "13.0.0" + resolved "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.0.0.tgz#0b4bff0289951ed21240bca54453eca3dbda1713" + integrity sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q== + dependencies: + klona "^2.0.4" + neo-async "^2.6.2" + +sass@^1.52.2: + version "1.52.3" + resolved "https://registry.npmmirror.com/sass/-/sass-1.52.3.tgz#b7cc7ffea2341ccc9a0c4fd372bf1b3f9be1b6cb" + integrity sha512-LNNPJ9lafx+j1ArtA7GyEJm9eawXN8KlA1+5dF6IZyoONg1Tyo/g+muOsENWJH/2Q1FHbbV4UwliU0cXMa/VIA== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +screenfull@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.1.tgz#3b71e6f06b72d817a8d3be73c45ebe71fa8da1ce" + integrity sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew== + +scroll-into-view-if-needed@^2.2.28: + version "2.2.29" + resolved "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" + integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== + dependencies: + compute-scroll-into-view "^1.0.17" + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA== + +semver@^7.3.5, semver@^7.3.6, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slate-history@^0.66.0: + version "0.66.0" + resolved "https://registry.npmmirror.com/slate-history/-/slate-history-0.66.0.tgz#ac63fddb903098ceb4c944433e3f75fe63acf940" + integrity sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== + dependencies: + is-plain-object "^5.0.0" + +slate@^0.72.0: + version "0.72.8" + resolved "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz#5a018edf24e45448655293a68bfbcf563aa5ba81" + integrity sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + dependencies: + immer "^9.0.6" + is-plain-object "^5.0.0" + tiny-warning "^1.0.3" + +snabbdom@^3.1.0: + version "3.5.0" + resolved "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.5.0.tgz#e75acbdedb26ea327c75028a433ba064db0ccf6e" + integrity sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g== + +sortablejs@^1.15.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a" + integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@0.6.1, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +splitpanes@^3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/splitpanes/-/splitpanes-3.1.1.tgz#be806205681a87c34075f1a06192df684e370e32" + integrity sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA== + +ssr-window@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz#fd5b82801638943e0cc704c4691801435af7ac37" + integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@2.3.0: + version "2.3.0" + resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.npmmirror.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.6.0" + resolved "https://registry.npmmirror.com/type/-/type-2.6.0.tgz#3ca6099af5981d36ca86b78442973694278a219f" + integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== + +typescript@^4.7.3: + version "4.7.3" + resolved "https://registry.npmmirror.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" + integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +vite@^2.9.9: + version "2.9.10" + resolved "https://registry.npmmirror.com/vite/-/vite-2.9.10.tgz#f574d96655622c2e0fbc662edd0ed199c60fe91a" + integrity sha512-TwZRuSMYjpTurLqXspct+HZE7ONiW9d+wSWgvADGxhDPPyoIcNywY+RX4ng+QpK30DCa1l/oZgi2PLZDibhzbQ== + dependencies: + esbuild "^0.14.27" + postcss "^8.4.13" + resolve "^1.22.0" + rollup "^2.59.0" + optionalDependencies: + fsevents "~2.3.2" + +vue-clipboard3@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz#79b026c765c0f6a5cde18a477c2dbfc7d3b9f178" + integrity sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A== + dependencies: + clipboard "^2.0.6" + +vue-demi@*: + version "0.13.1" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.1.tgz#7604904c88be338418a10abbc94d5b8caa14cb8c" + integrity sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg== + +vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz#d2535516f3f55adb387939427fe741065eb7948a" + integrity sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA== + dependencies: + debug "^4.3.4" + eslint-scope "^7.1.1" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^7.3.6" + +vue-grid-layout@^3.0.0-beta1: + version "3.0.0-beta1" + resolved "https://registry.npmmirror.com/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz#f8ce8eb7dbb1ff58f64820332afcc12c8cf873aa" + integrity sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg== + dependencies: + "@interactjs/actions" "^1.10.2" + "@interactjs/auto-start" "^1.10.2" + "@interactjs/dev-tools" "^1.10.2" + "@interactjs/interactjs" "^1.10.2" + "@interactjs/modifiers" "^1.10.2" + element-resize-detector "^1.2.1" + mitt "^2.1.0" + +vue-i18n@^9.1.10: + version "9.1.10" + resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.1.10.tgz#7ad516b89ba28debb90fc4181c9a2faec9ad97f9" + integrity sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g== + dependencies: + "@intlify/core-base" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + "@vue/devtools-api" "^6.0.0-beta.7" + +vue-router@^4.0.15: + version "4.0.15" + resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.15.tgz#b4a0661efe197f8c724e0f233308f8776e2c3667" + integrity sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg== + dependencies: + "@vue/devtools-api" "^6.0.0" + +vue@^3.2.36: + version "3.2.37" + resolved "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e" + integrity sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ== + dependencies: + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-sfc" "3.2.37" + "@vue/runtime-dom" "3.2.37" + "@vue/server-renderer" "3.2.37" + "@vue/shared" "3.2.37" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^1.1.0: + version "1.1.2" + resolved "https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz#a7020453084d8cd2efe70ba9d3696263de1710a5" + integrity sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng== + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +zrender@5.3.1, zrender@^5.1.1: + version "5.3.1" + resolved "https://registry.npmmirror.com/zrender/-/zrender-5.3.1.tgz#fa8e63ac7e719cfd563831fe8c42a9756c5af384" + integrity sha512-7olqIjy0gWfznKr6vgfnGBk7y4UtdMvdwFmK92vVQsQeDPyzkHW1OlrLEKg6GHz1W5ePf0FeN1q2vkl/HFqhXw== + dependencies: + tslib "2.3.0" -- Gitblit v1.9.2