commit 049828db859177266383d1db9bec6cd0d888176a Author: zpc Date: Tue Jul 29 19:22:24 2025 +0800 22 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7034f9b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# 告诉EditorConfig插件,这是根文件,不用继续往上查找 +root = true + +# 匹配全部文件 +[*] +# 设置字符集 +charset = utf-8 +# 缩进风格,可选space、tab +indent_style = space +# 缩进的空格数 +indent_size = 2 +# 结尾换行符,可选lf、cr、crlf +end_of_line = lf +# 在文件结尾插入新行 +insert_final_newline = true +# 删除一行中的前后空格 +trim_trailing_whitespace = true + +# 匹配md结尾的文件 +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.env b/.env new file mode 100644 index 0000000..977ffd9 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ + +# 页面标题 +VITE_APP_TITLE = 'ZRAdmin.NET' \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..488868c --- /dev/null +++ b/.env.development @@ -0,0 +1,16 @@ +# 开发环境配置 +ENV = 'development' + +VITE_APP_API_HOST = 'http://localhost:8888' + +# 开发环境 +VITE_APP_BASE_API = '/dev-api' + +# 路由前缀 +VITE_APP_ROUTER_PREFIX = '/' + +# 默认上传地址 +VITE_APP_UPLOAD_URL = '/Common/UploadFile' + +#socket API +VITE_APP_SOCKET_API = '/msghub' \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..56ccea2 --- /dev/null +++ b/.env.production @@ -0,0 +1,18 @@ +# 生产环境配置 +ENV = 'production' + + +# 生产环境 +VITE_APP_BASE_API = '/prod-api' + +# 路由前缀 +VITE_APP_ROUTER_PREFIX = '/' + +# 默认上传地址 +VITE_APP_UPLOAD_URL = '/Common/UploadFile' + +#socket API +VITE_APP_SOCKET_API = '/msghub' + +# 是否在打包时开启压缩,支持 gzip 和 brotli +VITE_BUILD_COMPRESS = gzip \ No newline at end of file diff --git a/.env.staging b/.env.staging new file mode 100644 index 0000000..62f968e --- /dev/null +++ b/.env.staging @@ -0,0 +1,18 @@ +# 测试环境配置 +ENV = 'staging' + + +# 测试环境 +VITE_APP_BASE_API = '/stage-api' + +# 路由前缀 +VITE_APP_ROUTER_PREFIX = '/' + +# 默认上传地址 +VITE_APP_UPLOAD_URL = '/Common/UploadFile' + +# 是否在打包时开启压缩,支持 gzip 和 brotli +VITE_BUILD_COMPRESS = gzip + +#socket API +VITE_APP_SOCKET_API = '/msghub' \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..cafab33 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,14 @@ +# 忽略build目录下类型为js的文件的语法检查 +build/*.js +# 忽略src/assets目录下文件的语法检查 +src/assets +# 忽略public目录下文件的语法检查 +public +# 忽略当前目录下为js的文件的语法检查 +# *.js +# 忽略当前目录下为vue的文件的语法检查 +# *.vue +/node_modules/ +/vite/ +.eslintrc.js +.prettierrc.js \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..82bbdee --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,199 @@ +// ESlint 检查配置 +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint', + sourceType: 'module' + }, + env: { + browser: true, + node: true, + es6: true, + }, + extends: ['plugin:vue/recommended', 'eslint:recommended'], + + // add your custom rules here + //it is base on https://github.com/vuejs/eslint-config-vue + rules: { + "vue/max-attributes-per-line": [2, { + "singleline": 10, + "multiline": { + "max": 1, + "allowFirstLine": false + } + }], + "vue/singleline-html-element-content-newline": "off", + "vue/multiline-html-element-content-newline":"off", + "vue/name-property-casing": ["error", "PascalCase"], + "vue/no-v-html": "off", + 'accessor-pairs': 2, + 'arrow-spacing': [2, { + 'before': true, + 'after': true + }], + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true + }], + 'camelcase': [0, { + 'properties': 'always' + }], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { + 'before': false, + 'after': true + }], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + 'curly': [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + 'eqeqeq': ["error", "always", {"null": "ignore"}], + 'generator-star-spacing': [2, { + 'before': true, + 'after': true + }], + 'handle-callback-err': [2, '^(err|error)$'], + 'indent': [2, 2, { + 'SwitchCase': 1 + }], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true + }], + 'keyword-spacing': [2, { + 'before': true, + 'after': true + }], + 'new-cap': [2, { + 'newIsCap': true, + 'capIsNew': false + }], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [2, { + 'allowLoop': false, + 'allowSwitch': false + }], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [2, { + 'max': 1 + }], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [2, { + 'defaultAssignment': false + }], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [2, { + 'vars': 'all', + 'args': 'none' + }], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [2, { + 'initialized': 'never' + }], + 'operator-linebreak': [2, 'after', { + 'overrides': { + '?': 'before', + ':': 'before' + } + }], + 'padded-blocks': [2, 'never'], + 'quotes': [2, 'single', { + 'avoidEscape': true, + 'allowTemplateLiterals': true + }], + 'semi': [2, 'never'], + 'semi-spacing': [2, { + 'before': false, + 'after': true + }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { + 'words': true, + 'nonwords': false + }], + 'spaced-comment': [2, 'always', { + 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] + }], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + 'yoda': [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': [2, 'always', { + objectsInObjects: false + }], + 'array-bracket-spacing': [2, 'never'] + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c73526c --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +**/*.log +.vs/* +tests/**/coverage/ +tests/e2e/reports +selenium-debug.log + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.local + +package-lock.json +yarn.lock +/deploy.js diff --git a/.jsbeautifyrc b/.jsbeautifyrc new file mode 100644 index 0000000..d79fae6 --- /dev/null +++ b/.jsbeautifyrc @@ -0,0 +1,12 @@ +{ + "brace_style": "none,preserve-inline", + "indent_size": 2, + "indent_char": " ", + "jslint_happy": true, + "unformatted": [ + "" + ], + "css": { + "indent_size": 2 + } +} \ No newline at end of file diff --git a/.prettierrc.cjs b/.prettierrc.cjs new file mode 100644 index 0000000..fae9475 --- /dev/null +++ b/.prettierrc.cjs @@ -0,0 +1,38 @@ +module.exports = { + // 超过最大值换行 + printWidth: 148, + // 使用 2 个空格缩进 + tabWidth: 2, + // 不使用缩进符,而使用空格 + useTabs: false, + // 行尾不需要有分号 + semi: false, + // 使用单引号 + singleQuote: true, + // 对象的 key 仅在必要时用引号 + quoteProps: 'as-needed', + // jsx 不使用单引号,而使用双引号 + jsxSingleQuote: false, + // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"",默认none + trailingComma: 'none', + // 在对象,数组括号与文字之间加空格 "{ foo: bar }" + bracketSpacing: true, + // jsx 标签的反尖括号需要换行 + jsxBracketSameLine: true, + bracketSameLine: true, + // 箭头函数,always只有一个参数的时候,也需要括号,'avoid'箭头函数只有一个参数的时候可以忽略括号 + arrowParens: 'always', + // 每个文件格式化的范围是文件的全部内容 + rangeStart: 0, + rangeEnd: Infinity, + // 不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 + proseWrap: 'preserve', + // 根据显示样式决定 html 要不要折行 + htmlWhitespaceSensitivity: 'css', + // 换行符使用 lf 结尾是 可选值"" + endOfLine: 'auto' +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a0e5e3a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,59 @@ +{ + "editor.fontSize": 15, + "editor.insertSpaces": false, + "editor.bracketPairColorization.enabled": true, + "editor.formatOnPaste": true, + "editor.formatOnType": true, + // 配置eslint适用于vue代码 + "eslint.validate": ["javascript", "typescript", "vue"], + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[scss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[ts]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[js]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + // 保存时 prettier 自动格式化 + "editor.formatOnSave": true, + // 保存时自动启用 eslint --fix 自动修复 + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "eslint.autoFixOnSave": "explicit" + }, + "eslint.options": { + "overrideConfig": { + "env": { + "browser": true, + "es6": true + }, + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "ecmaFeatures": { + "jsx": false + } + }, + "rules": { + "no-debugger": "off" + } + } + }, + "i18n-ally.displayLanguage": "zh-cn", + "i18n-ally.enabledParsers": ["json", "js"], + "i18n-ally.localesPaths": ["src/i18n/lang", "src/i18n/pages/login", "src/i18n/pages/menu"], + "i18n-ally.extract.parsers.html": { + "attributes": ["text", "title", "alt", "placeholder", "label", "aria-label"], + "ignoredTags": ["script", "style"], + "vBind": true, + "inlineText": true + }, + "i18n-ally.keystyle": "nested" +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..93d372d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 791736813@qq.com zr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..788cea2 --- /dev/null +++ b/README.md @@ -0,0 +1,103 @@ +

ZRAdmin.NET后台管理系统

+ +

+ + +

+ +## 🍟 概述 + +- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。 +- 配套后端代码仓库地址[ZRAdmin.NET](https://gitee.com/izory/ZrAdminNetCore/) 版本。 +- 前端采用 Vue3.0、Element UI Plus、vite、compisition api、Pinia 等。 +- 支持加载动态权限菜单,多方式轻松权限控制 +- 腾讯云秒杀场:[点我进入](https://curl.qcloud.com/4yEoRquq)。 +- 腾讯云优惠券:[点我领取](https://curl.qcloud.com/5J4nag8D)。 +- 七牛云通用云产品优惠券:[点我进入](https://s.qiniu.com/FzEfay)。 + +``` +如果对您有帮助,您可以点右上角 “Star” 收藏一下 ,这样作者才有继续免费下去的动力,谢谢!~ +``` + +## 🍿 在线体验 + +- 官方文档:http://www.izhaorui.cn +- 体验地址:http://demo.izhaorui.cn/vue3 +- 管理员:admin +- 密 码:123456 + +``` +由于是个人项目,资金有限,体验服是低配,请大家爱惜,轻戳,不胜感激!!! +``` + +## 🍁 前端运行 + +```bash +# 克隆项目 +git clone https://gitee.com/izory/ZRAdmin-vue.git + +# 进入项目目录 +cd ZRAdmin-vue + +# 安装依赖 +yarn --registry=https://registry.npm.taobao.org --strict-ssl false +yarn --registry=https://registry.npmmirror.com +# 启动服务 +yarn dev + +# 构建测试环境 yarn build:stage +# 构建生产环境 yarn build:prod +# 前端访问地址 http://localhost:8887 +``` + +## 🍖 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。(支持多语言) +5. 角色管理:角色菜单权限分配。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +8. 登录日志:系统登录日志记录查询包含登录异常。 +9. 系统接口:使用 swagger 生成相关 api 接口文档。 +10. 参数设置:常用参数配置 +11. 发送邮件:可以对多个用户进行发送邮件 +12. 任务系统:基于 Quartz.NET,可以在线(添加、修改、删除、手动执行)任务调度包含执行结果日志。 +13. 文章管理:可以写文章记录。 +14. 代码生成:可以一键生成前后端代码(.cs、.vue、.js、SQL 文件等),支持下载,自定义配置前端展示控件、让开发更快捷高效。 +15. 文件管理:可以进行上传文件管理,目前支持上传到本地、阿里云 +16. 通知管理:系统通知公告信息发布维护 +17. 参数管理:对系统动态配置常用参数。 +18. 多语言管理:动态修改多语言翻译 +19. 账号注册:可以注册账号登录系统。 +20. 多语言管理:支持静态、后端动态配置国际化。目前只支持中、英、繁体(仅支持 vue3) +21. 在线用户:可以查看正在登录使用的用户,可以对其踢出、通知操作 +22. db 审计日志:数据库审计功能 +23. 三方登录:提供三方登录实现逻辑 +24. 导入导出:支持中文表头导入、字典数据转换成文本导出 +25. 数据大屏:更直观的展示数据 + +## 🎉 优势 + +1. 前台系统不用编写登录、授权、认证模块;只负责编写业务模块即可 +2. 后台系统无需任何二次开发,直接发布即可使用 +3. 前台与后台系统分离,分别为不同的系统(域名可独立) +4. 全局异常统一处理 +5. 自定义的代码生成功能 +6. 国际化 + +## 💐 特别鸣谢 + +- 👉Ruoyi.vue:[Ruoyi](http://www.ruoyi.vip/) +- 👉zb-admin: [zb-admin](https://gitee.com/yuanzbz/vue-admin-perfect) + +## 🎀 捐赠 + +如果这个项目对您有所帮助,请扫下方二维码打赏作者喝杯咖啡。 + + +## 源码地址 + +- [Gitee](https://gitee.com/izory/ZrAdminNetCore/) +- [Github](https://github.com/izhaorui/ZrAdmin.NET/) diff --git a/bat/build.bat b/bat/build.bat new file mode 100644 index 0000000..ecbb454 --- /dev/null +++ b/bat/build.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] Weḅdistļ +echo. + +%~d0 +cd %~dp0 + +cd .. +yarn build:prod + +pause \ No newline at end of file diff --git a/bat/package.bat b/bat/package.bat new file mode 100644 index 0000000..965883a --- /dev/null +++ b/bat/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] װWeḅnode_modulesļ +echo. + +%~d0 +cd %~dp0 + +cd .. +yarn --registry=https://registry.npm.taobao.org + +pause \ No newline at end of file diff --git a/bat/run-web.bat b/bat/run-web.bat new file mode 100644 index 0000000..d2fe397 --- /dev/null +++ b/bat/run-web.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] ʹ Vite Web ̡ +echo. + +%~d0 +cd %~dp0 + +cd .. +yarn dev + +pause \ No newline at end of file diff --git a/html/ie.html b/html/ie.html new file mode 100644 index 0000000..052ffcd --- /dev/null +++ b/html/ie.html @@ -0,0 +1,46 @@ + + + + + + 请升级您的浏览器 + + + + + + +

请升级您的浏览器,以便我们更好的为您提供服务!

+

您正在使用 Internet Explorer 的早期版本(IE11以下版本或使用该内核的浏览器)。这意味着在升级浏览器前,您将无法访问此网站。

+
+

请注意:微软公司对Windows XP 及 Internet Explorer 早期版本的支持已经结束

+

自 2016 年 1 月 12 日起,Microsoft 不再为 IE 11 以下版本提供相应支持和更新。没有关键的浏览器安全更新,您的电脑可能易受有害病毒、间谍软件和其他恶意软件的攻击,它们可以窃取或损害您的业务数据和信息。请参阅 微软对 Internet Explorer 早期版本的支持将于 2016 年 1 月 12 日结束的说明

+
+

您可以选择更先进的浏览器

+

推荐使用以下浏览器的最新版本。如果您的电脑已有以下浏览器的最新版本则直接使用该浏览器访问即可。

+ +
+ + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..e078955 --- /dev/null +++ b/index.html @@ -0,0 +1,139 @@ + + + + + + + + + + ZRAdmin.NET管理系统 + + + + + +
+
+
+ +
+
正在加载系统资源...
+
+
+ + + + \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..86b1741 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,11 @@ +/* 主要作用是vscode导入使用别名时可以自动化提示文件路径 */ +{ + "compilerOptions": { + "experimentalDecorators": true, + "baseUrl": "./", + "paths": { + "@/*": ["src/*"] + } + }, + "exclude": ["node_modules", "dist", ".vscode"] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..4469455 --- /dev/null +++ b/package.json @@ -0,0 +1,64 @@ +{ + "name": "zr.admin", + "version": "v20240105", + "description": "ZRAdmin.NET管理系统", + "author": "ZR", + "license": "MIT", + "type": "module", + "scripts": { + "dev": "vite", + "build:prod": "vite build", + "build:stage": "vite build --mode staging", + "preview": "vite preview" + }, + "repository": { + "type": "git", + "url": "https://gitee.com/izory/ZrAdminNetCore" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "@microsoft/signalr": "^8.0.0", + "@vueuse/core": "^10.7.0", + "@wangeditor/editor": "^5.1.1", + "@wangeditor/editor-for-vue": "^5.1.11", + "axios": "^1.6.2", + "crypto-js": "^4.1.1", + "echarts": "5.2.2", + "element-plus": "^2.9.0", + "file-saver": "2.0.5", + "fuse.js": "6.4.6", + "highlight.js": "^11.5.1", + "js-cookie": "3.0.1", + "jsencrypt": "3.2.1", + "md-editor-v3": "^4.9.0", + "nprogress": "0.2.0", + "pinia": "^2.3.0", + "pinia-plugin-persistedstate": "^3.2.3", + "qrcodejs2-fixes": "^0.0.2", + "qs": "^6.11.0", + "sortablejs": "^1.15.6", + "v-code-diff": "^1.8.0", + "vue": "^3.5.13", + "vue-clipboard3": "^2.0.0", + "vue-countup-v3": "^1.4.0", + "vue-cropper": "1.0.2", + "vue-i18n": "9.2.2", + "vue-router": "^4.5.0", + "vxe-pc-ui": "^4.0.12", + "vxe-table": "^4.9.16", + "xe-utils": "^3.5.32" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "@vue/compiler-sfc": "^3.3.4", + "consola": "^3.2.3", + "sass": "^1.82.0", + "unplugin-auto-import": "^0.17.2", + "vite": "^6.0.2", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-lazy-import": "^1.0.7", + "vite-plugin-style-import": "^2.0.0", + "vite-plugin-svg-icons": "^2.0.1", + "vite-plugin-vue-setup-extend": "^0.4.0" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..fcb6999 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..c744625 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,62 @@ + + diff --git a/src/api/article/article.js b/src/api/article/article.js new file mode 100644 index 0000000..8c1a5e4 --- /dev/null +++ b/src/api/article/article.js @@ -0,0 +1,96 @@ +import request from '@/utils/request' + +// 查询列表 +export function listArticle(query) { + return request({ + url: '/Article/list', + method: 'get', + params: query + }) +} +// 查询最新列表 +export function listNewArticle(query) { + return request({ + url: '/Article/newList', + method: 'get', + params: query + }) +} + +// 查询详细 +export function getArticle(Id) { + return request({ + url: '/Article/' + Id, + method: 'get' + }) +} + +// 新增 +export function addArticle(data) { + return request({ + url: '/Article/add', + method: 'post', + data: data + }) +} + +// 修改 +export function updateArticle(data) { + return request({ + url: '/Article/edit', + method: 'put', + data: data + }) +} + +// 删除文章 +export function delArticle(id) { + return request({ + url: '/Article/' + id, + method: 'delete' + }) +} +// 查询目录 +export function listArticleCategory() { + return request({ + url: '/Article/CategoryList', + method: 'get' + }) +} +// 查询文章目录树 +export function listArticleCategoryTree() { + return request({ + url: '/Article/CategoryTreeList', + menubar: 'get' + }) +} + +// 置顶 +export function topArticle(data) { + return request({ + url: '/Article/top', + method: 'put', + data: data + }) +} +// 修改是否公开 +export function changeArticlePublic(data) { + return request({ + url: '/Article/ChangePublic', + method: 'put', + data: data + }) +} + +/** + * 审核 + * @param type 审核类型 pass ,reject + * @param ids id + */ +export function auditArticle(type, ids, data) { + return request({ + url: `article/${type}/${ids}`, + method: 'PUT', + params: data + }) +} diff --git a/src/api/article/articlecategory.js b/src/api/article/articlecategory.js new file mode 100644 index 0000000..4e344b3 --- /dev/null +++ b/src/api/article/articlecategory.js @@ -0,0 +1,88 @@ +import request from '@/utils/request' + +/** + * 文章目录分页查询 + * @param {查询条件} data + */ +export function listArticleCategory(query) { + return request({ + url: 'article/ArticleCategory/list', + method: 'get', + params: query + }) +} + +/** + * 文章目录tree查询 + * @param {查询条件} data + */ +export function treelistArticleCategory(query) { + return request({ + url: 'article/ArticleCategory/treelist', + method: 'get', + params: query + }) +} + +/** + * 新增文章目录 + * @param data + */ +export function addArticleCategory(data) { + return request({ + url: 'article/ArticleCategory', + method: 'post', + data: data + }) +} + +/** + * 修改文章目录 + * @param data + */ +export function updateArticleCategory(data) { + return request({ + url: 'article/ArticleCategory', + method: 'PUT', + data: data + }) +} + +/** + * 获取文章目录详情 + * @param {Id} + */ +export function getArticleCategory(id) { + return request({ + url: 'article/ArticleCategory/' + id, + method: 'get' + }) +} + +/** + * 删除文章目录 + * @param {主键} pid + */ +export function delArticleCategory(pid) { + return request({ + url: 'article/ArticleCategory/' + pid, + method: 'delete' + }) +} + +// 导出文章目录 +export function exportArticleCategory(query) { + return request({ + url: 'article/ArticleCategory/export', + method: 'get', + params: query + }) +} + +export function changeSort(data) { + return request({ + url: 'article/ArticleCategory/ChangeSort', + method: 'get', + params: data + }) +} diff --git a/src/api/article/articletopic.js b/src/api/article/articletopic.js new file mode 100644 index 0000000..b89e569 --- /dev/null +++ b/src/api/article/articletopic.js @@ -0,0 +1,62 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** + * 话题分页查询 + * @param {查询条件} data + */ +export function listArticleTopic(query) { + return request({ + url: 'article/ArticleTopic/list', + method: 'get', + params: query + }) +} + +/** + * 新增话题 + * @param data + */ +export function addArticleTopic(data) { + return request({ + url: 'article/ArticleTopic', + method: 'post', + data: data + }) +} +/** + * 修改话题 + * @param data + */ +export function updateArticleTopic(data) { + return request({ + url: 'article/ArticleTopic', + method: 'PUT', + data: data + }) +} +/** + * 获取话题详情 + * @param {Id} + */ +export function getArticleTopic(id) { + return request({ + url: 'article/ArticleTopic/' + id, + method: 'get' + }) +} + +/** + * 删除话题 + * @param {主键} pid + */ +export function delArticleTopic(pid) { + return request({ + url: 'article/ArticleTopic/delete/' + pid, + method: 'delete' + }) +} +// 导出话题 +export async function exportArticleTopic(query) { + await downFile('article/ArticleTopic/export', { ...query }) +} diff --git a/src/api/common.js b/src/api/common.js new file mode 100644 index 0000000..7932a9f --- /dev/null +++ b/src/api/common.js @@ -0,0 +1,23 @@ +import request from '@/utils/request' + +export function upload(data) { + return request({ + url: '/common/UploadFile', + method: 'POST', + data: data, + headers: { 'Content-Type': 'multipart/form-data' } + }) +} + +/** + * 发送邮件 + * @param {*} data + * @returns + */ +export function sendEmail(data) { + return request({ + url: '/common/SendEmail', + method: 'POST', + data: data + }) +} diff --git a/src/api/monitor/cache.js b/src/api/monitor/cache.js new file mode 100644 index 0000000..59d3505 --- /dev/null +++ b/src/api/monitor/cache.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 查询缓存详细 +export function getCache() { + return request({ + url: '/monitor/cache', + method: 'get' + }) +} diff --git a/src/api/monitor/job.js b/src/api/monitor/job.js new file mode 100644 index 0000000..d40b293 --- /dev/null +++ b/src/api/monitor/job.js @@ -0,0 +1,114 @@ +import request from '@/utils/request' + +export function queryTasks(data) { + return request({ + url: '/system/tasks/list', + method: 'get', + params: data + }) +} + +export function getTasks(id) { + return request({ + url: '/system/tasks/get?id=' + id, + method: 'get' + }) +} + +/** + * + * 获取所有任务 + * @returns + */ +export function getAllTasks() { + return request({ + url: '/system/tasks/getAll', + method: 'get' + }) +} + +/** + * 创建任务 + * @param {*} data + * @returns + */ +export function createTasks(data) { + return request({ + url: '/system/tasks/create', + method: 'post', + data + }) +} + +/** + * 更新任务 + * @param {*} data + * @returns + */ +export function updateTasks(data) { + return request({ + url: '/system/tasks/update', + method: 'post', + data + }) +} + +/** + * 删除任务 + * @param {*} id + * @returns + */ +export function deleteTasks(id) { + return request({ + url: '/system/tasks/delete?id=' + id, + method: 'delete' + }) +} + +/** + * 启动任务 + * @param {*} id + * @returns + */ +export function startTasks(id) { + return request({ + url: '/system/tasks/start?id=' + id, + method: 'get' + }) +} + +/** + * 停止任务 + * @param {*} id + * @returns + */ +export function stopTasks(id) { + return request({ + url: '/system/tasks/stop?id=' + id, + method: 'get' + }) +} + +/** + * 运行一次 + * @param {*} id + * @returns + */ +export function runTasks(id) { + return request({ + url: '/system/tasks/run?id=' + id, + method: 'get' + }) +} +/** + * 导出 + * @returns + */ +export function exportTasks() { + return request({ + url: '/system/tasks/export', + method: 'get' + }) +} + +export default { queryTasks, getTasks, getAllTasks, createTasks, updateTasks, deleteTasks, startTasks, stopTasks, runTasks, exportTasks } diff --git a/src/api/monitor/jobLog.js b/src/api/monitor/jobLog.js new file mode 100644 index 0000000..be1fffd --- /dev/null +++ b/src/api/monitor/jobLog.js @@ -0,0 +1,35 @@ +import request from '@/utils/request' + +// 查询调度日志列表 +export function listJobLog(query) { + return request({ + url: '/monitor/jobLog/list', + method: 'get', + params: query + }) +} + +// 删除调度日志 +export function delJobLog(jobLogId) { + return request({ + url: '/monitor/jobLog/' + jobLogId, + method: 'delete' + }) +} + +// 清空调度日志 +export function cleanJobLog() { + return request({ + url: '/monitor/jobLog/clean', + method: 'delete' + }) +} + +// 导出调度日志 +export function exportJobLog(query) { + return request({ + url: '/monitor/jobLog/export', + method: 'get', + params: query + }) +} \ No newline at end of file diff --git a/src/api/monitor/logininfor.js b/src/api/monitor/logininfor.js new file mode 100644 index 0000000..e31ca6a --- /dev/null +++ b/src/api/monitor/logininfor.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询登录日志列表 +export function list(query) { + return request({ + url: '/monitor/logininfor/list', + method: 'get', + params: query + }) +} + +// 查询我的登录日志列表 +export function queryMylist(query) { + return request({ + url: '/monitor/logininfor/mylist', + method: 'get', + params: query + }) +} + +// 删除登录日志 +export function delLogininfor(infoId) { + return request({ + url: '/monitor/logininfor/' + infoId, + method: 'delete' + }) +} + +// 清空登录日志 +export function cleanLogininfor() { + return request({ + url: '/monitor/logininfor/clean', + method: 'delete' + }) +} + +// 导出登录日志 +export function exportLogininfor(query) { + return request({ + url: '/monitor/logininfor/export', + method: 'get', + params: query + }) +} diff --git a/src/api/monitor/online.js b/src/api/monitor/online.js new file mode 100644 index 0000000..26a4646 --- /dev/null +++ b/src/api/monitor/online.js @@ -0,0 +1,28 @@ +import request from '@/utils/request' + +// 查询在线用户列表 +export function listOnline(query) { + return request({ + url: '/monitor/online/list', + method: 'get', + params: query + }) +} + +// 强退用户 +export function forceLogout(data) { + return request({ + url: '/monitor/online/force', + method: 'delete', + data: data + }) +} + +// 批量强退用户 +export function forceLogoutAll(data) { + return request({ + url: '/monitor/online/batchForce', + method: 'delete', + data: data + }) +} diff --git a/src/api/monitor/operlog.js b/src/api/monitor/operlog.js new file mode 100644 index 0000000..57f275a --- /dev/null +++ b/src/api/monitor/operlog.js @@ -0,0 +1,39 @@ +import request from '@/utils/request' +import QS from 'qs' + +// 查询操作日志列表 +export function list(query) { + return request({ + url: '/monitor/operlog/list', + method: 'get', + params: query, + paramsSerializer: function (params) { + return QS.stringify(params, { indices: false }) + } + }) +} + +// 删除操作日志 +export function delOperlog(operId) { + return request({ + url: '/monitor/operlog/' + operId, + method: 'delete' + }) +} + +// 清空操作日志 +export function cleanOperlog() { + return request({ + url: '/monitor/operlog/clean', + method: 'delete' + }) +} + +// 导出操作日志 +export function exportOperlog(query) { + return request({ + url: '/monitor/operlog/export', + method: 'get', + params: query + }) +} diff --git a/src/api/monitor/server.js b/src/api/monitor/server.js new file mode 100644 index 0000000..bdcc62b --- /dev/null +++ b/src/api/monitor/server.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 查询服务器详细 +export function getServer() { + return request({ + url: '/monitor/server', + method: 'get' + }) +} diff --git a/src/api/monitor/sqldifflog.js b/src/api/monitor/sqldifflog.js new file mode 100644 index 0000000..b46a7c0 --- /dev/null +++ b/src/api/monitor/sqldifflog.js @@ -0,0 +1,29 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** + * 数据差异日志分页查询 + * @param {查询条件} data + */ +export function listSqlDiffLog(query) { + return request({ + url: 'monitor/SqlDiffLog/list', + method: 'get', + params: query + }) +} + +/** + * 删除数据差异日志 + * @param {主键} pid + */ +export function delSqlDiffLog(pid) { + return request({ + url: 'monitor/SqlDiffLog/' + pid, + method: 'delete' + }) +} +// 导出数据差异日志 +export async function exportSqlDiffLog(query) { + await downFile('monitor/SqlDiffLog/export', { ...query }) +} diff --git a/src/api/monitor/useronlinelog.js b/src/api/monitor/useronlinelog.js new file mode 100644 index 0000000..a4b7d73 --- /dev/null +++ b/src/api/monitor/useronlinelog.js @@ -0,0 +1,51 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** +* 用户在线时长分页查询 +* @param {查询条件} data +*/ +export function listUserOnlineLog(query) { + return request({ + url: 'monitor/UserOnlineLog/list', + method: 'get', + params: query, + }) +} + +/** +* 新增用户在线时长 +* @param data +*/ +export function addUserOnlineLog(data) { + return request({ + url: 'monitor/UserOnlineLog', + method: 'post', + data: data, + }) +} +/** +* 获取用户在线时长详情 +* @param {Id} +*/ +export function getUserOnlineLog(id) { + return request({ + url: 'monitor/UserOnlineLog/' + id, + method: 'get' + }) +} + +/** +* 删除用户在线时长 +* @param {主键} pid +*/ +export function delUserOnlineLog(pid) { + return request({ + url: 'monitor/UserOnlineLog/delete/' + pid, + method: 'delete' + }) +} +// 导出用户在线时长 +export async function exportUserOnlineLog(query) { + await downFile('monitor/UserOnlineLog/export', { ...query }) +} diff --git a/src/api/public/bannerconfig.js b/src/api/public/bannerconfig.js new file mode 100644 index 0000000..c60b6bc --- /dev/null +++ b/src/api/public/bannerconfig.js @@ -0,0 +1,69 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** +* 广告管理分页查询 +* @param {查询条件} data +*/ +export function listBannerConfig(query) { + return request({ + url: 'public/BannerConfig/list', + method: 'get', + params: query, + }) +} + +/** +* 新增广告管理 +* @param data +*/ +export function addBannerConfig(data) { + return request({ + url: 'public/BannerConfig', + method: 'post', + data: data, + }) +} +/** +* 修改广告管理 +* @param data +*/ +export function updateBannerConfig(data) { + return request({ + url: 'public/BannerConfig', + method: 'PUT', + data: data, + }) +} +/** +* 获取广告管理详情 +* @param {Id} +*/ +export function getBannerConfig(id) { + return request({ + url: 'public/BannerConfig/' + id, + method: 'get' + }) +} + +/** +* 删除广告管理 +* @param {主键} pid +*/ +export function delBannerConfig(pid) { + return request({ + url: 'public/BannerConfig/delete/' + pid, + method: 'delete' + }) +} +// 导出广告管理 +export async function exportBannerConfig(query) { + await downFile('public/BannerConfig/export', { ...query }) +} +export function changeSort(data) { + return request({ + url: 'public/BannerConfig/ChangeSort', + method: 'get', + params: data + }) +} diff --git a/src/api/system/commonlang.js b/src/api/system/commonlang.js new file mode 100644 index 0000000..d1e6628 --- /dev/null +++ b/src/api/system/commonlang.js @@ -0,0 +1,100 @@ +import request from '@/utils/request' + +/** + * 多语言配置分页查询 + * @param {查询条件} data + */ +export function listCommonLang(query) { + return request({ + url: 'system/CommonLang/list', + method: 'get', + params: query + }) +} +/** + * 多语言配置查询 + * @param {查询条件} data + */ +export function listLangByLocale(locale) { + return request({ + url: 'system/CommonLang/list/' + locale, + method: 'get' + }) +} + +/** + * 新增多语言配置 + * @param data + */ +export function addCommonLang(data) { + return request({ + url: 'system/CommonLang', + method: 'post', + data: data + }) +} + +/** + * 修改多语言配置 + * @param data + */ +export function updateCommonLang(data) { + return request({ + url: 'system/CommonLang', + method: 'PUT', + data: data + }) +} + +/** + * 获取多语言配置详情 + * @param {Id} + */ +export function getCommonLang(id) { + return request({ + url: 'system/CommonLang/' + id, + method: 'get' + }) +} +/** + * 获取多语言配置详情 + * @param {key} + */ +export function getCommonLangByKey(key) { + return request({ + url: 'system/CommonLang/key/' + key, + method: 'get' + }) +} + +/** + * 删除多语言配置 + * @param {主键} pid + */ +export function delCommonLang(pid) { + return request({ + url: 'system/CommonLang/' + pid, + method: 'delete' + }) +} + +/** + * 删除多语言配置 + * @param {key} langkey + */ +export function delCommonLangByKey(langkey) { + return request({ + url: 'system/CommonLang/ByKey', + method: 'delete', + params: { langkey } + }) +} + +// 导出多语言配置 +export function exportCommonLang(query) { + return request({ + url: 'system/CommonLang/export', + method: 'get', + params: query + }) +} diff --git a/src/api/system/config.js b/src/api/system/config.js new file mode 100644 index 0000000..3633ba1 --- /dev/null +++ b/src/api/system/config.js @@ -0,0 +1,69 @@ +import request from '@/utils/request' + +// 查询参数列表 +export function listConfig(query) { + return request({ + url: '/system/config/list', + method: 'get', + params: query + }) +} + +// 查询参数详细 +export function getConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'get' + }) +} + +// 根据参数键名查询参数值 +export function getConfigKey(configKey) { + return request({ + url: '/system/config/configKey/' + configKey, + method: 'get' + }) +} + +// 新增参数配置 +export function addConfig(data) { + return request({ + url: '/system/config', + method: 'post', + data: data + }) +} + +// 修改参数配置 +export function updateConfig(data) { + return request({ + url: '/system/config', + method: 'put', + data: data + }) +} + +// 删除参数配置 +export function delConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'delete' + }) +} + +// 刷新参数缓存 +export function refreshCache() { + return request({ + url: '/system/config/refreshCache', + method: 'delete' + }) +} + +// 导出参数 +// export function exportConfig(query) { +// return request({ +// url: '/system/config/export', +// method: 'get', +// params: query +// }) +// } diff --git a/src/api/system/dept.js b/src/api/system/dept.js new file mode 100644 index 0000000..2804676 --- /dev/null +++ b/src/api/system/dept.js @@ -0,0 +1,68 @@ +import request from '@/utils/request' + +// 查询部门列表 +export function listDept(query) { + return request({ + url: '/system/dept/list', + method: 'get', + params: query + }) +} + +// 查询部门列表(排除节点) +export function listDeptExcludeChild(deptId) { + return request({ + url: '/system/dept/list/exclude/' + deptId, + method: 'get' + }) +} + +// 查询部门详细 +export function getDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'get' + }) +} + +// 查询部门下拉树结构 +export function treeselect() { + return request({ + url: '/system/dept/treeselect', + method: 'get' + }) +} + +// 根据角色ID查询部门树结构 +export function roleDeptTreeselect(roleId) { + return request({ + url: '/system/dept/roleDeptTreeselect/' + roleId, + method: 'get' + }) +} + +// 新增部门 +export function addDept(data) { + return request({ + url: '/system/dept', + method: 'post', + data: data + }) +} + +// 修改部门 +export function updateDept(data) { + return request({ + url: '/system/dept', + method: 'put', + data: data + }) +} + +// 删除部门 +export function delDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/src/api/system/dict/data.js b/src/api/system/dict/data.js new file mode 100644 index 0000000..77202b6 --- /dev/null +++ b/src/api/system/dict/data.js @@ -0,0 +1,89 @@ +import request from '@/utils/request' + +// 查询字典数据列表 +export function listData(query) { + return request({ + url: '/system/dict/data/list', + method: 'get', + params: query + }) +} + +// 查询字典数据详细 +export function getData(dictCode) { + return request({ + url: '/system/dict/data/info/' + dictCode, + method: 'get' + }) +} + +// 根据字典类型查询字典数据信息 +export function getDicts(dictType) { + if (typeof dictType === 'object') { + var data = dictType.map((x) => { + if (typeof x === 'object') { + return x.dictType + } else { + return x + } + }) + return request({ + url: '/system/dict/data/dicts', + data: data, + method: 'post' + }) + } else { + return request({ + url: '/system/dict/data/type/' + dictType, + method: 'get' + }) + } +} + +// 新增字典数据 +export function addData(data) { + return request({ + url: '/system/dict/data', + method: 'post', + data: data + }) +} + +// 修改字典数据 +export function updateData(data) { + return request({ + url: '/system/dict/data', + method: 'put', + data: data + }) +} + +// 状态修改 +export function changeStatus(dictCode, status) { + const data = { + dictCode, + status + } + return request({ + url: '/system/dict/data/changeStatus', + method: 'put', + data: data + }) +} + +// 删除字典数据 +export function delData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'delete' + }) +} + +// 导出字典数据 +export function exportData(query) { + return request({ + url: '/system/dict/data/export', + method: 'get', + params: query + }) +} diff --git a/src/api/system/dict/type.js b/src/api/system/dict/type.js new file mode 100644 index 0000000..27ae18f --- /dev/null +++ b/src/api/system/dict/type.js @@ -0,0 +1,69 @@ +import request from '@/utils/request' + +// 查询字典类型列表 +export function listType(query) { + return request({ + url: '/system/dict/type/list', + method: 'get', + params: query + }) +} + +// 查询字典类型详细 +export function getType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'get' + }) +} + +// 新增字典类型 +export function addType(data) { + return request({ + url: '/system/dict/type/edit', + method: 'post', + data: data + }) +} + +// 修改字典类型 +export function updateType(data) { + return request({ + url: '/system/dict/type/edit', + method: 'put', + data: data + }) +} + +// 删除字典类型 +export function delType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'delete' + }) +} + +// 清理参数缓存 +export function clearCache() { + return request({ + url: '/system/dict/type/clearCache', + method: 'delete' + }) +} + +// 导出字典类型 +export function exportType(query) { + return request({ + url: '/system/dict/type/export', + method: 'get', + params: query + }) +} + +// 获取字典选择框列表 +export function optionselect() { + return request({ + url: '/system/dict/type/optionselect', + method: 'get' + }) +} diff --git a/src/api/system/emaillog.js b/src/api/system/emaillog.js new file mode 100644 index 0000000..a06a77f --- /dev/null +++ b/src/api/system/emaillog.js @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +/** +* 邮件发送记录分页查询 +* @param {查询条件} data +*/ +export function listEmailLog(query) { + return request({ + url: 'system/EmailLog/list', + method: 'get', + params: query, + }) +} + +/** +* 新增邮件发送记录 +* @param data +*/ +export function sendEmail(data) { + return request({ + url: 'system/EmailLog/sendEmail', + method: 'post', + data: data, + }) +} +/** +* 获取邮件发送记录详情 +* @param {Id} +*/ +export function getEmailLog(id) { + return request({ + url: 'system/EmailLog/' + id, + method: 'get' + }) +} + +/** +* 删除邮件发送记录 +* @param {主键} pid +*/ +export function delEmailLog(pid) { + return request({ + url: 'system/EmailLog/' + pid, + method: 'delete' + }) +} diff --git a/src/api/system/emailtpl.js b/src/api/system/emailtpl.js new file mode 100644 index 0000000..0fc12e6 --- /dev/null +++ b/src/api/system/emailtpl.js @@ -0,0 +1,57 @@ +import request from '@/utils/request' + +/** +* 邮件模板分页查询 +* @param {查询条件} data +*/ +export function listEmailTpl(query) { + return request({ + url: 'system/EmailTpl/list', + method: 'get', + params: query, + }) +} + +/** +* 新增邮件模板 +* @param data +*/ +export function addEmailTpl(data) { + return request({ + url: 'system/EmailTpl', + method: 'post', + data: data, + }) +} +/** +* 修改邮件模板 +* @param data +*/ +export function updateEmailTpl(data) { + return request({ + url: 'system/EmailTpl', + method: 'PUT', + data: data, + }) +} +/** +* 获取邮件模板详情 +* @param {Id} +*/ +export function getEmailTpl(id) { + return request({ + url: 'system/EmailTpl/' + id, + method: 'get' + }) +} + +/** +* 删除邮件模板 +* @param {主键} pid +*/ +export function delEmailTpl(pid) { + return request({ + url: 'system/EmailTpl/' + pid, + method: 'delete' + }) +} diff --git a/src/api/system/login.js b/src/api/system/login.js new file mode 100644 index 0000000..11272ba --- /dev/null +++ b/src/api/system/login.js @@ -0,0 +1,118 @@ +import request from '@/utils/request' + +// 登录方法 +export function login(username, password, code, uuid, clientId) { + const data = { + username, + password, + code, + uuid, + clientId + } + return request({ + url: '/login', + method: 'POST', + data: data, + headers: { + userName: username + } + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + url: '/getInfo', + method: 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + url: '/LogOut', + method: 'POST' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + url: '/captchaImage', + method: 'get' + }) +} +/** + * 注册 + * @returns + */ +export function register(data) { + return request({ + url: '/register', + method: 'post', + data: data + }) +} + +/** + * 三方授权回调 + * @param {*} data + * @param {*} params + * @returns + */ +export function oauthCallback(data, params) { + return request({ + url: '/auth/callback', + method: 'post', + data: data, + params: params + }) +} + +/** + * 生成二维码 + * @param {*} data + * @returns + */ +export function generateQrcode(data) { + return request({ + url: '/GenerateQrcode', + method: 'GET', + params: data + }) +} + +/** + * 刷新二维码 + * @param {*} data + * @returns + */ +export function verifyScan(data) { + return request({ + url: '/VerifyScan', + method: 'post', + data: data + }) +} + +/** + * 发送短信验证码 + * @param {*} data + * @returns + */ +export function checkMobile(data) { + return request({ + method: 'post', + data: data, + url: '/checkMobile' + }) +} + +// 登录方法 +export function phoneLogin(data) { + return request({ + url: '/phoneLogin', + method: 'POST', + data: data + }) +} diff --git a/src/api/system/menu.js b/src/api/system/menu.js new file mode 100644 index 0000000..1414a43 --- /dev/null +++ b/src/api/system/menu.js @@ -0,0 +1,92 @@ +import request from '@/utils/request' + +// 查询菜单列表 +export function listMenu(query) { + return request({ + url: '/system/menu/treelist', + method: 'get', + params: query + }) +} +// 查询菜单列表 +export function listMenuById(menuId) { + return request({ + url: '/system/menu/list/' + menuId, + method: 'get' + }) +} +// 查询菜单详细 +export function getMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'get' + }) +} + +// 查询菜单下拉树结构 +export function treeselect() { + return request({ + url: '/system/Menu/treeSelect', + method: 'get' + }) +} + +// 根据角色ID查询菜单下拉树结构 +export function roleMenuTreeselect(roleId) { + return request({ + url: '/system/menu/roleMenuTreeselect/' + roleId, + method: 'get' + }) +} + +// 新增菜单 +export const addMenu = (data) => { + return request({ + url: '/system/menu/add', + method: 'put', + data: data + }) +} + +// 修改菜单 +export function updateMenu(data) { + return request({ + url: '/system/Menu/edit', + method: 'post', + data: data + }) +} + +// 删除菜单 +export function delMenu(menuId) { + return request({ + url: '/system/Menu/' + menuId, + method: 'delete' + }) +} + +// 删除菜单 +export function delAllMenu(menuId) { + return request({ + url: '/system/Menu/deleteAll/' + menuId, + method: 'delete' + }) +} + +//排序 +export function changeMenuSort(data) { + return request({ + url: '/system/Menu/ChangeSort', + method: 'GET', + params: data + }) +} + +// 获取路由 +export const getRouters = (query) => { + return request({ + url: '/getRouters', + method: 'get', + params: query + }) +} diff --git a/src/api/system/notice.js b/src/api/system/notice.js new file mode 100644 index 0000000..fc80afb --- /dev/null +++ b/src/api/system/notice.js @@ -0,0 +1,61 @@ +import request from '@/utils/request' + +// 导航栏查询公告列表 +export function queryNotice(query) { + return request({ + url: '/system/notice/queryNotice', + method: 'get', + params: query + }) +} + +// 查询公告列表 +export function listNotice(query) { + return request({ + url: '/system/notice/list', + method: 'get', + params: query + }) +} + +// 查询公告详细 +export function getNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'get' + }) +} + +// 新增公告 +export function addNotice(data) { + return request({ + url: '/system/notice', + method: 'post', + data: data + }) +} + +// 修改公告 +export function updateNotice(data) { + return request({ + url: '/system/notice', + method: 'put', + data: data + }) +} + +// 删除公告 +export function delNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'delete' + }) +} + +// 发送通知公告 +export function sendNotice(noticeId) { + return request({ + url: '/system/notice/send/' + noticeId, + method: 'PUT' + }) +} \ No newline at end of file diff --git a/src/api/system/post.js b/src/api/system/post.js new file mode 100644 index 0000000..8b9aff8 --- /dev/null +++ b/src/api/system/post.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' +// 查询岗位列表 +export function listPost(query) { + return request({ + url: '/system/post/list', + method: 'get', + params: query + }) +} + +// 查询岗位详细 +export function getPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'get' + }) +} + +// 新增岗位 +export function addPost(data) { + return request({ + url: '/system/post', + method: 'post', + data: data + }) +} + +// 修改岗位 +export function updatePost(data) { + return request({ + url: '/system/post', + method: 'put', + data: data + }) +} + +// 删除岗位 +export function delPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'delete' + }) +} + +// 导出岗位 +export async function exportPost(query) { + // return request({ + // url: '/system/post/export', + // method: 'get', + // params: query + // }) + await downFile('/system/post/export', query) +} diff --git a/src/api/system/role.js b/src/api/system/role.js new file mode 100644 index 0000000..ea28f22 --- /dev/null +++ b/src/api/system/role.js @@ -0,0 +1,80 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +// 查询角色列表 +export function listRole(query) { + return request({ + url: '/system/role/list', + method: 'get', + params: query + }) +} + +// 查询角色详细 +export function getRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'get' + }) +} + +// 新增角色 +export const addRole = (data) => { + return request({ + url: '/system/role/edit', + method: 'post', + data: data + }) +} + +// 修改角色 +export function updateRole(data) { + return request({ + url: '/system/role/edit', + method: 'put', + data: data + }) +} + +// 角色数据权限 +export function dataScope(data) { + return request({ + url: '/system/role/dataScope', + method: 'put', + data: data + }) +} + +// 角色状态修改 +export function changeRoleStatus(roleId, status) { + const data = { + roleId, + status + } + return request({ + url: '/system/role/changeStatus', + method: 'put', + data: data + }) +} + +// 删除角色 +export function delRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'delete' + }) +} + +// 导出角色 +export function exportRole(query) { + return request({ + url: '/system/role/export', + method: 'get', + params: query + }) +} +// 导出角色菜单 +export async function exportRoleMenu(query) { + await downFile('/system/role/exportRoleMenu', { ...query }) +} diff --git a/src/api/system/smscodelog.js b/src/api/system/smscodelog.js new file mode 100644 index 0000000..991c7f8 --- /dev/null +++ b/src/api/system/smscodelog.js @@ -0,0 +1,40 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** + * 短信验证码记录分页查询 + * @param {查询条件} data + */ +export function listSmscodeLog(query) { + return request({ + url: 'system/SmscodeLog/list', + method: 'get', + params: query + }) +} + +/** + * 获取短信验证码记录详情 + * @param {Id} + */ +export function getSmscodeLog(id) { + return request({ + url: 'system/SmscodeLog/' + id, + method: 'get' + }) +} + +/** + * 删除短信验证码记录 + * @param {主键} pid + */ +export function delSmscodeLog(pid) { + return request({ + url: 'system/SmscodeLog/' + pid, + method: 'delete' + }) +} +// 导出短信验证码记录 +export async function exportSmscodeLog(query) { + await downFile('system/SmscodeLog/export', { ...query }) +} diff --git a/src/api/system/sysusermsg.js b/src/api/system/sysusermsg.js new file mode 100644 index 0000000..b4417ec --- /dev/null +++ b/src/api/system/sysusermsg.js @@ -0,0 +1,82 @@ +import request from '@/utils/request' +import { downFile } from '@/utils/request' + +/** + * 用户系统消息分页查询 + * @param {查询条件} data + */ +export function listSysUserMsg(query) { + return request({ + url: 'SysUserMsg/list', + method: 'get', + params: query + }) +} + +/** + * 用户系统消息分页查询 + * @param {查询条件} data + */ +export function listMySysUserMsg(query) { + return request({ + url: 'SysUserMsg/mylist', + method: 'get', + params: query + }) +} + +/** + * 新增用户系统消息 + * @param data + */ +export function addSysUserMsg(data) { + return request({ + url: 'SysUserMsg', + method: 'post', + data: data + }) +} +/** + * 获取用户系统消息详情 + * @param {Id} + */ +export function getSysUserMsg(id) { + return request({ + url: 'SysUserMsg/' + id, + method: 'get' + }) +} + +/** + * 删除用户系统消息 + * @param {主键} pid + */ +export function delSysUserMsg(pid) { + return request({ + url: 'SysUserMsg/delete/' + pid, + method: 'delete' + }) +} +// 清空用户系统消息 +export function clearSysUserMsg() { + return request({ + url: 'SysUserMsg/clean', + method: 'delete' + }) +} +// 导出用户系统消息 +export async function exportSysUserMsg(query) { + await downFile('SysUserMsg/export', { ...query }) +} + +/** + * 已读用户系统消息 + * @param data + */ +export function readSysUserMsg(msgId, msgType) { + return request({ + url: 'SysUserMsg/read/' + msgId + '/' + msgType, + method: 'post', + params: { msgType } + }) +} diff --git a/src/api/system/thirdaccount.js b/src/api/system/thirdaccount.js new file mode 100644 index 0000000..7637df3 --- /dev/null +++ b/src/api/system/thirdaccount.js @@ -0,0 +1,70 @@ +import request from '@/utils/request' + +/** +* 三方账号绑定分页查询 +* @param {查询条件} data +*/ +export function listThirdAccount(query) { + return request({ + url: 'system/ThirdAccount/list', + method: 'get', + params: query, + }) +} + + +/** +* 新增三方账号绑定 +* @param data +*/ +export function addThirdAccount(data) { + return request({ + url: 'system/ThirdAccount', + method: 'post', + data: data, + }) +} + +/** +* 修改三方账号绑定 +* @param data +*/ +export function updateThirdAccount(data) { + return request({ + url: 'system/ThirdAccount', + method: 'PUT', + data: data, + }) +} + +/** +* 获取三方账号绑定详情 +* @param {Id} +*/ +export function getThirdAccount(id) { + return request({ + url: 'system/ThirdAccount/' + id, + method: 'get' + }) +} + +/** +* 删除三方账号绑定 +* @param {主键} pid +*/ +export function delThirdAccount(pid) { + return request({ + url: 'system/ThirdAccount/' + pid, + method: 'delete' + }) +} + +// 导出三方账号绑定 +export function exportThirdAccount(query) { + return request({ + url: 'system/ThirdAccount/export', + method: 'get', + params: query + }) +} + diff --git a/src/api/system/user.js b/src/api/system/user.js new file mode 100644 index 0000000..d7ee0ed --- /dev/null +++ b/src/api/system/user.js @@ -0,0 +1,131 @@ +import request from '@/utils/request' +import { praseStrZero } from '@/utils/ruoyi' +import { downFile } from '@/utils/request' + +// 查询用户列表 +export function listUser(query) { + return request({ + url: '/system/user/list', + method: 'get', + params: query + }) +} + +// 查询用户详细 +export function getUser(userId) { + return request({ + url: '/system/user/' + praseStrZero(userId), + method: 'get' + }) +} + +// 新增用户 +export function addUser(data) { + return request({ + url: '/system/user/add', + method: 'post', + data: data + }) +} + +// 修改用户 +export function updateUser(data) { + return request({ + url: '/system/user/edit', + method: 'put', + data: data + }) +} + +// 删除用户 +export function delUser(userId) { + return request({ + url: '/system/user/' + userId, + method: 'delete' + }) +} + +// 导出用户 +export async function exportUser(query) { + // return request({ + // url: '/system/User/export', + // method: 'get', + // params: query + // }) + await downFile('/system/user/export', { ...query }) +} + +// 用户密码重置 +export function resetUserPwd(userId, password) { + const data = { + userId, + password + } + return request({ + url: '/system/user/resetPwd', + method: 'put', + data: data + }) +} + +// 用户状态修改 +export function changeUserStatus(userId, status) { + const data = { + userId, + status + } + return request({ + url: '/system/user/changeStatus', + method: 'put', + data: data + }) +} + +// 查询用户个人信息 +export function getUserProfile() { + return request({ + url: '/system/user/profile', + method: 'get' + }) +} + +// 修改用户个人信息 +export function updateUserProfile(data) { + return request({ + url: '/system/user/profile', + method: 'put', + data: data + }) +} + +// 用户密码重置 +export function updateUserPwd(oldPassword, newPassword) { + const data = { + oldPassword, + newPassword + } + return request({ + url: '/system/user/profile/updatePwd', + method: 'put', + params: data + }) +} + +// 用户头像上传 +export function uploadAvatar(data) { + return request({ + url: '/system/user/profile/avatar', + method: 'post', + data: data, + headers: { 'Content-Type': 'multipart/form-data' } + }) +} + +// 下载用户导入模板 +export function importTemplate() { + return request({ + url: '/system/user/importTemplate', + method: 'get', + responseType: 'blob' //1.首先设置responseType对象格式为 blob: + }) +} diff --git a/src/api/system/userRoles.js b/src/api/system/userRoles.js new file mode 100644 index 0000000..d5d94b3 --- /dev/null +++ b/src/api/system/userRoles.js @@ -0,0 +1,37 @@ +import request from '@/utils/request' + +// 查询角色用户 +export function getRoleUsers(query) { + return request({ + url: '/system/userRole/list', + method: 'get', + params: query, + }) +} + +// 添加角色用户 +export function createRoleUsers(data) { + return request({ + url: '/system/userRole/create', + method: 'post', + data + }) +} +// 删除角色用户 +export function deleteRoleUsers(data) { + return request({ + url: '/system/userRole/delete', + method: 'post', + data + }) +} +// 查询角色未添加用户列表 +export function getExcludeUsers(query) { + return request({ + url: '/system/userRole/getExcludeUsers', + method: 'get', + params: query, + }) +} + +// export default { getRoleUsers, getExcludeUsers } diff --git a/src/api/tool/file.js b/src/api/tool/file.js new file mode 100644 index 0000000..7b9ea40 --- /dev/null +++ b/src/api/tool/file.js @@ -0,0 +1,68 @@ +import request from '@/utils/request' + +/** + * 文件存储分页查询 + * @param {查询条件} data + */ +export function listSysfile(query) { + return request({ + url: 'tool/file/list', + method: 'get', + params: query + }) +} + +/** + * 新增文件存储 + * @param data + */ +export function addSysfile(data) { + return request({ + url: 'tool/file', + method: 'post', + data: data + }) +} + +/** + * 修改文件存储 + * @param data + */ +export function updateSysfile(data) { + return request({ + url: 'tool/file', + method: 'PUT', + data: data + }) +} + +/** + * 获取文件存储详情 + * @param {Id} + */ +export function getSysfile(id) { + return request({ + url: 'tool/file/' + id, + method: 'get' + }) +} + +/** + * 删除文件存储 + * @param {主键} pid + */ +export function delSysfile(pid) { + return request({ + url: 'tool/file/' + pid, + method: 'delete' + }) +} + +// 导出文件存储 +export function exportSysfile(query) { + return request({ + url: 'tool/file/export', + method: 'get', + params: query + }) +} diff --git a/src/api/tool/gen.js b/src/api/tool/gen.js new file mode 100644 index 0000000..21d6e3c --- /dev/null +++ b/src/api/tool/gen.js @@ -0,0 +1,103 @@ +import request from '@/utils/request' + +/** + * 获取数据库 + */ +export function codeGetDBList() { + return request({ + url: 'tool/gen/getDbList', + method: 'get' + }) +} +/** + * 获取数据库表 + */ +export function listDbTable(data) { + return request({ + url: 'tool/gen/getTableList', + method: 'get', + params: data + }) +} +/** + * 生成代码 + */ +export async function codeGenerator(data) { + return await request({ + url: 'tool/gen/genCode', + method: 'POST', + data: data + }) +} + +/** + * 获取表格列信息 + * @param {*} data + * @returns + */ +export function queryColumnInfo(tableId) { + return request({ + url: 'tool/gen/Column/' + tableId, + method: 'GET' + }) +} + +// 查询生成表数据 +export function listTable(params) { + return request({ + url: 'tool/gen/list', + method: 'get', + params: params + }) +} + +// 查询表详细信息 +export function getGenTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'get' + }) +} + +// 导入表 +export function importTable(data) { + return request({ + url: '/tool/gen/importTable', + method: 'post', + data: data + }) +} +// 删除表数据 +export function delTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'delete' + }) +} + +// 修改代码生成表信息 +export function updateGenTable(data) { + return request({ + url: '/tool/gen/', + method: 'put', + data: data + }) +} + +// 预览生成代码 +export function previewTable(tableId, data) { + return request({ + url: '/tool/gen/preview/' + tableId, + method: 'post', + params: data + }) +} + +// 同步数据库 +export function synchDb(tableId, data) { + return request({ + url: '/tool/gen/synchDb/' + tableId, + method: 'get', + params: data + }) +} diff --git a/src/assets/401_images/401.gif b/src/assets/401_images/401.gif new file mode 100644 index 0000000..cd6e0d9 Binary files /dev/null and b/src/assets/401_images/401.gif differ diff --git a/src/assets/404_images/404.png b/src/assets/404_images/404.png new file mode 100644 index 0000000..3d8e230 Binary files /dev/null and b/src/assets/404_images/404.png differ diff --git a/src/assets/404_images/404_cloud.png b/src/assets/404_images/404_cloud.png new file mode 100644 index 0000000..c6281d0 Binary files /dev/null and b/src/assets/404_images/404_cloud.png differ diff --git a/src/assets/iconfont/iconfont.css b/src/assets/iconfont/iconfont.css new file mode 100644 index 0000000..d4d53d8 --- /dev/null +++ b/src/assets/iconfont/iconfont.css @@ -0,0 +1,399 @@ +@font-face { + font-family: "iconfont"; /* Project id 4017520 */ + src: url('iconfont.woff2?t=1695878634619') format('woff2'), + url('iconfont.woff?t=1695878634619') format('woff'), + url('iconfont.ttf?t=1695878634619') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-exit-fullscreen:before { + content: "\e66d"; +} + +.icon-validCode:before { + content: "\e621"; +} + +.icon-index:before { + content: "\e61f"; +} + +.icon-tree-table:before { + content: "\e637"; +} + +.icon-unlock:before { + content: "\e654"; +} + +.icon-zujian:before { + content: "\e655"; +} + +.icon-theme:before { + content: "\e659"; +} + +.icon-swagger:before { + content: "\e65c"; +} + +.icon-star:before { + content: "\e661"; +} + +.icon-time:before { + content: "\e662"; +} + +.icon-upload:before { + content: "\e663"; +} + +.icon-weixin:before { + content: "\e664"; +} + +.icon-system:before { + content: "\e667"; +} + +.icon-web:before { + content: "\e668"; +} + +.icon-tree:before { + content: "\e669"; +} + +.icon-user:before { + content: "\e66a"; +} + +.icon-tool:before { + content: "\e66b"; +} + +.icon-zip:before { + content: "\e66c"; +} + +.icon-link:before { + content: "\e636"; +} + +.icon-list:before { + content: "\e638"; +} + +.icon-international:before { + content: "\e639"; +} + +.icon-language:before { + content: "\e63a"; +} + +.icon-ipvisits:before { + content: "\e63c"; +} + +.icon-money:before { + content: "\e63d"; +} + +.icon-message:before { + content: "\e63e"; +} + +.icon-login:before { + content: "\e63f"; +} + +.icon-lock:before { + content: "\e640"; +} + +.icon-menu:before { + content: "\e641"; +} + +.icon-log:before { + content: "\e643"; +} + +.icon-logininfor:before { + content: "\e644"; +} + +.icon-mnt:before { + content: "\e645"; +} + +.icon-password:before { + content: "\e646"; +} + +.icon-peoples:before { + content: "\e647"; +} + +.icon-post:before { + content: "\e648"; +} + +.icon-permission:before { + content: "\e649"; +} + +.icon-phone:before { + content: "\e64a"; +} + +.icon-people:before { + content: "\e64b"; +} + +.icon-online:before { + content: "\e64d"; +} + +.icon-pdf:before { + content: "\e64f"; +} + +.icon-redis:before { + content: "\e650"; +} + +.icon-size:before { + content: "\e651"; +} + +.icon-search:before { + content: "\e652"; +} + +.icon-server:before { + content: "\e653"; +} + +.icon-select:before { + content: "\e656"; +} + +.icon-question:before { + content: "\e657"; +} + +.icon-rate:before { + content: "\e658"; +} + +.icon-monitor:before { + content: "\e65a"; +} + +.icon-source:before { + content: "\e65b"; +} + +.icon-role:before { + content: "\e65d"; +} + +.icon-shopping:before { + content: "\e65e"; +} + +.icon-skill:before { + content: "\e65f"; +} + +.icon-number:before { + content: "\e660"; +} + +.icon-a-404:before { + content: "\e622"; +} + +.icon-email:before { + content: "\e623"; +} + +.icon-example:before { + content: "\e624"; +} + +.icon-error:before { + content: "\e625"; +} + +.icon-excel:before { + content: "\e626"; +} + +.icon-education:before { + content: "\e627"; +} + +.icon-eye-open:before { + content: "\e628"; +} + +.icon-eye:before { + content: "\e629"; +} + +.icon-github:before { + content: "\e62b"; +} + +.icon-guide:before { + content: "\e62c"; +} + +.icon-gonggao:before { + content: "\e62d"; +} + +.icon-icon1:before { + content: "\e62e"; +} + +.icon-fullscreen:before { + content: "\e62f"; +} + +.icon-icon:before { + content: "\e630"; +} + +.icon-image:before { + content: "\e631"; +} + +.icon-form:before { + content: "\e632"; +} + +.icon-job:before { + content: "\e635"; +} + +.icon-cascader:before { + content: "\e603"; +} + +.icon-alipay:before { + content: "\e604"; +} + +.icon-anq:before { + content: "\e605"; +} + +.icon-backup:before { + content: "\e606"; +} + +.icon-bug:before { + content: "\e607"; +} + +.icon-button:before { + content: "\e609"; +} + +.icon-chain:before { + content: "\e60b"; +} + +.icon-chart:before { + content: "\e60c"; +} + +.icon-checkbox:before { + content: "\e60d"; +} + +.icon-clipboard:before { + content: "\e60e"; +} + +.icon-codeConsole:before { + content: "\e60f"; +} + +.icon-code:before { + content: "\e610"; +} + +.icon-color:before { + content: "\e611"; +} + +.icon-database:before { + content: "\e612"; +} + +.icon-component:before { + content: "\e613"; +} + +.icon-dashboard:before { + content: "\e614"; +} + +.icon-date:before { + content: "\e615"; +} + +.icon-deploy:before { + content: "\e616"; +} + +.icon-develop:before { + content: "\e617"; +} + +.icon-dept:before { + content: "\e619"; +} + +.icon-dictionary:before { + content: "\e61a"; +} + +.icon-documentation:before { + content: "\e61b"; +} + +.icon-doc:before { + content: "\e61c"; +} + +.icon-download:before { + content: "\e61d"; +} + +.icon-dict:before { + content: "\e61e"; +} + +.icon-edit:before { + content: "\e620"; +} + +.icon-app:before { + content: "\e602"; +} + diff --git a/src/assets/iconfont/iconfont.js b/src/assets/iconfont/iconfont.js new file mode 100644 index 0000000..ebeadac --- /dev/null +++ b/src/assets/iconfont/iconfont.js @@ -0,0 +1 @@ +window._iconfont_svg_string_4017520='',function(a){var c=(c=document.getElementsByTagName("script"))[c.length-1],h=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var l,v,o,t,m,i=function(c,h){h.parentNode.insertBefore(c,h)};if(h&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}l=function(){var c,h=document.createElement("div");h.innerHTML=a._iconfont_svg_string_4017520,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(c=document.body).firstChild?i(h,c.firstChild):c.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),l()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(o=l,t=a.document,m=!1,s(),t.onreadystatechange=function(){"complete"==t.readyState&&(t.onreadystatechange=null,z())})}function z(){m||(m=!0,o())}function s(){try{t.documentElement.doScroll("left")}catch(c){return void setTimeout(s,50)}z()}}(window); \ No newline at end of file diff --git a/src/assets/iconfont/iconfont.json b/src/assets/iconfont/iconfont.json new file mode 100644 index 0000000..471c549 --- /dev/null +++ b/src/assets/iconfont/iconfont.json @@ -0,0 +1,681 @@ +{ + "id": "4017520", + "name": "admin", + "font_family": "iconfont", + "css_prefix_text": "icon-", + "description": "", + "glyphs": [ + { + "icon_id": "37140510", + "name": "exit-fullscreen", + "font_class": "exit-fullscreen", + "unicode": "e66d", + "unicode_decimal": 58989 + }, + { + "icon_id": "37139279", + "name": "validCode", + "font_class": "validCode", + "unicode": "e621", + "unicode_decimal": 58913 + }, + { + "icon_id": "35896169", + "name": "index", + "font_class": "index", + "unicode": "e61f", + "unicode_decimal": 58911 + }, + { + "icon_id": "35076965", + "name": "tree-table", + "font_class": "tree-table", + "unicode": "e637", + "unicode_decimal": 58935 + }, + { + "icon_id": "35076967", + "name": "unlock", + "font_class": "unlock", + "unicode": "e654", + "unicode_decimal": 58964 + }, + { + "icon_id": "35076968", + "name": "zujian", + "font_class": "zujian", + "unicode": "e655", + "unicode_decimal": 58965 + }, + { + "icon_id": "35076969", + "name": "theme", + "font_class": "theme", + "unicode": "e659", + "unicode_decimal": 58969 + }, + { + "icon_id": "35076970", + "name": "swagger", + "font_class": "swagger", + "unicode": "e65c", + "unicode_decimal": 58972 + }, + { + "icon_id": "35076971", + "name": "star", + "font_class": "star", + "unicode": "e661", + "unicode_decimal": 58977 + }, + { + "icon_id": "35076972", + "name": "time", + "font_class": "time", + "unicode": "e662", + "unicode_decimal": 58978 + }, + { + "icon_id": "35076973", + "name": "upload", + "font_class": "upload", + "unicode": "e663", + "unicode_decimal": 58979 + }, + { + "icon_id": "35076974", + "name": "weixin", + "font_class": "weixin", + "unicode": "e664", + "unicode_decimal": 58980 + }, + { + "icon_id": "35076977", + "name": "system", + "font_class": "system", + "unicode": "e667", + "unicode_decimal": 58983 + }, + { + "icon_id": "35076979", + "name": "web", + "font_class": "web", + "unicode": "e668", + "unicode_decimal": 58984 + }, + { + "icon_id": "35076980", + "name": "tree", + "font_class": "tree", + "unicode": "e669", + "unicode_decimal": 58985 + }, + { + "icon_id": "35076981", + "name": "user", + "font_class": "user", + "unicode": "e66a", + "unicode_decimal": 58986 + }, + { + "icon_id": "35076982", + "name": "tool", + "font_class": "tool", + "unicode": "e66b", + "unicode_decimal": 58987 + }, + { + "icon_id": "35076986", + "name": "zip", + "font_class": "zip", + "unicode": "e66c", + "unicode_decimal": 58988 + }, + { + "icon_id": "35076492", + "name": "link", + "font_class": "link", + "unicode": "e636", + "unicode_decimal": 58934 + }, + { + "icon_id": "35076494", + "name": "list", + "font_class": "list", + "unicode": "e638", + "unicode_decimal": 58936 + }, + { + "icon_id": "35076495", + "name": "international", + "font_class": "international", + "unicode": "e639", + "unicode_decimal": 58937 + }, + { + "icon_id": "35076496", + "name": "language", + "font_class": "language", + "unicode": "e63a", + "unicode_decimal": 58938 + }, + { + "icon_id": "35076498", + "name": "ipvisits", + "font_class": "ipvisits", + "unicode": "e63c", + "unicode_decimal": 58940 + }, + { + "icon_id": "35076499", + "name": "money", + "font_class": "money", + "unicode": "e63d", + "unicode_decimal": 58941 + }, + { + "icon_id": "35076500", + "name": "message", + "font_class": "message", + "unicode": "e63e", + "unicode_decimal": 58942 + }, + { + "icon_id": "35076501", + "name": "login", + "font_class": "login", + "unicode": "e63f", + "unicode_decimal": 58943 + }, + { + "icon_id": "35076502", + "name": "lock", + "font_class": "lock", + "unicode": "e640", + "unicode_decimal": 58944 + }, + { + "icon_id": "35076503", + "name": "menu", + "font_class": "menu", + "unicode": "e641", + "unicode_decimal": 58945 + }, + { + "icon_id": "35076505", + "name": "log", + "font_class": "log", + "unicode": "e643", + "unicode_decimal": 58947 + }, + { + "icon_id": "35076506", + "name": "logininfor", + "font_class": "logininfor", + "unicode": "e644", + "unicode_decimal": 58948 + }, + { + "icon_id": "35076507", + "name": "mnt", + "font_class": "mnt", + "unicode": "e645", + "unicode_decimal": 58949 + }, + { + "icon_id": "35076509", + "name": "password", + "font_class": "password", + "unicode": "e646", + "unicode_decimal": 58950 + }, + { + "icon_id": "35076510", + "name": "peoples", + "font_class": "peoples", + "unicode": "e647", + "unicode_decimal": 58951 + }, + { + "icon_id": "35076511", + "name": "post", + "font_class": "post", + "unicode": "e648", + "unicode_decimal": 58952 + }, + { + "icon_id": "35076512", + "name": "permission", + "font_class": "permission", + "unicode": "e649", + "unicode_decimal": 58953 + }, + { + "icon_id": "35076513", + "name": "phone", + "font_class": "phone", + "unicode": "e64a", + "unicode_decimal": 58954 + }, + { + "icon_id": "35076514", + "name": "people", + "font_class": "people", + "unicode": "e64b", + "unicode_decimal": 58955 + }, + { + "icon_id": "35076516", + "name": "online", + "font_class": "online", + "unicode": "e64d", + "unicode_decimal": 58957 + }, + { + "icon_id": "35076518", + "name": "pdf", + "font_class": "pdf", + "unicode": "e64f", + "unicode_decimal": 58959 + }, + { + "icon_id": "35076519", + "name": "redis", + "font_class": "redis", + "unicode": "e650", + "unicode_decimal": 58960 + }, + { + "icon_id": "35076520", + "name": "size", + "font_class": "size", + "unicode": "e651", + "unicode_decimal": 58961 + }, + { + "icon_id": "35076521", + "name": "search", + "font_class": "search", + "unicode": "e652", + "unicode_decimal": 58962 + }, + { + "icon_id": "35076522", + "name": "server", + "font_class": "server", + "unicode": "e653", + "unicode_decimal": 58963 + }, + { + "icon_id": "35076525", + "name": "select", + "font_class": "select", + "unicode": "e656", + "unicode_decimal": 58966 + }, + { + "icon_id": "35076526", + "name": "question", + "font_class": "question", + "unicode": "e657", + "unicode_decimal": 58967 + }, + { + "icon_id": "35076527", + "name": "rate", + "font_class": "rate", + "unicode": "e658", + "unicode_decimal": 58968 + }, + { + "icon_id": "35076529", + "name": "monitor", + "font_class": "monitor", + "unicode": "e65a", + "unicode_decimal": 58970 + }, + { + "icon_id": "35076530", + "name": "source", + "font_class": "source", + "unicode": "e65b", + "unicode_decimal": 58971 + }, + { + "icon_id": "35076532", + "name": "role", + "font_class": "role", + "unicode": "e65d", + "unicode_decimal": 58973 + }, + { + "icon_id": "35076533", + "name": "shopping", + "font_class": "shopping", + "unicode": "e65e", + "unicode_decimal": 58974 + }, + { + "icon_id": "35076534", + "name": "skill", + "font_class": "skill", + "unicode": "e65f", + "unicode_decimal": 58975 + }, + { + "icon_id": "35076535", + "name": "number", + "font_class": "number", + "unicode": "e660", + "unicode_decimal": 58976 + }, + { + "icon_id": "35076366", + "name": "404", + "font_class": "a-404", + "unicode": "e622", + "unicode_decimal": 58914 + }, + { + "icon_id": "35076470", + "name": "email", + "font_class": "email", + "unicode": "e623", + "unicode_decimal": 58915 + }, + { + "icon_id": "35076471", + "name": "example", + "font_class": "example", + "unicode": "e624", + "unicode_decimal": 58916 + }, + { + "icon_id": "35076472", + "name": "error", + "font_class": "error", + "unicode": "e625", + "unicode_decimal": 58917 + }, + { + "icon_id": "35076473", + "name": "excel", + "font_class": "excel", + "unicode": "e626", + "unicode_decimal": 58918 + }, + { + "icon_id": "35076474", + "name": "education", + "font_class": "education", + "unicode": "e627", + "unicode_decimal": 58919 + }, + { + "icon_id": "35076475", + "name": "eye-open", + "font_class": "eye-open", + "unicode": "e628", + "unicode_decimal": 58920 + }, + { + "icon_id": "35076476", + "name": "eye", + "font_class": "eye", + "unicode": "e629", + "unicode_decimal": 58921 + }, + { + "icon_id": "35076480", + "name": "github", + "font_class": "github", + "unicode": "e62b", + "unicode_decimal": 58923 + }, + { + "icon_id": "35076481", + "name": "guide", + "font_class": "guide", + "unicode": "e62c", + "unicode_decimal": 58924 + }, + { + "icon_id": "35076482", + "name": "gonggao", + "font_class": "gonggao", + "unicode": "e62d", + "unicode_decimal": 58925 + }, + { + "icon_id": "35076483", + "name": "icon1", + "font_class": "icon1", + "unicode": "e62e", + "unicode_decimal": 58926 + }, + { + "icon_id": "35076484", + "name": "fullscreen", + "font_class": "fullscreen", + "unicode": "e62f", + "unicode_decimal": 58927 + }, + { + "icon_id": "35076485", + "name": "icon", + "font_class": "icon", + "unicode": "e630", + "unicode_decimal": 58928 + }, + { + "icon_id": "35076486", + "name": "image", + "font_class": "image", + "unicode": "e631", + "unicode_decimal": 58929 + }, + { + "icon_id": "35076487", + "name": "form", + "font_class": "form", + "unicode": "e632", + "unicode_decimal": 58930 + }, + { + "icon_id": "35076491", + "name": "job", + "font_class": "job", + "unicode": "e635", + "unicode_decimal": 58933 + }, + { + "icon_id": "35076284", + "name": "cascader", + "font_class": "cascader", + "unicode": "e603", + "unicode_decimal": 58883 + }, + { + "icon_id": "35076315", + "name": "alipay", + "font_class": "alipay", + "unicode": "e604", + "unicode_decimal": 58884 + }, + { + "icon_id": "35076316", + "name": "anq", + "font_class": "anq", + "unicode": "e605", + "unicode_decimal": 58885 + }, + { + "icon_id": "35076317", + "name": "backup", + "font_class": "backup", + "unicode": "e606", + "unicode_decimal": 58886 + }, + { + "icon_id": "35076318", + "name": "bug", + "font_class": "bug", + "unicode": "e607", + "unicode_decimal": 58887 + }, + { + "icon_id": "35076321", + "name": "button", + "font_class": "button", + "unicode": "e609", + "unicode_decimal": 58889 + }, + { + "icon_id": "35076323", + "name": "chain", + "font_class": "chain", + "unicode": "e60b", + "unicode_decimal": 58891 + }, + { + "icon_id": "35076324", + "name": "chart", + "font_class": "chart", + "unicode": "e60c", + "unicode_decimal": 58892 + }, + { + "icon_id": "35076325", + "name": "checkbox", + "font_class": "checkbox", + "unicode": "e60d", + "unicode_decimal": 58893 + }, + { + "icon_id": "35076326", + "name": "clipboard", + "font_class": "clipboard", + "unicode": "e60e", + "unicode_decimal": 58894 + }, + { + "icon_id": "35076327", + "name": "codeConsole", + "font_class": "codeConsole", + "unicode": "e60f", + "unicode_decimal": 58895 + }, + { + "icon_id": "35076328", + "name": "code", + "font_class": "code", + "unicode": "e610", + "unicode_decimal": 58896 + }, + { + "icon_id": "35076329", + "name": "color", + "font_class": "color", + "unicode": "e611", + "unicode_decimal": 58897 + }, + { + "icon_id": "35076330", + "name": "database", + "font_class": "database", + "unicode": "e612", + "unicode_decimal": 58898 + }, + { + "icon_id": "35076331", + "name": "component", + "font_class": "component", + "unicode": "e613", + "unicode_decimal": 58899 + }, + { + "icon_id": "35076332", + "name": "dashboard", + "font_class": "dashboard", + "unicode": "e614", + "unicode_decimal": 58900 + }, + { + "icon_id": "35076333", + "name": "date", + "font_class": "date", + "unicode": "e615", + "unicode_decimal": 58901 + }, + { + "icon_id": "35076334", + "name": "deploy", + "font_class": "deploy", + "unicode": "e616", + "unicode_decimal": 58902 + }, + { + "icon_id": "35076335", + "name": "develop", + "font_class": "develop", + "unicode": "e617", + "unicode_decimal": 58903 + }, + { + "icon_id": "35076337", + "name": "dept", + "font_class": "dept", + "unicode": "e619", + "unicode_decimal": 58905 + }, + { + "icon_id": "35076340", + "name": "dictionary", + "font_class": "dictionary", + "unicode": "e61a", + "unicode_decimal": 58906 + }, + { + "icon_id": "35076341", + "name": "documentation", + "font_class": "documentation", + "unicode": "e61b", + "unicode_decimal": 58907 + }, + { + "icon_id": "35076342", + "name": "doc", + "font_class": "doc", + "unicode": "e61c", + "unicode_decimal": 58908 + }, + { + "icon_id": "35076343", + "name": "download", + "font_class": "download", + "unicode": "e61d", + "unicode_decimal": 58909 + }, + { + "icon_id": "35076344", + "name": "dict", + "font_class": "dict", + "unicode": "e61e", + "unicode_decimal": 58910 + }, + { + "icon_id": "35076351", + "name": "edit", + "font_class": "edit", + "unicode": "e620", + "unicode_decimal": 58912 + }, + { + "icon_id": "35075963", + "name": "app", + "font_class": "app", + "unicode": "e602", + "unicode_decimal": 58882 + } + ] +} diff --git a/src/assets/iconfont/iconfont.ttf b/src/assets/iconfont/iconfont.ttf new file mode 100644 index 0000000..9d4af45 Binary files /dev/null and b/src/assets/iconfont/iconfont.ttf differ diff --git a/src/assets/iconfont/iconfont.woff b/src/assets/iconfont/iconfont.woff new file mode 100644 index 0000000..ceb56d3 Binary files /dev/null and b/src/assets/iconfont/iconfont.woff differ diff --git a/src/assets/iconfont/iconfont.woff2 b/src/assets/iconfont/iconfont.woff2 new file mode 100644 index 0000000..85f6f66 Binary files /dev/null and b/src/assets/iconfont/iconfont.woff2 differ diff --git a/src/assets/icons/svg/build.svg b/src/assets/icons/svg/build.svg new file mode 100644 index 0000000..97c4688 --- /dev/null +++ b/src/assets/icons/svg/build.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/emailLog.svg b/src/assets/icons/svg/emailLog.svg new file mode 100644 index 0000000..5cb5987 --- /dev/null +++ b/src/assets/icons/svg/emailLog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/emailSend.svg b/src/assets/icons/svg/emailSend.svg new file mode 100644 index 0000000..41155d3 --- /dev/null +++ b/src/assets/icons/svg/emailSend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/gitee.svg b/src/assets/icons/svg/gitee.svg new file mode 100644 index 0000000..e2ffd2e --- /dev/null +++ b/src/assets/icons/svg/gitee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/gonggao.svg b/src/assets/icons/svg/gonggao.svg new file mode 100644 index 0000000..cfd00f7 --- /dev/null +++ b/src/assets/icons/svg/gonggao.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/new.svg b/src/assets/icons/svg/new.svg new file mode 100644 index 0000000..8d49665 --- /dev/null +++ b/src/assets/icons/svg/new.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/pc.svg b/src/assets/icons/svg/pc.svg new file mode 100644 index 0000000..cbcabe7 --- /dev/null +++ b/src/assets/icons/svg/pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/qr.svg b/src/assets/icons/svg/qr.svg new file mode 100644 index 0000000..4e50218 --- /dev/null +++ b/src/assets/icons/svg/qr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/charts/center-inner1.png b/src/assets/images/charts/center-inner1.png new file mode 100644 index 0000000..421d90d Binary files /dev/null and b/src/assets/images/charts/center-inner1.png differ diff --git a/src/assets/images/charts/charts-bg.png b/src/assets/images/charts/charts-bg.png new file mode 100644 index 0000000..1b42a58 Binary files /dev/null and b/src/assets/images/charts/charts-bg.png differ diff --git a/src/assets/images/charts/circle-bg.png b/src/assets/images/charts/circle-bg.png new file mode 100644 index 0000000..25d9f77 Binary files /dev/null and b/src/assets/images/charts/circle-bg.png differ diff --git a/src/assets/images/charts/header-bg.png b/src/assets/images/charts/header-bg.png new file mode 100644 index 0000000..7ae3251 Binary files /dev/null and b/src/assets/images/charts/header-bg.png differ diff --git a/src/assets/images/profile.jpg b/src/assets/images/profile.jpg new file mode 100644 index 0000000..997732a Binary files /dev/null and b/src/assets/images/profile.jpg differ diff --git a/src/assets/images/qrcode.jpg b/src/assets/images/qrcode.jpg new file mode 100644 index 0000000..3261850 Binary files /dev/null and b/src/assets/images/qrcode.jpg differ diff --git a/src/assets/images/qrcodeH5.png b/src/assets/images/qrcodeH5.png new file mode 100644 index 0000000..95d60c4 Binary files /dev/null and b/src/assets/images/qrcodeH5.png differ diff --git a/src/assets/images/reward.jpg b/src/assets/images/reward.jpg new file mode 100644 index 0000000..68fe0d3 Binary files /dev/null and b/src/assets/images/reward.jpg differ diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png new file mode 100644 index 0000000..9838306 Binary files /dev/null and b/src/assets/logo/logo.png differ diff --git a/src/assets/styles/btn.scss b/src/assets/styles/btn.scss new file mode 100644 index 0000000..742ba77 --- /dev/null +++ b/src/assets/styles/btn.scss @@ -0,0 +1,99 @@ +@use './variables.module.scss'; + +@mixin colorBtn($color) { + background: $color; + + &:hover { + color: $color; + + &:before, + &:after { + background: $color; + } + } +} + +.blue-btn { + @include colorBtn(variables.$blue); +} + +.light-blue-btn { + @include colorBtn(variables.$light-blue); +} + +.red-btn { + @include colorBtn(variables.$red); +} + +.pink-btn { + @include colorBtn(variables.$pink); +} + +.green-btn { + @include colorBtn(variables.$green); +} + +.tiffany-btn { + @include colorBtn(variables.$tiffany); +} + +.yellow-btn { + @include colorBtn(variables.$yellow); +} + +.pan-btn { + font-size: 14px; + color: #fff; + padding: 14px 36px; + border-radius: 8px; + border: none; + outline: none; + transition: 600ms ease all; + position: relative; + display: inline-block; + + &:hover { + background: #fff; + + &:before, + &:after { + width: 100%; + transition: 600ms ease all; + } + } + + &:before, + &:after { + content: ''; + position: absolute; + top: 0; + right: 0; + height: 2px; + width: 0; + transition: 400ms ease all; + } + + &::after { + right: inherit; + top: inherit; + left: 0; + bottom: 0; + } +} + +.custom-button { + display: inline-block; + line-height: 1; + white-space: nowrap; + cursor: pointer; + background: #fff; + color: #fff; + -webkit-appearance: none; + text-align: center; + box-sizing: border-box; + outline: 0; + margin: 0; + padding: 10px 15px; + font-size: 14px; + border-radius: 4px; +} diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss new file mode 100644 index 0000000..f3926de --- /dev/null +++ b/src/assets/styles/element-ui.scss @@ -0,0 +1,175 @@ +// cover some element-ui styles + +.el-upload__input { + display: none; +} + +.cell { + .el-tag { + margin-right: 0px; + } +} + +// table 里面操作按钮样式覆盖 +.el-table__cell .cell { + .el-button.is-text { + padding: 8px 5px; + } +} + +.status-col { + .cell { + padding: 0 10px; + text-align: center; + + .el-tag { + margin-right: 0px; + } + } +} +// fix 2.2.0 版本label标签不居中 +// .el-form-item--small .el-form-item__label { +// line-height: 32px !important; +// } + +// element ui 移动端组件适配 +.el-icon { + vertical-align: middle; +} + +.el-header { + --el-header-padding: 0 0px !important; + // --el-header-height: 50px !important; +} +// el 2.2.0 text button +.el-button.is-text { + color: var(--el-color-primary) !important; +} +@media screen and (max-width: 500px) { + .el-message { + min-width: 300px !important; + } +} + +@media screen and (max-width: 500px) { + .el-message-box { + width: 300px !important; + } + + .el-pagination__jump { + display: none !important; + } + + .el-pagination__sizes { + display: none !important; + } +} + +// dialog +@media screen and (max-width: 700px) { + .el-dialog { + --el-dialog-width: 100% !important; + // --el-dialog-margin-top: 0 !important; + } + // .el-dialog:not(.is-fullscreen) { + // margin-top: 0 !important; + // } + .el-drawer { + width: 85% !important; + } +} + +/** 表格更多操作下拉样式 */ +.el-table .el-dropdown-link { + cursor: pointer; + color: #409eff; + margin-left: 5px; +} + +.el-table .el-dropdown, +.el-icon-arrow-down { + font-size: 12px; +} + +//适配完毕 + +// 隐藏picture-card 上传按钮 +.hide .el-upload--picture-card { + display: none; +} + +// 禁止菜单选中 +.el-sub-menu .el-sub-menu__title span, +.el-menu .el-menu-item { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +// fix 侧边栏二级导航缩小图标消失问题 +// .el-sub-menu__title { +// padding-right: unset !important; +// } + +// fix 顶部导航更多样式问题 +// .el-menu--horizontal .el-sub-menu .el-sub-menu__icon-arrow { +// right: calc(0px - var(--el-menu-base-level-padding)) !important; +// } + +// 弹出搜索框 +.header-search-select { + .el-select-dropdown__item { + height: unset !important; + line-height: unset !important; + margin-bottom: 5px; + display: flex; + align-items: center; + justify-content: space-between; + } +} + +// el-table 表头样式 +.el-table-header-cell { + text-align: center !important; +} + +.el-dialog__headerbtn { + width: 47px !important; +} + +// el-tree + +.tree-item-flex { + &.is-expanded .el-tree-node__children { + display: flex !important; + flex-direction: column; + flex-direction: row; + flex-wrap: wrap; + } +} + +// 修复饿了么 el-select没有宽度 +.el-select { + --el-select-width: 200px !important; +} + +// 按钮样式调整 +.el-button { + margin-left: unset !important; + margin-right: 12px; +} +.el-button:last-child { + margin-right: 0; +} +// 解决top布局一级菜单高度不整齐 +.topbar-menu .el-menu-item { + height: unset; + line-height: unset; +} +// 顶部导航宽度 +.nav3 { + .el-sub-menu__title { + --el-menu-base-level-padding: 5px; + } +} diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss new file mode 100644 index 0000000..230dd2c --- /dev/null +++ b/src/assets/styles/index.scss @@ -0,0 +1,283 @@ +@use './variables.module.scss'; +@use './mixin.scss'; +@use './transition.scss'; +@use './element-ui.scss'; +@use './sidebar.scss'; +@use './btn.scss'; +@use './waves.scss'; + +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(--base-bg-main); + // overflow: hidden; + position: relative; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +.no-padding { + padding: 0 !important; +} + +.padding-content { + padding: 4px 0; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.fr { + float: right; +} + +.fl { + float: left; +} + +.pr-5 { + padding-right: 5px; +} + +.pl-5 { + padding-left: 5px; +} + +.block { + display: block; +} + +.pointer { + cursor: pointer; +} + +.inlineBlock { + display: block; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: ' '; + clear: both; + height: 0; + } +} + +.text-center { + text-align: center; +} + +.link-type, +.link-type:focus { + color: var(--el-color-primary); + cursor: pointer; + + &:hover { + // color: rgb(32, 160, 255); + opacity: 0.3; + } +} + +/** 基础通用 **/ +.pt5 { + padding-top: 5px; +} + +.pr5 { + padding-right: 5px; +} + +.pb5 { + padding-bottom: 5px; +} +.pb20 { + padding-bottom: 20px; +} + +.mt5 { + margin-top: 5px; +} + +.mr5 { + margin-right: 5px; +} + +.mb5 { + margin-bottom: 5px; +} + +.mb8 { + margin-bottom: 8px; +} + +.ml5 { + margin-left: 5px; +} + +.mt10 { + margin-top: 10px; +} + +.mr10 { + margin-right: 10px; +} + +.mb10 { + margin-bottom: 10px; +} + +.ml10 { + margin-left: 10px; +} + +.mt20 { + margin-top: 20px; +} + +.mr20 { + margin-right: 20px; +} + +.mb20 { + margin-bottom: 20px; +} + +.ml20 { + margin-left: 20px; +} + +.ml { + margin-left: auto; +} + +.mr { + margin-right: auto; +} + +.mt { + margin-top: auto; +} + +.mb { + margin-bottom: auto; +} +.w20 { + width: 20%; +} +.w100 { + width: 100%; +} + +.pull-right { + float: right !important; +} + +/* text color */ +.text-navy { + color: #1ab394; +} +.text-pink { + color: pink; +} +.text-primary { + color: inherit; +} + +.text-success { + color: #1c84c6; +} + +.text-info { + color: #23c6c8; +} + +.text-warning { + color: #f8ac59; +} + +.text-danger { + color: #ff0000; +} + +.text-muted { + color: #888888; +} + +.text-orange { + color: #ff7d00; +} + +.text-hotpink { + color: hotpink; +} + +.text-green { + color: green; +} + +.text-greenyellow { + color: greenyellow; +} +.text-purple { + color: #ff00ff; +} + +/* image */ +.img-circle { + border-radius: 50%; +} + +.card-box { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 10px; +} + +.icon { + width: 100px; +} + +.table-td-thumb { + width: 56px; +} + +.flex-center { + flex-direction: column; + overflow: hidden; +} + +.hljs { + display: flex; + flex-wrap: wrap; + width: 100%; + border-radius: 5px; +} diff --git a/src/assets/styles/login.scss b/src/assets/styles/login.scss new file mode 100644 index 0000000..5208a57 --- /dev/null +++ b/src/assets/styles/login.scss @@ -0,0 +1,111 @@ +.login-wrap { + background: radial-gradient(220% 105% at top center, #1b2947 10%, #4b76a7 40%, #81acae 65%, #f7f7b6); + background-attachment: fixed; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + // background-image: url('@/assets/images/login-bg.jpg'); + background-size: cover; + flex-direction: column; + + .login { + margin: 0 auto; + background: #ffffff; + border-radius: 6px; + width: var(--base-login-width); + position: relative; + // height: 420px; + } +} + +.title { + margin: 10px auto 15px auto; + text-align: center; + // color: #fff; +} + +.login-form { + padding: 5px 25px 5px 25px; + position: relative; + height: 230px; + + .input-icon { + height: 30px; + width: 14px; + margin-left: 0px; + } +} + +.login-tip { + font-size: 13px; + text-align: center; + color: #bfbfbf; +} + +.login-code { + width: 33%; + height: 40px; + float: right; + + img { + width: 100%; + cursor: pointer; + vertical-align: middle; + } +} + +.el-login-footer { + height: 40px; + line-height: 40px; + position: fixed; + bottom: 0; + width: 100%; + text-align: center; + color: #fff; + font-family: Arial; + font-size: 12px; + letter-spacing: 1px; +} + +.login-code-img { + height: 40px; + padding-left: 12px; +} +.langSet { + position: absolute; + left: 20px; + top: 10px; +} + +.scan-wrap { + position: absolute; + right: 0; + top: 0; + width: 50px; + height: 50px; + cursor: pointer; + transition: all ease 0.3s; + overflow: hidden; + + .icon { + width: 48px; + height: 50px; + display: inline-block; + font-size: 48px; + position: absolute; + right: 1px; + top: 0px; + } + .scan-delta { + position: absolute; + width: 35px; + height: 70px; + z-index: 2; + top: 2px; + right: 21px; + background: var(--el-color-white); + transform: rotate(-45deg); + } +} diff --git a/src/assets/styles/mixin.scss b/src/assets/styles/mixin.scss new file mode 100644 index 0000000..06fa061 --- /dev/null +++ b/src/assets/styles/mixin.scss @@ -0,0 +1,66 @@ +@mixin clearfix { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin scrollBar { + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } +} + +@mixin relative { + position: relative; + width: 100%; + height: 100%; +} + +@mixin pct($pct) { + width: #{$pct}; + position: relative; + margin: 0 auto; +} + +@mixin triangle($width, $height, $color, $direction) { + $width: $width/2; + $color-border-style: $height solid $color; + $transparent-border-style: $width solid transparent; + height: 0; + width: 0; + + @if $direction==up { + border-bottom: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==right { + border-left: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } + + @else if $direction==down { + border-top: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==left { + border-right: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } +} diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss new file mode 100644 index 0000000..f205253 --- /dev/null +++ b/src/assets/styles/sidebar.scss @@ -0,0 +1,85 @@ +.el-menu-item, +.el-sub-menu { + .svg-icon + span { + margin-left: 5px; + } +} +#app { + .sidebar { + position: relative; + overflow-y: hidden; + z-index: 1001; + transition: width 0.28s ease; + background-color: var(--base-menu-background); + height: 100%; + display: flex; + flex-direction: column; + -webkit-box-shadow: 2px 0 14px rgb(0 21 41 / 10%); + box-shadow: 2px 0 14px rgb(0 21 41 / 10%); + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + // 去掉el-menu边框 + .el-menu { + border: none; + } + + // [class^='el-icon'] { + // width: 1em; + // height: 1em; + // font-size: unset; + // } + } + + // 展开sidebar状态设置svg-icon边距 + .openSidebar { + .sidebar { + transform: translate(0); + } + } + // 隐藏侧边栏样式 + .hideSidebar { + .el-aside { + --el-aside-width: 60px; + } + // 隐藏箭头 + .el-sub-menu { + overflow: hidden; + + & > .el-sub-menu__title { + .el-sub-menu__icon-arrow { + display: none; + } + } + } + + // 折叠状态下 + .el-menu--collapse { + .menu-icon { + margin-right: 0; + } + } + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar { + transition: transform 0.28s; + position: fixed; + // background: var(--base-menu-background, #fff); + } + + &.hideSidebar { + .sidebar { + pointer-events: none; + transform: translate3d(-220px, 0, 0); + transition-duration: 0.3s; + } + } + } +} diff --git a/src/assets/styles/transition.scss b/src/assets/styles/transition.scss new file mode 100644 index 0000000..4cb27cc --- /dev/null +++ b/src/assets/styles/transition.scss @@ -0,0 +1,48 @@ +// global transition css + +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/* fade-transform */ +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all .5s; +} + +.fade-transform-enter { + opacity: 0; + transform: translateX(-30px); +} + +.fade-transform-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* breadcrumb transition */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all .5s; +} + +.breadcrumb-enter, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} + +.breadcrumb-move { + transition: all .5s; +} + +.breadcrumb-leave-active { + position: absolute; +} diff --git a/src/assets/styles/variables.module.scss b/src/assets/styles/variables.module.scss new file mode 100644 index 0000000..7c8163d --- /dev/null +++ b/src/assets/styles/variables.module.scss @@ -0,0 +1,92 @@ +// base color +$blue: #324157; +$light-blue: #3a71a8; +$red: #c03639; +$pink: #e65d6e; +$green: #30b08f; +$tiffany: #4ab7bd; +$yellow: #fec171; +$panGreen: #30b08f; + +// 默认菜单主题风格 +:root { + --base-text-color-rgba: rgba(0, 0, 0, 0.85); + --base-menu-background: #fff; + --base-sidebar-width: 220px; + // 左侧菜单宽度 + --el-aside-width: 220px; + //底部高度 + --base-footer-height: 30px; + --base-tags-height: 34px; + --base-header-height: 50px; + //登录框宽度 + --base-login-width: 360px; + + // 侧边栏图标大小 + --el-menu-icon-width: 14px; + + --el-menu-horizontal-height: 50px; + + --vxe-table-column-padding-default: 7px 0 !important; +} + +/***侧边栏深色配置***/ +[data-theme='theme-black'] { + --base-menu-background: #324157; + --base-logo-title-color: #ffffff; + --base-topBar-background: #324157; + --base-topBar-color: #fff; + + // el-ement ui 设置 + // --el-fill-color-blank: #304156; + --el-text-color-primary: #e5eaf3; + --base-color-white: #ffffff; + --el-menu-text-color: var(--el-text-color-primary); +} +// 黑色主题 +html.dark { + /* custom dark bg color */ + // --el-bg-color: #141414; + --base-color-white: #ffffff; + --base-text-color-rgba: #ffffff; + --base-menu-background: #000; + --base-topBar-background: #000; + + // vxe-table黑色样式 + --vxe-font-color: #98989e; + --vxe-primary-color: #2c7ecf; + --vxe-icon-background-color: #98989e; + --vxe-table-font-color: #98989e; + --vxe-table-resizable-color: #95969a; + --vxe-table-header-background-color: #28282a; + --vxe-table-body-background-color: #151518; + --vxe-table-background-color: #4a5663; + --vxe-table-border-width: 1px; + --vxe-table-border-color: #37373a; + + .current-row { + color: #e65d6e; + } + + .header-search { + .el-select { + background-color: #000; + } + } + + // wangEditor + --w-e-textarea-bg-color: #111; + --w-e-textarea-color: #fff; + + --w-e-toolbar-color: #fff; + --w-e-toolbar-bg-color: #111; + --w-e-toolbar-active-color: #ccc; + --w-e-toolbar-active-bg-color: #111; + /* ...其他... */ +} +html.cafe { + filter: sepia(0.9) hue-rotate(315deg) brightness(0.9); +} +html.contrast { + filter: contrast(2); +} diff --git a/src/assets/styles/waves.scss b/src/assets/styles/waves.scss new file mode 100644 index 0000000..23add2c --- /dev/null +++ b/src/assets/styles/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/auto-import.d.ts b/src/auto-import.d.ts new file mode 100644 index 0000000..a606bd4 --- /dev/null +++ b/src/auto-import.d.ts @@ -0,0 +1,87 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'] + const computed: typeof import('vue')['computed'] + const createApp: typeof import('vue')['createApp'] + const createPinia: typeof import('pinia')['createPinia'] + const customRef: typeof import('vue')['customRef'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const defineStore: typeof import('pinia')['defineStore'] + const effectScope: typeof import('vue')['effectScope'] + const getActivePinia: typeof import('pinia')['getActivePinia'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const inject: typeof import('vue')['inject'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const mapActions: typeof import('pinia')['mapActions'] + const mapGetters: typeof import('pinia')['mapGetters'] + const mapState: typeof import('pinia')['mapState'] + const mapStores: typeof import('pinia')['mapStores'] + const mapWritableState: typeof import('pinia')['mapWritableState'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] + const provide: typeof import('vue')['provide'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const setActivePinia: typeof import('pinia')['setActivePinia'] + const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const storeToRefs: typeof import('pinia')['storeToRefs'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const unref: typeof import('vue')['unref'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useId: typeof import('vue')['useId'] + const useLink: typeof import('vue-router')['useLink'] + const useModel: typeof import('vue')['useModel'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useSlots: typeof import('vue')['useSlots'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} diff --git a/src/components.d.ts b/src/components.d.ts new file mode 100644 index 0000000..b7fb812 --- /dev/null +++ b/src/components.d.ts @@ -0,0 +1,19 @@ +import SvgIcon from '@/components/SvgIcon/index.vue' +import UploadImage from '@/components/ImageUpload.vue' +import UploadFile from '@/components/FileUpload' +import ImagePreview from '@/components/ImagePreview' +import DictTag from '@/components/DictTag' +import Dialog from '@/components/Dialog' +import MyTable from '@/components/MyTable' + +declare module '@vue/runtime-core' { + export interface GlobalComponents { + SvgIcon: typeof SvgIcon, + UploadImage: typeof UploadImage, + DictTag: typeof DictTag, + ImagePreview: typeof ImagePreview, + UploadFile: typeof UploadFile, + ZrDialog: typeof Dialog, + MyTable: typeof MyTable + } +} \ No newline at end of file diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue new file mode 100644 index 0000000..3d65f4a --- /dev/null +++ b/src/components/Breadcrumb/index.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/src/components/Crontab/day.vue b/src/components/Crontab/day.vue new file mode 100644 index 0000000..66882ec --- /dev/null +++ b/src/components/Crontab/day.vue @@ -0,0 +1,170 @@ + + + + diff --git a/src/components/Crontab/hour.vue b/src/components/Crontab/hour.vue new file mode 100644 index 0000000..6f6f533 --- /dev/null +++ b/src/components/Crontab/hour.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/src/components/Crontab/index.vue b/src/components/Crontab/index.vue new file mode 100644 index 0000000..f4c80f7 --- /dev/null +++ b/src/components/Crontab/index.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/src/components/Crontab/min.vue b/src/components/Crontab/min.vue new file mode 100644 index 0000000..4e2c129 --- /dev/null +++ b/src/components/Crontab/min.vue @@ -0,0 +1,126 @@ + + + + diff --git a/src/components/Crontab/month.vue b/src/components/Crontab/month.vue new file mode 100644 index 0000000..6d2e06f --- /dev/null +++ b/src/components/Crontab/month.vue @@ -0,0 +1,144 @@ + + + + + diff --git a/src/components/Crontab/result.vue b/src/components/Crontab/result.vue new file mode 100644 index 0000000..e3eb757 --- /dev/null +++ b/src/components/Crontab/result.vue @@ -0,0 +1,560 @@ + + + diff --git a/src/components/Crontab/second.vue b/src/components/Crontab/second.vue new file mode 100644 index 0000000..5cb3baf --- /dev/null +++ b/src/components/Crontab/second.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/src/components/Crontab/week.vue b/src/components/Crontab/week.vue new file mode 100644 index 0000000..d3d83da --- /dev/null +++ b/src/components/Crontab/week.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/components/Crontab/year.vue b/src/components/Crontab/year.vue new file mode 100644 index 0000000..5a02ee6 --- /dev/null +++ b/src/components/Crontab/year.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/components/Dialog/index.vue b/src/components/Dialog/index.vue new file mode 100644 index 0000000..ebde022 --- /dev/null +++ b/src/components/Dialog/index.vue @@ -0,0 +1,75 @@ + + + + diff --git a/src/components/DictTag/index.vue b/src/components/DictTag/index.vue new file mode 100644 index 0000000..c8a650c --- /dev/null +++ b/src/components/DictTag/index.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/components/Echarts/Gauge.vue b/src/components/Echarts/Gauge.vue new file mode 100644 index 0000000..25960e9 --- /dev/null +++ b/src/components/Echarts/Gauge.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue new file mode 100644 index 0000000..7d0c82f --- /dev/null +++ b/src/components/Editor/index.vue @@ -0,0 +1,128 @@ + + diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue new file mode 100644 index 0000000..872a3a3 --- /dev/null +++ b/src/components/FileUpload/index.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue new file mode 100644 index 0000000..01cb87f --- /dev/null +++ b/src/components/Hamburger/index.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue new file mode 100644 index 0000000..1a188ac --- /dev/null +++ b/src/components/HeaderSearch/index.vue @@ -0,0 +1,253 @@ + + + + + diff --git a/src/components/IconSelect/index.vue b/src/components/IconSelect/index.vue new file mode 100644 index 0000000..3eaadab --- /dev/null +++ b/src/components/IconSelect/index.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/src/components/IconSelect/requireIcons.js b/src/components/IconSelect/requireIcons.js new file mode 100644 index 0000000..8286a05 --- /dev/null +++ b/src/components/IconSelect/requireIcons.js @@ -0,0 +1,14 @@ +let icons = [] +const modules = import.meta.glob('./../../assets/icons/svg/*.svg') +for (const path in modules) { + const p = path.split('assets/icons/svg/')[1].split('.svg')[0] + icons.push(p) +} + +// iconfont +import iconList from '@/assets/iconfont/iconfont.json' + +iconList.glyphs.forEach((element) => { + icons.push(element.name) +}) +export default icons diff --git a/src/components/ImagePreview/index.vue b/src/components/ImagePreview/index.vue new file mode 100644 index 0000000..76a9656 --- /dev/null +++ b/src/components/ImagePreview/index.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue new file mode 100644 index 0000000..e988239 --- /dev/null +++ b/src/components/ImageUpload/index.vue @@ -0,0 +1,237 @@ + + + + diff --git a/src/components/ImportData/index.vue b/src/components/ImportData/index.vue new file mode 100644 index 0000000..97fa86c --- /dev/null +++ b/src/components/ImportData/index.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/components/InputTag/index.vue b/src/components/InputTag/index.vue new file mode 100644 index 0000000..2d06871 --- /dev/null +++ b/src/components/InputTag/index.vue @@ -0,0 +1,71 @@ + + diff --git a/src/components/LangSelect/index.vue b/src/components/LangSelect/index.vue new file mode 100644 index 0000000..27e9154 --- /dev/null +++ b/src/components/LangSelect/index.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/MyTable/index.vue b/src/components/MyTable/index.vue new file mode 100644 index 0000000..9484fca --- /dev/null +++ b/src/components/MyTable/index.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/components/Notice/Index.vue b/src/components/Notice/Index.vue new file mode 100644 index 0000000..e33d71a --- /dev/null +++ b/src/components/Notice/Index.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/src/components/Notice/noticeInfo.vue b/src/components/Notice/noticeInfo.vue new file mode 100644 index 0000000..f7d218f --- /dev/null +++ b/src/components/Notice/noticeInfo.vue @@ -0,0 +1,113 @@ + + + diff --git a/src/components/NoticeBar/index.vue b/src/components/NoticeBar/index.vue new file mode 100644 index 0000000..95cdb41 --- /dev/null +++ b/src/components/NoticeBar/index.vue @@ -0,0 +1,84 @@ + + + + diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue new file mode 100644 index 0000000..bc631d6 --- /dev/null +++ b/src/components/Pagination/index.vue @@ -0,0 +1,113 @@ + + + + diff --git a/src/components/ParentView/index.vue b/src/components/ParentView/index.vue new file mode 100644 index 0000000..7bf6148 --- /dev/null +++ b/src/components/ParentView/index.vue @@ -0,0 +1,3 @@ + diff --git a/src/components/RightToolbar/index.vue b/src/components/RightToolbar/index.vue new file mode 100644 index 0000000..b45f3b1 --- /dev/null +++ b/src/components/RightToolbar/index.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue new file mode 100644 index 0000000..73e95a2 --- /dev/null +++ b/src/components/Screenfull/index.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/components/SizeSelect/index.vue b/src/components/SizeSelect/index.vue new file mode 100644 index 0000000..9dbb53c --- /dev/null +++ b/src/components/SizeSelect/index.vue @@ -0,0 +1,38 @@ + + + + diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..64be8d9 --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/components/SvgIcon/svgicon.js b/src/components/SvgIcon/svgicon.js new file mode 100644 index 0000000..bb68b67 --- /dev/null +++ b/src/components/SvgIcon/svgicon.js @@ -0,0 +1,10 @@ +import * as components from '@element-plus/icons-vue' + +export default { + install: (app) => { + for (const key in components) { + const componentConfig = components[key]; + app.component(componentConfig.name, componentConfig); + } + }, +}; \ No newline at end of file diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue new file mode 100644 index 0000000..f406614 --- /dev/null +++ b/src/components/TopNav/index.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/src/components/Zr/Doc/index.vue b/src/components/Zr/Doc/index.vue new file mode 100644 index 0000000..b7c73d8 --- /dev/null +++ b/src/components/Zr/Doc/index.vue @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/src/components/Zr/Git/index.vue b/src/components/Zr/Git/index.vue new file mode 100644 index 0000000..de93bec --- /dev/null +++ b/src/components/Zr/Git/index.vue @@ -0,0 +1,20 @@ + + \ No newline at end of file diff --git a/src/components/iFrame/index.vue b/src/components/iFrame/index.vue new file mode 100644 index 0000000..091b1a2 --- /dev/null +++ b/src/components/iFrame/index.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue new file mode 100644 index 0000000..b2b6426 --- /dev/null +++ b/src/layout/components/Navbar.vue @@ -0,0 +1,216 @@ + + + + + diff --git a/src/layout/components/Settings/index.vue b/src/layout/components/Settings/index.vue new file mode 100644 index 0000000..e3a2e85 --- /dev/null +++ b/src/layout/components/Settings/index.vue @@ -0,0 +1,462 @@ + + + + + diff --git a/src/layout/components/Sidebar/Link.vue b/src/layout/components/Sidebar/Link.vue new file mode 100644 index 0000000..c7ce424 --- /dev/null +++ b/src/layout/components/Sidebar/Link.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue new file mode 100644 index 0000000..4833f36 --- /dev/null +++ b/src/layout/components/Sidebar/Logo.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue new file mode 100644 index 0000000..b9d6963 --- /dev/null +++ b/src/layout/components/Sidebar/SidebarItem.vue @@ -0,0 +1,123 @@ + + + diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue new file mode 100644 index 0000000..f43aeea --- /dev/null +++ b/src/layout/components/Sidebar/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..e925d07 --- /dev/null +++ b/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue new file mode 100644 index 0000000..cceaf02 --- /dev/null +++ b/src/layout/components/TagsView/index.vue @@ -0,0 +1,341 @@ + + + + + diff --git a/src/layout/components/TopBar/index.vue b/src/layout/components/TopBar/index.vue new file mode 100644 index 0000000..e7a96e5 --- /dev/null +++ b/src/layout/components/TopBar/index.vue @@ -0,0 +1,84 @@ + + + + diff --git a/src/layout/components/index.js b/src/layout/components/index.js new file mode 100644 index 0000000..422accd --- /dev/null +++ b/src/layout/components/index.js @@ -0,0 +1,4 @@ +// export { default as AppMain } from './AppMain' +export { default as Navbar } from './Navbar' +export { default as Settings } from './Settings' +export { default as TagsView } from './TagsView/index.vue' diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..b97bef7 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..8e7e535 --- /dev/null +++ b/src/main.js @@ -0,0 +1,78 @@ +import { createApp } from 'vue' +// import Cookies from 'js-cookie' + +import ElementPlus from 'element-plus' +import 'dayjs/locale/zh-cn' +import '@/assets/styles/index.scss' // global css + +import App from './App' +import router from './router' +import directive from './directive' // directive +import vxetb from './vxe-tb' +// 注册指令 +import plugins from './plugins' // plugins +import { downFile } from '@/utils/request' +import signalR from '@/signalr/signalr' +import vueI18n from './i18n/index' +import pinia from '@/store/index' + +// svg图标 +import '@/assets/iconfont/iconfont.js' //iconfont +import 'virtual:svg-icons-register' +import SvgIcon from '@/components/SvgIcon/index.vue' +import elementIcons from '@/components/SvgIcon/svgicon' + +import './permission' // permission control + +import { getConfigKey } from '@/api/system/config' +import { getDicts } from '@/api/system/dict/data' +import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, download } from '@/utils/ruoyi' + +// 分页组件 +import Pagination from '@/components/Pagination' +// 自定义表格工具组件 +import RightToolbar from '@/components/RightToolbar' +// 文件上传组件 +import FileUpload from '@/components/FileUpload' +// 图片上传组件 +import ImageUpload from '@/components/ImageUpload' +// 图片预览组件 +import ImagePreview from '@/components/ImagePreview' +// 字典标签组件 +import DictTag from '@/components/DictTag' +// el-date-picker 快捷选项 +import dateOptions from '@/utils/dateOptions' +// Dialog组件 +import Dialog from '@/components/Dialog' +// 自定义table +import MyTable from '@/components/MyTable' + +const app = createApp(App) +signalR.init(import.meta.env.VITE_APP_SOCKET_API) +app.config.globalProperties.signalr = signalR +// 全局方法挂载 +app.config.globalProperties.getConfigKey = getConfigKey +app.config.globalProperties.getDicts = getDicts +app.config.globalProperties.download = download +app.config.globalProperties.downFile = downFile +app.config.globalProperties.parseTime = parseTime +app.config.globalProperties.resetForm = resetForm +app.config.globalProperties.handleTree = handleTree +app.config.globalProperties.addDateRange = addDateRange +app.config.globalProperties.selectDictLabel = selectDictLabel +app.config.globalProperties.dateOptions = dateOptions + +// 全局组件挂载 +app.component('DictTag', DictTag) +app.component('Pagination', Pagination) +app.component('UploadFile', FileUpload) +app.component('UploadImage', ImageUpload) +app.component('ImagePreview', ImagePreview) +app.component('RightToolbar', RightToolbar) +app.component('svg-icon', SvgIcon) +app.component('ZrDialog', Dialog) +app.component('MyTable', MyTable) + +directive(app) +vxetb(app) +app.use(pinia).use(router).use(plugins).use(ElementPlus, {}).use(elementIcons).use(vueI18n).mount('#app') diff --git a/src/permission.js b/src/permission.js new file mode 100644 index 0000000..f54951d --- /dev/null +++ b/src/permission.js @@ -0,0 +1,73 @@ +import router from './router' +// import { ElMessage } from 'element-plus' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { getToken } from '@/utils/auth' +import { isHttp } from '@/utils/validate' +import useUserStore from '@/store/modules/user' +import useSettingsStore from '@/store/modules/settings' +import usePermissionStore from '@/store/modules/permission' +import { getQueryObject } from '@/utils/index' +NProgress.configure({ showSpinner: false }) + +const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/socialLogin', '/error'] + +router.beforeEach((to, from, next) => { + NProgress.start() + if (getToken()) { + to.meta.title && useSettingsStore().setTitle(to.meta.title) + /* has token*/ + if (to.path === '/login') { + next({ path: '/' }) + NProgress.done() + } else { + if (useUserStore().roles.length === 0) { + // 判断当前用户是否已拉取完user_info信息 + useUserStore() + .getInfo() + .then(() => { + usePermissionStore() + .generateRoutes() + .then((accessRoutes) => { + // 根据roles权限生成可访问的路由表 + accessRoutes.forEach((route) => { + if (!isHttp(route.path)) { + router.addRoute(route) // 动态添加可访问路由表 + } + }) + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 + }) + }) + .catch((err) => { + useUserStore() + .logOut() + .then(() => { + // ElMessage.error(err != undefined ? err : '登录失败') + next({ path: '/' }) + }) + }) + } else { + next() + } + } + } else { + // 没有token + if (whiteList.indexOf(to.path) !== -1) { + // 在免登录白名单,直接进入 + next() + } else { + var toPath = to.fullPath // /index?redirect=/demo + var obj = getQueryObject(to.fullPath) + + if (obj.redirect) { + toPath = obj.redirect + } + next(`/login?redirect=${encodeURIComponent(toPath)}`) // 否则全部重定向到登录页 + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() +}) diff --git a/src/plugins/auth.js b/src/plugins/auth.js new file mode 100644 index 0000000..1ec8c41 --- /dev/null +++ b/src/plugins/auth.js @@ -0,0 +1,60 @@ +import useUserStore from '@/store/modules/user' + +function authPermission(permission) { + const all_permission = "*:*:*"; + const permissions = useUserStore() && useUserStore().permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "admin"; + const roles = useUserStore().roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 验证用户是否具备某权限 + hasPermi(permission) { + return authPermission(permission); + }, + // 验证用户是否含有指定权限,只需包含其中一个 + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 验证用户是否含有指定权限,必须全部拥有 + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 验证用户是否具备某角色 + hasRole(role) { + return authRole(role); + }, + // 验证用户是否含有指定角色,只需包含其中一个 + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 验证用户是否含有指定角色,必须全部拥有 + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} \ No newline at end of file diff --git a/src/plugins/cache.js b/src/plugins/cache.js new file mode 100644 index 0000000..492170d --- /dev/null +++ b/src/plugins/cache.js @@ -0,0 +1,96 @@ +const sessionCache = { + set(key, value) { + if (!sessionStorage) { + return + } + if (key != null && value != null) { + sessionStorage.setItem(key, value) + } + }, + get(key) { + if (!sessionStorage) { + return null + } + if (key == null) { + return null + } + return sessionStorage.getItem(key) + }, + setJSON(key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON(key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove(key) { + sessionStorage.removeItem(key); + } +} +const localCache = { + set(key, value) { + if (!localStorage) { + return + } + if (key != null && value != null) { + localStorage.setItem(key, value) + } + }, + get(key) { + if (!localStorage) { + return null + } + if (key == null) { + return null + } + return localStorage.getItem(key) + }, + setJSON(key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON(key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove(key) { + localStorage.removeItem(key); + } +} +import Cookies from 'js-cookie' + +const cookie = { + set(key, data, expires) { + Cookies.set(key, data, { expires: expires }) + }, + set(key, data) { + Cookies.set(key, data) + }, + remove(key) { + Cookies.remove(key) + }, + get(key) { + Cookies.get(key) + } +} +export default { + /** + * 会话级缓存 + */ + session: sessionCache, + /** + * 本地缓存 + */ + local: localCache, + /** + * cookie存储 + */ + cookie: cookie +} \ No newline at end of file diff --git a/src/plugins/download.js b/src/plugins/download.js new file mode 100644 index 0000000..c31a064 --- /dev/null +++ b/src/plugins/download.js @@ -0,0 +1,72 @@ +import axios from 'axios' +import { ElMessage } from 'element-plus' +import { saveAs } from 'file-saver' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { blobValidate } from '@/utils/ruoyi' + +const baseURL = import.meta.env.VITE_APP_BASE_API + +export default { + name(name, isDelete = true) { + var url = baseURL + "/common/download?fileName=" + encodeURI(name) + "&delete=" + isDelete + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURI(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + resource(resource) { + var url = baseURL + "/common/download/resource?resource=" + encodeURI(resource); + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURI(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + zip(url, name) { + var url = baseURL + url + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data], { type: 'application/zip' }) + this.saveAs(blob, name) + } else { + this.printErrMsg(res.data); + } + }) + }, + saveAs(text, name, opts) { + saveAs(text, name, opts); + }, + async printErrMsg(data) { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + ElMessage.error(errMsg); + } +} + diff --git a/src/plugins/index.js b/src/plugins/index.js new file mode 100644 index 0000000..bc20928 --- /dev/null +++ b/src/plugins/index.js @@ -0,0 +1,27 @@ +import tab from './tab' +import auth from './auth' +import cache from './cache' +import modal from './modal' +import download from './download' + +export default function installPlugins(app) { + // 页签操作 + app.config.globalProperties.$tab = tab + // 认证对象 + app.config.globalProperties.$auth = auth + // 缓存对象 + app.config.globalProperties.$cache = cache + // 模态框对象 + app.config.globalProperties.$modal = modal + // 下载文件 + app.config.globalProperties.$download = download + + Array.prototype.showColumn = function (column) { + var item = this.find((x) => x.prop == column) + // console.log('showColumn方法', this, column, item) + if (item) { + return item.visible + } + return true + } +} diff --git a/src/plugins/modal.js b/src/plugins/modal.js new file mode 100644 index 0000000..e1d71be --- /dev/null +++ b/src/plugins/modal.js @@ -0,0 +1,82 @@ +import { ElMessage, ElMessageBox, ElNotification, ElLoading } from 'element-plus' + +let loadingInstance; + +export default { + // 消息提示 + msg(content) { + ElMessage.info(content) + }, + // 错误消息 + msgError(content) { + ElMessage.error(content) + }, + // 成功消息 + msgSuccess(content) { + ElMessage.success(content) + }, + // 警告消息 + msgWarning(content) { + ElMessage.warning(content) + }, + // 弹出提示 + alert(content) { + ElMessageBox.alert(content, "系统提示") + }, + // 错误提示 + alertError(content) { + ElMessageBox.alert(content, "系统提示", { type: 'error' }) + }, + // 成功提示 + alertSuccess(content) { + ElMessageBox.alert(content, "系统提示", { type: 'success' }) + }, + // 警告提示 + alertWarning(content) { + ElMessageBox.alert(content, "系统提示", { type: 'warning' }) + }, + // 通知提示 + notify(content) { + ElNotification.info(content) + }, + // 错误通知 + notifyError(content) { + ElNotification.error(content); + }, + // 成功通知 + notifySuccess(content) { + ElNotification.success(content) + }, + // 警告通知 + notifyWarning(content) { + ElNotification.warning(content) + }, + // 确认窗体 + confirm(content) { + return ElMessageBox.confirm(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 提交内容 + prompt(content) { + return ElMessageBox.prompt(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 打开遮罩层 + loading(content) { + loadingInstance = ElLoading.service({ + lock: true, + text: content, + background: "rgba(0, 0, 0, 0.7)", + }) + }, + // 关闭遮罩层 + closeLoading() { + loadingInstance.close(); + } +} \ No newline at end of file diff --git a/src/plugins/tab.js b/src/plugins/tab.js new file mode 100644 index 0000000..76f1eed --- /dev/null +++ b/src/plugins/tab.js @@ -0,0 +1,65 @@ +import useTagsViewStore from '@/store/modules/tagsView' +import router from '@/router' + +export default { + // 刷新当前tab页签 + refreshPage(obj) { + const { path, query, matched } = router.currentRoute.value; + if (obj === undefined) { + matched.forEach((m) => { + if (m.components && m.components.default && m.components.default.name) { + if (!['Layout', 'ParentView'].includes(m.components.default.name)) { + obj = { name: m.components.default.name, path: path, query: query }; + } + } + }); + } + return useTagsViewStore().delCachedView(obj).then(() => { + const { path, query } = obj + router.replace({ + path: '/redirect' + path, + query: query + }) + }) + }, + // 关闭当前tab页签,打开新页签 + closeOpenPage(obj) { + useTagsViewStore().delView(router.currentRoute.value); + if (obj !== undefined) { + return router.push(obj); + } + }, + // 关闭指定tab页签 + closePage(obj) { + if (obj === undefined) { + return useTagsViewStore().delView(router.currentRoute.value).then(({ lastPath }) => { + return router.push(lastPath || '/index'); + }); + } + return useTagsViewStore().delView(obj); + }, + // 关闭所有tab页签 + closeAllPage() { + return useTagsViewStore().delAllViews(); + }, + // 关闭左侧tab页签 + closeLeftPage(obj) { + return useTagsViewStore().delLeftTags(obj || router.currentRoute.value); + }, + // 关闭右侧tab页签 + closeRightPage(obj) { + return useTagsViewStore().delRightTags(obj || router.currentRoute.value); + }, + // 关闭其他tab页签 + closeOtherPage(obj) { + return useTagsViewStore().delOthersViews(obj || router.currentRoute.value); + }, + // 打开tab页签 + openPage(url) { + return router.push(url); + }, + // 修改tab页签 + updatePage(obj) { + return useTagsViewStore().updateVisitedView(obj); + } +} \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..3e10920 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,108 @@ +import { createWebHistory, createRouter } from 'vue-router' +import Layout from '@/layout' + +/** + * Note: 路由配置项 + * + * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1 + * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面 + * // 若你想不管路由下面的 children 声明的个数都显示你的根路由 + * // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由 + * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + * name:'router-name' // 设定路由的名字,一定要填写不然使用时会出现各种问题 + * query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数 + * meta : { + noCache: true // 如果设置为true,则不会被 缓存(默认 false) + title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 + icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg + breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 + activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 + } + */ + +// 公共路由 +export const constantRoutes = [ + { + path: '/redirect', + component: Layout, + hidden: true, + children: [ + { + path: '/redirect/:path(.*)', + component: () => import('@/views/redirect/index.vue') + } + ] + }, + { + path: '/login', + component: () => import('@/views/login'), + hidden: true + }, + { + path: '/sociallogin', + component: () => import('@/views/socialLogin'), + hidden: true + }, + { + path: '/register', + component: () => import('@/views/register'), + hidden: true + }, + { + path: '/:pathMatch(.*)*', + component: () => import('@/views/error/404'), + hidden: true + }, + { + path: '/401', + component: () => import('@/views/error/401'), + hidden: true + }, + { + path: '/error', + component: () => import('@/views/error/Error'), + hidden: true + }, + { + path: '', + component: Layout, + redirect: '/index', + children: [ + { + path: '/index', + component: () => import('@/views/index'), + name: 'Index', + meta: { title: '首页', icon: 'index', affix: true, titleKey: 'menu.home' } + } + ] + }, + { + path: '/user', + component: Layout, + hidden: true, + redirect: 'noredirect', + children: [ + { + path: 'profile', + component: () => import('@/views/system/user/profile/index'), + name: 'Profile', + meta: { title: '个人中心', icon: 'user', titleKey: 'menu.personalCenter' } + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(import.meta.env.VITE_APP_ROUTER_PREFIX), + routes: constantRoutes, + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { top: 0 } + } + } +}) + +export default router diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..de450d0 --- /dev/null +++ b/src/settings.js @@ -0,0 +1,111 @@ +export default { + /** + * 框架版本号 + */ + version: '20240105', + /** + * 网页标题 + */ + title: import.meta.env.VITE_APP_TITLE, + /** + * 侧边栏主题 深色主题theme-dark,浅色主题theme-light + */ + sideTheme: 'theme-dark', + /** + * 框架主题颜色值 + */ + theme: '#409EFF', + /** + * 是否系统布局配置 + */ + showSettings: false, + + /** + * 是否显示顶部导航 + */ + topNav: false, + + /** + * 是否显示 tagsView + */ + tagsView: true, + + /** + * 是否固定头部 + */ + fixedHeader: false, + + /** + * 是否显示logo + */ + sidebarLogo: true, + + /** + * 是否显示动态标题 + */ + dynamicTitle: false, + + /** + * @type {string | array} 'production' | ['production', 'development'] + * @description Need show err logs component. + * The default is only used in the production env + * If you want to also use it in dev, you can pass ['production', 'development'] + */ + errorLog: 'production', + /** + * 版权信息 + */ + copyright: 'Copyright ©2024 ZRAdmin.NET All Rights Reserved.', + /** + * 是否显示底部栏 + */ + showFooter: true, + /** + * 是否显示水印 + */ + showWatermark: false, + /** + * 水印文案 + */ + watermarkText: 'ZRAdmin.NET', + /** + * 是否显示其他登录 + */ + showOtherLogin: true, + /** + * 默认大小 + */ + defaultSize: 'default', + /** + * 默认语言 + */ + defaultLang: 'zh-cn', + /** + * 左侧菜单是否显示New标记 + */ + menuShowNew: false, + /** + * 是否显示QR登录 + */ + showQrLogin: true, + /** + * 是否显示手机号登录 + */ + showPhoneLogin: true, + /** + * 标签页持久化 + */ + tagsViewPersist: false, + /** + * 标签显示icon + */ + tagsShowIcon: true, + /** + * 导航模式 1、侧边栏 2、混合 3、纯顶部 + */ + navType: 1, + /** + * 前往通知地址 + */ + noticeUrl: 'https://gitee.com/izory/ZrAdminNetCore' +} diff --git a/src/signalr/analysis.js b/src/signalr/analysis.js new file mode 100644 index 0000000..ccfd2e7 --- /dev/null +++ b/src/signalr/analysis.js @@ -0,0 +1,83 @@ +import { ElNotification, ElMessageBox } from 'element-plus' +import useSocketStore from '@/store/modules/socket' +import useUserStore from '@/store/modules/user' +import { webNotify } from '@/utils/index' +import gongaoIcon from '@/assets/icons/svg/gonggao.svg' + +export default { + onMessage(connection) { + connection.on(MsgType.M001, (data) => { + useSocketStore().setOnlineUsers(data) + }) + + // 接收后台手动推送消息 + connection.on('receiveNotice', (title, data) => { + ElNotification({ + type: 'info', + title: title, + message: data, + dangerouslyUseHTMLString: true, + duration: 0 + }) + webNotify({ title: title, body: '你有一条新消息', icon: gongaoIcon }) + }) + // 接收系统通知/公告 + connection.on('moreNotice', (data) => { + if (data.code == 200) { + useSocketStore().setNoticeList(data.data) + } + }) + + // 接收在线用户 + // connection.on('onlineUser', (data) => { + // useSocketStore().setOnlineUsers(data) + // }) + + // 接收强退通知 + connection.on('forceUser', (data) => { + useSocketStore().setGlobalError({ code: 0, msg: `你的账号已被强退,原因:${data.reason || '无'}` }) + useUserStore() + .logOut() + .then(() => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'error' + }) + }) + // 接收聊天数据 + connection.on('receiveChat', (data) => { + const { fromUser, message } = data + + useSocketStore().setChat(data) + if (data.userId != useUserStore().userId) { + ElNotification({ + title: fromUser.nickName, + message: message, + type: 'success', + duration: 3000 + }) + webNotify({ title: '来自:' + fromUser.nickName, body: message, icon: gongaoIcon }) + } + }) + + connection.on('onlineInfo', (data) => { + useSocketStore().getOnlineInfo(data) + }) + + connection.on(MsgType.LogOut, () => { + useUserStore() + .logOut() + .then(() => { + ElMessageBox.alert(`你的账号已在其他设备登录,如果不是你的操作请尽快修改密码`, '提示', { + confirmButtonText: '确定', + callback: () => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'index' + } + }) + }) + }) + } +} +const MsgType = { + M001: 'onlineNum', + M002: 'connId', + LogOut: 'logOut' +} diff --git a/src/signalr/signalr.js b/src/signalr/signalr.js new file mode 100644 index 0000000..0c3d1df --- /dev/null +++ b/src/signalr/signalr.js @@ -0,0 +1,73 @@ +// 官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2&tabs=visual-studio +import * as signalR from '@microsoft/signalr' +import { getToken } from '@/utils/auth' +import { ElMessage } from 'element-plus' +import cache from '@/plugins/cache' +import analysis from '@/signalr/analysis' + +export default { + // signalR对象 + SR: {}, + // 失败连接重试次数 + failNum: 4, + init(url) { + var socketUrl = window.location.origin + url + '?clientId=' + cache.local.get('clientId') + const connection = new signalR.HubConnectionBuilder() + .withUrl(socketUrl, { accessTokenFactory: () => getToken() }) + .withAutomaticReconnect() //自动重新连接 + .configureLogging(signalR.LogLevel.Warning) + .build() + this.SR = connection + // 断线重连 + connection.onclose(async (error) => { + console.error('断开连接了' + error) + console.assert(connection.state === signalR.HubConnectionState.Disconnected) + // 建议用户重新刷新浏览器 + await this.start() + }) + + connection.onreconnected((connectionId) => { + ElMessage({ + message: '与服务器通讯已连接成功', + type: 'success', + duration: 2000 + }) + console.log('断线重新连接成功' + connectionId) + }) + + connection.onreconnecting(async () => { + console.log('断线重新连接中... ') + + await this.start() + }) + analysis.onMessage(connection) + // 启动 + // this.start(); + }, + /** + * 调用 this.signalR.start().then(async () => { await this.SR.invoke("method")}) + * @returns + */ + async start() { + try { + console.log('signalR-1', this.SR.state) + //使用async和await 或 promise的then 和catch 处理来自服务端的异常 + if (this.SR.state === signalR.HubConnectionState.Disconnected) { + await this.SR.start() + } + + console.log('signalR-2', this.SR.state) + return true + } catch (error) { + console.error(error) + this.failNum-- + // console.log(`失败重试剩余次数${that.failNum}`, error) + if (this.failNum > 0 && this.SR.state.Disconnected) { + setTimeout(async () => { + await this.start() + }, 5000) + } + return false + } + } +} diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..6287b29 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,5 @@ +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +const store = createPinia() +store.use(piniaPluginPersistedstate) +export default store diff --git a/src/store/modules/app.js b/src/store/modules/app.js new file mode 100644 index 0000000..f56136d --- /dev/null +++ b/src/store/modules/app.js @@ -0,0 +1,39 @@ +// import Cookies from 'js-cookie' +import cache from '@/plugins/cache' +import defaultSettings from '@/settings' +const useAppStore = defineStore('app', { + state: () => ({ + sidebar: { + opened: false, // Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, + // withoutAnimation: false, + hide: false + }, + device: 'desktop', + size: cache.local.get('size') || defaultSettings.defaultSize, + lang: cache.local.get('lang') || defaultSettings.defaultLang + }), + actions: { + toggleSideBar() { + this.sidebar.opened = !this.sidebar.opened + }, + closeSideBar() { + this.sidebar.opened = false + }, + toggleDevice(device) { + this.device = device + }, + setSize(size) { + this.size = size + cache.local.set('size', size) + }, + toggleSideBarHide(status) { + this.sidebar.hide = status + }, + setLang(lang) { + this.lang = lang + cache.local.set('lang', lang) + } + } +}) + +export default useAppStore diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js new file mode 100644 index 0000000..c177484 --- /dev/null +++ b/src/store/modules/permission.js @@ -0,0 +1,121 @@ +import { constantRoutes } from '@/router' +import { getRouters } from '@/api/system/menu' +import Layout from '@/layout/index' +import ParentView from '@/components/ParentView' +import InnerLink from '@/layout/components/InnerLink' +import cache from '@/plugins/cache' + +// 匹配views里面所有的.vue文件 +const modules = import.meta.glob('./../../views/**/*.vue') + +const usePermissionStore = defineStore('permission', { + state: () => ({ + routes: [], + defaultRoutes: [], + topbarRouters: [], + sidebarRouters: [], + commonlyUsedRoutes: [] //常用路由 + }), + actions: { + setRoutes(routes) { + this.addRoutes = routes + this.routes = constantRoutes.concat(routes) + }, + setDefaultRoutes(routes) { + this.defaultRoutes = constantRoutes.concat(routes) + }, + setTopbarRoutes(routes) { + this.topbarRouters = routes + }, + setSidebarRouters(routes) { + this.sidebarRouters = routes + }, + // 生成路由 + generateRoutes() { + return new Promise((resolve) => { + // 向后端请求路由数据 + getRouters().then((res) => { + const sdata = JSON.parse(JSON.stringify(res.data)) + const rdata = JSON.parse(JSON.stringify(res.data)) + const defaultData = JSON.parse(JSON.stringify(res.data)) + const sidebarRoutes = filterAsyncRouter(sdata) + const rewriteRoutes = filterAsyncRouter(rdata, false, true) + const defaultRoutes = filterAsyncRouter(defaultData) + this.setRoutes(rewriteRoutes) + this.setSidebarRouters(constantRoutes.concat(sidebarRoutes)) + this.setDefaultRoutes(sidebarRoutes) + this.setTopbarRoutes(defaultRoutes) + this.setCommonlyUsedRoutes() + resolve(rewriteRoutes) + }) + }) + }, + // 设置常用路由 + setCommonlyUsedRoutes() { + var arraryObjectLocal = cache.local.getJSON('commonlyUseMenu') || [] + this.commonlyUsedRoutes = arraryObjectLocal + }, + // 移除常用路由 + removeCommonlyUsedRoutes(item) { + var routes = this.commonlyUsedRoutes + + const fi = routes.findIndex((v) => v.path === item.path) + routes.splice(fi, 1) + cache.local.setJSON('commonlyUseMenu', routes) + } + } +}) + +// 遍历后台传来的路由字符串,转换为组件对象 +function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { + return asyncRouterMap.filter((route) => { + if (type && route.children) { + route.children = filterChildren(route.children) + } + if (route.component) { + // Layout ParentView 组件特殊处理 + if (route.component === 'Layout') { + route.component = Layout + } else if (route.component === 'ParentView') { + route.component = ParentView + } else if (route.component === 'InnerLink') { + route.component = InnerLink + } else { + route.component = loadView(route.component) + } + } + if (route.children != null && route.children && route.children.length) { + route.children = filterAsyncRouter(route.children, route, type) + } else { + delete route['children'] + delete route['redirect'] + } + return true + }) +} + +function filterChildren(childrenMap, lastRouter = false) { + var children = [] + childrenMap.forEach(el => { + el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path + if (el.children && el.children.length && el.component === 'ParentView') { + children = children.concat(filterChildren(el.children, el)) + } else { + children.push(el) + } + }) + return children +} + +export const loadView = (view) => { + let res + for (const path in modules) { + const dir = path.split('views/')[1].split('.vue')[0] + if (dir === view) { + res = () => modules[path]() + } + } + return res +} + +export default usePermissionStore diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js new file mode 100644 index 0000000..f21b365 --- /dev/null +++ b/src/store/modules/settings.js @@ -0,0 +1,74 @@ +import defaultSettings from '@/settings' +import { useDynamicTitle } from '@/utils/dynamicTitle' + +const { + sideTheme, + theme, + showSettings, + topNav, + tagsView, + fixedHeader, + sidebarLogo, + dynamicTitle, + showFooter, + showWatermark, + watermarkText, + tagsViewPersist, + codeMode, + tagsShowIcon, + navType +} = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' +const useSettingsStore = defineStore('layout-setting', { + persist: { + paths: [ + 'theme', + 'sideTheme', + 'topNav', + 'tagsView', + 'fixedHeader', + 'sidebarLogo', + 'dynamicTitle', + 'showFooter', + 'showWatermark', + 'tagsViewPersist', + 'codeMode', + 'tagsShowIcon', + 'navType' + ] //存储指定key + }, + state: () => ({ + title: '', + theme: storageSetting.theme || theme, + sideTheme: storageSetting.sideTheme || sideTheme, + showSettings: showSettings, + topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, + fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, + sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, + dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle, + showFooter: storageSetting.showFooter === undefined ? showFooter : storageSetting.showFooter, + showWatermark: storageSetting.showWatermark === undefined ? showWatermark : storageSetting.showWatermark, + watermarkText: storageSetting.watermarkText === undefined ? watermarkText : storageSetting.watermarkText, + tagsViewPersist: storageSetting.tagsViewPersist === undefined ? tagsViewPersist : storageSetting.tagsViewPersist, + codeMode: storageSetting.codeMode === undefined ? codeMode : storageSetting.codeMode, + tagsShowIcon: storageSetting.tagsShowIcon === undefined ? tagsShowIcon : storageSetting.tagsShowIcon, + navType: storageSetting.navType === undefined ? navType : storageSetting.navType + }), + actions: { + // 修改布局设置 + changeSetting(data) { + const { key, value } = data + if (Object.prototype.hasOwnProperty.call(this.$state, key)) { + this[key] = value + } + }, + // 设置网页标题 + setTitle(title) { + this.title = title + useDynamicTitle() + } + } +}) +export default useSettingsStore diff --git a/src/store/modules/socket.js b/src/store/modules/socket.js new file mode 100644 index 0000000..4c95326 --- /dev/null +++ b/src/store/modules/socket.js @@ -0,0 +1,170 @@ +import useUserStore from './user' +import signalR from '@/signalr/signalr' +const useSocketStore = defineStore('socket', { + persist: { + paths: ['chatMessage', 'chatList', 'sessionList', 'newChat', 'noticeIdArr', 'newNotice', 'globalErrorMsg', 'promptNoticeReadList'] //存储指定key + }, + state: () => ({ + onlineNum: 0, + onlineUsers: [], + noticeList: [], + //未读(公告) + promptNoticeList: [], + //弹框通知已读 + promptNoticeReadList: [], + //在线用户信息 + onlineInfo: {}, + // 聊天数据 + chatList: {}, + // 离开用户信息 + leaveUser: {}, + // 会话列表 + sessionList: {}, + //私信未读数 + newChat: 0, + //通知未读数 + newNotice: 0, + //系统消息未读数 + newSysMsg: 0, + //所有通知id + noticeIdArr: [], + // 全局错误提醒 + globalErrorMsg: {} + }), + getters: { + /** + * 返回当前会话的消息 + * @param {*} state + * @returns + */ + getMessageList(state) { + return (conversationId) => state.chatList[conversationId] + }, + getSessionList(state) { + return (userid) => state.sessionList[userid] || [] + }, + /** + * 获取所有未读小红点 + * @param {*} state + * @returns + */ + getAllDotNum() { + return this.newChat + this.newNotice + this.newSysMsg + }, + /** + * 获取所有小红点 + * @returns + */ + getMsgNum() { + return { + noticeNum: this.newNotice, + chatNum: this.newChat, + sysMsgNum: this.newSysMsg + } + } + }, + actions: { + //更新在线人数 + setOnlineUserNum(num) { + this.onlineNum = num + }, + setSysMsgNum(num) { + this.newSysMsg = num + }, + // 更新系统通知 + setNoticeList(data) { + this.noticeList = data + var gonggaoNoticeList = data.filter((x) => x.popup == 1) + const allNoticeIdArr = data.map((x) => { + return x.noticeId + }) + + var diffArr = allNoticeIdArr.filter((v) => !this.noticeIdArr.some((item) => item == v)) + + if (diffArr.length > 0) { + this.newNotice = diffArr.length + this.noticeIdArr = allNoticeIdArr + } + + // 未读弹框通知 + this.promptNoticeList = gonggaoNoticeList.filter((v) => !this.promptNoticeReadList.some((item) => item == v.noticeId)) + }, + setOnlineUsers(data) { + const { onlineClients, num, leaveUser } = data + this.onlineUsers = onlineClients + this.onlineNum = num + if (leaveUser != null) { + this.leaveUser = leaveUser + } + }, + getOnlineInfo(data) { + this.onlineInfo = data + }, + setChat(data) { + const userStore = useUserStore() + var selfUserId = userStore.userId + + var sessionId = data.toUserId + if (data.userId != selfUserId) { + sessionId = data.userId + } + var obj = this.chatList[sessionId] + if (obj && obj.length >= 50) { + this.chatList[sessionId].shift() + } + if (obj == null || obj == undefined) { + this.chatList[sessionId] = [] + } + // 判断消息是否是自己发的 + data.self = data.userId == selfUserId + this.chatList[sessionId].push(data) + if (selfUserId == data.userId) return + this.newChat++ + + if (this.sessionList[selfUserId] == undefined) { + this.sessionList[selfUserId] = [] + } + var index = this.getSessionList(selfUserId).findIndex((x) => x.userId == data.userId) + this.getSessionList(selfUserId).splice(index, 1) + this.getSessionList(selfUserId).push(data) + }, + sendChat(data) { + // console.log(JSON.stringify(data)) + return new Promise((resolve, reject) => { + signalR.SR.invoke('sendMessage', data.toUserId, data.message) + .then(() => { + resolve(true) + }) + .catch((err) => { + reject(false) + console.error(err.toString()) + }) + }) + }, + /** + * 消息已读 + * @param {*} type + */ + readAll(type) { + if (type == 0) { + this.newNotice = 0 + } else if (type == 1) { + this.newChat = 0 + } else if (type == 2) { + this.newSysMsg = 0 + } + }, + readPromptNotice(id) { + this.promptNoticeReadList.push(id) + }, + setGlobalError(data) { + this.globalErrorMsg = data + }, + clear() { + this.promptNoticeReadList = [] + this.noticeIdArr = [] + this.globalErrorMsg = {} + } + } +}) +export default useSocketStore diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..8347f34 --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,186 @@ +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' + +const useTagsViewStore = defineStore('tagsView', { + persist: { + paths: [storageSetting.tagsViewPersist ? 'visitedViews' : ''] //存储指定key + }, + state: () => ({ + visitedViews: [], + cachedViews: [], + iframeViews: [] + }), + actions: { + addView(view) { + this.addVisitedView(view) + this.addCachedView(view) + }, + addIframeView(view) { + if (this.iframeViews.some((v) => v.path === view.path)) return + this.iframeViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + this.addCachedView(view) + }, + addVisitedView(view) { + if (this.visitedViews.some((v) => v.path === view.path)) return + this.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + addCachedView(view) { + if (this.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + this.cachedViews.push(view.name) + } + }, + delView(view) { + return new Promise((resolve) => { + this.delVisitedView(view) + this.delCachedView(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delVisitedView(view) { + return new Promise((resolve) => { + for (const [i, v] of this.visitedViews.entries()) { + if (v.path === view.path) { + this.visitedViews.splice(i, 1) + break + } + } + this.iframeViews = this.iframeViews.filter((item) => item.path !== view.path) + resolve([...this.visitedViews]) + }) + }, + delIframeView(view) { + return new Promise((resolve) => { + this.iframeViews = this.iframeViews.filter((item) => item.path !== view.path) + resolve([...this.iframeViews]) + }) + }, + delCachedView(view) { + return new Promise((resolve) => { + const index = this.cachedViews.indexOf(view.name) + index > -1 && this.cachedViews.splice(index, 1) + resolve([...this.cachedViews]) + }) + }, + delOthersViews(view) { + return new Promise((resolve) => { + this.delOthersVisitedViews(view) + this.delOthersCachedViews(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delOthersVisitedViews(view) { + return new Promise((resolve) => { + this.visitedViews = this.visitedViews.filter((v) => { + return v.meta.affix || v.path === view.path + }) + this.iframeViews = this.iframeViews.filter((item) => item.path === view.path) + resolve([...this.visitedViews]) + }) + }, + delOthersCachedViews(view) { + return new Promise((resolve) => { + const index = this.cachedViews.indexOf(view.name) + if (index > -1) { + this.cachedViews = this.cachedViews.slice(index, index + 1) + } else { + this.cachedViews = [] + } + resolve([...this.cachedViews]) + }) + }, + delAllViews(view) { + return new Promise((resolve) => { + this.delAllVisitedViews(view) + this.delAllCachedViews(view) + resolve({ + visitedViews: [...this.visitedViews], + cachedViews: [...this.cachedViews] + }) + }) + }, + delAllVisitedViews(view) { + return new Promise((resolve) => { + const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) + this.visitedViews = affixTags + this.iframeViews = [] + resolve([...this.visitedViews]) + }) + }, + delAllCachedViews(view) { + return new Promise((resolve) => { + this.cachedViews = [] + resolve([...this.cachedViews]) + }) + }, + updateVisitedView(view) { + for (let v of this.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + delRightTags(view) { + return new Promise((resolve) => { + const index = this.visitedViews.findIndex((v) => v.path === view.path) + if (index === -1) { + return + } + this.visitedViews = this.visitedViews.filter((item, idx) => { + if (idx <= index || (item.meta && item.meta.affix)) { + return true + } + const i = this.cachedViews.indexOf(item.name) + if (i > -1) { + this.cachedViews.splice(i, 1) + } + if (item.meta.link) { + const fi = this.iframeViews.findIndex((v) => v.path === item.path) + this.iframeViews.splice(fi, 1) + } + return false + }) + resolve([...this.visitedViews]) + }) + }, + delLeftTags(view) { + return new Promise((resolve) => { + const index = this.visitedViews.findIndex((v) => v.path === view.path) + if (index === -1) { + return + } + this.visitedViews = this.visitedViews.filter((item, idx) => { + if (idx >= index || (item.meta && item.meta.affix)) { + return true + } + const i = this.cachedViews.indexOf(item.name) + if (i > -1) { + this.cachedViews.splice(i, 1) + } + if (item.meta.link) { + const fi = this.iframeViews.findIndex((v) => v.path === item.path) + this.iframeViews.splice(fi, 1) + } + return false + }) + resolve([...this.visitedViews]) + }) + } + } +}) + +export default useTagsViewStore diff --git a/src/store/modules/user.js b/src/store/modules/user.js new file mode 100644 index 0000000..1642040 --- /dev/null +++ b/src/store/modules/user.js @@ -0,0 +1,173 @@ +import { login, logout, getInfo, oauthCallback, phoneLogin } from '@/api/system/login' +import { getToken, setToken, removeToken } from '@/utils/auth' +import useTagsViewStore from './tagsView' +import defAva from '@/assets/images/profile.jpg' +import cache from '@/plugins/cache' +import md5 from 'crypto-js/md5' + +const useUserStore = defineStore('user', { + persist: { + paths: ['loginType', 'clientId'] //存储指定key + }, + state: () => ({ + loginType: 1, + userInfo: '', + token: getToken(), + name: '', + avatar: '', + roles: [], + permissions: [], + userId: 0, + authSource: '', + userName: '', + clientId: '' + }), + actions: { + setAuthSource(source) { + this.authSource = source + }, + // 登录 + login(userInfo) { + const username = userInfo.username.trim() + const password = md5(userInfo.password).toString() + const code = userInfo.code + const uuid = userInfo.uuid + const clientId = this.clientId + + return new Promise((resolve, reject) => { + login(username, password, code, uuid, clientId) + .then((res) => { + if (res.code == 200) { + setToken(res.data) + this.token = res.data + resolve() //then处理 + } else { + console.log('login error ', res) + reject(res) //catch处理 + } + }) + .catch((error) => { + reject(error) + }) + }) + }, + /** + * 三方授权登录 + * @param {*} data + * @param {*} param { authSource : ''} + * @returns + */ + oauthLogin(data, param) { + return new Promise((resolve, reject) => { + oauthCallback(data, param) + .then((res) => { + const { code, data } = res + if (code == 200) { + setToken(data.token) + this.token = data.token + // Cookies.set('username', data.userName, { expires: 30 }) + // Cookies.set('password', encrypt(data.password), { expires: 30 }) + // Cookies.set('rememberMe', true, { expires: 30 }) + resolve(res) //then处理 + } else { + console.log('login error ', res) + reject(res) //catch处理 + } + }) + .catch((err) => { + reject(err) + }) + }) + }, + // 扫码登录 + scanLogin(data) { + return new Promise((resolve, reject) => { + setToken(data.token) + this.token = data.token + + resolve(data.token) //then处理 + }) + }, + // 手机号登录 + phoneNumLogin(userInfo) { + return new Promise((resolve, reject) => { + phoneLogin(userInfo) + .then((res) => { + if (res.code == 200) { + setToken(res.data) + this.token = res.data + resolve() //then处理 + } else { + console.log('login error ', res) + reject(res) //catch处理 + } + }) + .catch((error) => { + reject(error) + }) + }) + }, + // 获取用户信息 + getInfo() { + return new Promise((resolve, reject) => { + getInfo() + .then((res) => { + const data = res.data + const avatar = data.user.avatar == '' ? defAva : data.user.avatar + + if (data.roles && data.roles.length > 0) { + // 验证返回的roles是否是一个非空数组 + this.roles = data.roles + this.permissions = data.permissions + } else { + this.roles = ['ROLE_DEFAULT'] + } + + this.name = data.user.nickName + this.avatar = avatar + this.userInfo = data.user //新加 + this.userId = data.user.userId //新加 + this.userName = data.user.userName //新加 + resolve(res) + }) + .catch((error) => { + console.warn(error) + reject('获取用户信息失败') + }) + }) + }, + // 退出系统 + logOut() { + return new Promise((resolve, reject) => { + logout(this.token) + .then((res) => { + this.token = '' + this.roles = [] + this.permissions = [] + removeToken() + useTagsViewStore().visitedViews = [] + resolve(res) + }) + .catch((error) => { + reject(error) + }) + }) + }, + // 前端 登出 + fedLogOut() { + return new Promise((resolve) => { + this.token = '' + removeToken() + resolve() + }) + }, + setClientId(clientId) { + this.clientId = clientId + }, + refreshToken(token) { + setToken(token) + this.token = token + } + } +}) +export default useUserStore diff --git a/src/utils/auth.js b/src/utils/auth.js new file mode 100644 index 0000000..fa92d24 --- /dev/null +++ b/src/utils/auth.js @@ -0,0 +1,15 @@ +// import Cookies from 'js-cookie' + +const TokenKey = 'ZR-Token' + +export function getToken() { + return localStorage.getItem(TokenKey) +} + +export function setToken(token) { + return localStorage.setItem(TokenKey, token) +} + +export function removeToken() { + return localStorage.removeItem(TokenKey) +} diff --git a/src/utils/dateOptions.js b/src/utils/dateOptions.js new file mode 100644 index 0000000..d886440 --- /dev/null +++ b/src/utils/dateOptions.js @@ -0,0 +1,85 @@ +// dayjs 参考:https://www.cnblogs.com/Airon-wei/p/14362160.html +import dayjs from 'dayjs' + +const dateOptions = [ + { + text: '昨天', + value: () => { + const start = dayjs().subtract(1, 'day').format('YYYY-MM-DD') + const end = start + ' 23:59:59' + + return [start, dayjs(end).toISOString()] + } + }, + { + text: '今天', + value: () => { + const start = dayjs().format('YYYY-MM-DD') + const end = start + ' 23:59:59' + + return [start, end] + } + }, + { + text: '本周', + value: () => { + const end = dayjs().endOf('week').add(1, 'day').format('YYYY-MM-DD') + ' 23:59:59' + const start = dayjs().startOf('week').add(1, 'day').format('YYYY-MM-DD') + return [start, end] + } + }, + { + text: '上周', + value: () => { + const start = dayjs().add(-1, 'week').startOf('week').add(1, 'day').format('YYYY-MM-DD') + const end = dayjs().add(-1, 'week').endOf('week').add(1, 'day').format('YYYY-MM-DD') + ' 23:59:59' + return [start, end] + } + }, + { + text: '本月', + value: () => { + const end = dayjs().endOf('month').format('YYYY-MM-DD') + const start = dayjs().startOf('month').format('YYYY-MM-DD') + + return [start, end + ' 23:59:59'] + } + }, + { + text: '上月', + value: () => { + const end = dayjs().startOf('month').format('YYYY-MM-DD') + const start = dayjs().add(-1, 'month').startOf('month').format('YYYY-MM-DD') + + return [start, end] + } + }, + { + text: '最近一周', + value: () => { + const end = dayjs().format('YYYY-MM-DD') + ' 23:59:59' + const start = new Date() + start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) + return [dayjs(start).format('YYYY-MM-DD'), end] + } + }, + { + text: '最近一个月', + value: () => { + const end = dayjs().format('YYYY-MM-DD') + ' 23:59:59' + // const start = new Date() + //start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) + return [dayjs().day(-30).format('YYYY-MM-DD'), end] + } + }, + { + text: '最近三个月', + value: () => { + const end = dayjs().format('YYYY-MM-DD') + ' 23:59:59' + // const start = new Date() + // start.setTime(start.getTime() - 3600 * 1000 * 24 * 90) + return [dayjs().day(-90).format('YYYY-MM-DD'), end] + } + } +] +export default dateOptions diff --git a/src/utils/dict.js b/src/utils/dict.js new file mode 100644 index 0000000..44eb728 --- /dev/null +++ b/src/utils/dict.js @@ -0,0 +1,17 @@ +import { getDicts } from '@/api/system/dict/data' + +/** + * 获取字典数据 + */ +export function useDict(...args) { + const res = ref({}); + return (() => { + args.forEach((d, index) => { + res.value[d] = []; + getDicts(d).then(resp => { + res.value[d] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, listClass: p.listClass, cssClass: p.cssClass })) + }) + }) + return toRefs(res.value); + })() +} \ No newline at end of file diff --git a/src/utils/dynamicTitle.js b/src/utils/dynamicTitle.js new file mode 100644 index 0000000..449d899 --- /dev/null +++ b/src/utils/dynamicTitle.js @@ -0,0 +1,14 @@ +import defaultSettings from '@/settings' +import useSettingsStore from '@/store/modules/settings' + +/** + * 动态修改标题 + */ +export function useDynamicTitle() { + const settingsStore = useSettingsStore() + if (settingsStore.dynamicTitle) { + document.title = settingsStore.title + ' - ' + defaultSettings.title; + } else { + document.title = defaultSettings.title; + } +} \ No newline at end of file diff --git a/src/utils/errorCode.js b/src/utils/errorCode.js new file mode 100644 index 0000000..d2111ee --- /dev/null +++ b/src/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..b1bdcf6 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,387 @@ +import { dayjs } from 'element-plus' +import { parseTime } from './ruoyi' +import { useWebNotification } from '@vueuse/core' + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分' + } +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function showTime(time) { + const d = new Date(time) + const now = Date.now() + var y1 = d.getFullYear() + var y2 = dayjs(now).year() + + if (y1 == y2) { + return parseTime(time, 'MM-DD HH:mm') + } else { + return parseTime(time, 'YYYY-MM-DD') + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function getQueryObject(url) { + url = url == null ? window.location.href : url + const search = url.substring(url.lastIndexOf('?') + 1) + const obj = {} + const reg = /([^?&=]+)=([^?&=]*)/g + search.replace(reg, (rs, $1, $2) => { + const name = decodeURIComponent($1) + let val = decodeURIComponent($2) + val = String(val) + obj[name] = val + return rs + }) + return obj +} + +/** + * 清空数组 + * @param {Array} actual + * @returns {Array} + */ +export function cleanArray(actual) { + const newArray = [] + for (let i = 0; i < actual.length; i++) { + if (actual[i]) { + newArray.push(actual[i]) + } + } + return newArray +} + +/** + * @param {Object} json + * @returns {Array} + */ +export function param(json) { + if (!json) return '' + return cleanArray( + Object.keys(json).map((key) => { + if (json[key] === undefined) return '' + return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) + }) + ).join('&') +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach((v) => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +/** + * @param {string} val + * @returns {string} + */ +export function html2Text(val) { + const div = document.createElement('div') + div.innerHTML = val + return div.textContent || div.innerText +} + +/** + * Merges two objects, giving the last one precedence + * @param {Object} target + * @param {(Object|Array)} source + * @returns {Object} + */ +export function objectMerge(target, source) { + if (typeof target !== 'object') { + target = {} + } + if (Array.isArray(source)) { + return source.slice() + } + Object.keys(source).forEach((property) => { + const sourceProperty = source[property] + if (typeof sourceProperty === 'object') { + target[property] = objectMerge(target[property], sourceProperty) + } else { + target[property] = sourceProperty + } + }) + return target +} + +/** + * @param {HTMLElement} element + * @param {string} className + */ +export function toggleClass(element, className) { + if (!element || !className) { + return + } + let classString = element.className + const nameIndex = classString.indexOf(className) + if (nameIndex === -1) { + classString += '' + className + } else { + classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length) + } + element.className = classString +} + +/** + * @param {string} type + * @returns {Date} + */ +export function getTime(type) { + if (type === 'start') { + return new Date().getTime() - 3600 * 1000 * 24 * 90 + } else { + return new Date(new Date().toDateString()) + } +} + +/** + * @param {Function} func + * @param {number} wait + * @param {boolean} immediate + * @return {*} + */ +export function debounce(func, wait, immediate) { + let timeout, args, context, timestamp, result + + const later = function () { + // 据上一次触发时间间隔 + const last = +new Date() - timestamp + + // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait + if (last < wait && last > 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = null + // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 + if (!immediate) { + result = func.apply(context, args) + if (!timeout) context = args = null + } + } + } + + return function (...args) { + context = this + timestamp = +new Date() + const callNow = immediate && !timeout + // 如果延时不存在,重新设定延时 + if (!timeout) timeout = setTimeout(later, wait) + if (callNow) { + result = func.apply(context, args) + context = args = null + } + + return result + } +} + +/** + * This is just a simple version of deep copy + * Has a lot of edge cases bug + * If you want to use a perfect deep copy, use lodash's _.cloneDeep + * @param {Object} source + * @returns {Object} + */ +export function deepClone(source) { + if (!source && typeof source !== 'object') { + throw new Error('error arguments', 'deepClone') + } + const targetObj = source.constructor === Array ? [] : {} + Object.keys(source).forEach((keys) => { + if (source[keys] && typeof source[keys] === 'object') { + targetObj[keys] = deepClone(source[keys]) + } else { + targetObj[keys] = source[keys] + } + }) + return targetObj +} + +/** + * @param {Array} arr + * @returns {Array} + */ +export function uniqueArr(arr) { + return Array.from(new Set(arr)) +} + +/** + * @returns {string} + */ +export function createUniqueString() { + const timestamp = +new Date() + '' + const randomNum = parseInt((1 + Math.random()) * 65536) + '' + return (+(randomNum + timestamp)).toString(32) +} + +/** + * Check if an element has a class + * @param {HTMLElement} elm + * @param {string} cls + * @returns {boolean} + */ +export function hasClass(ele, cls) { + return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) +} + +/** + * Add class to element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function addClass(ele, cls) { + if (!hasClass(ele, cls)) ele.className += ' ' + cls +} + +/** + * Remove class from element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function removeClass(ele, cls) { + if (hasClass(ele, cls)) { + const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') + ele.className = ele.className.replace(reg, ' ') + } +} + +export function makeMap(str, expectsLowerCase) { + const map = Object.create(null) + const list = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase ? (val) => map[val.toLowerCase()] : (val) => map[val] +} + +// 首字母大小 +export function titleCase(str) { + return str.replace(/( |^)[a-z]/g, (L) => L.toUpperCase()) +} + +// 下划转驼峰 +export function camelCase(str) { + return str.replace(/_[a-z]/g, (str1) => str1.substr(-1).toUpperCase()) +} + +// 是否数字 +export function isNumberStr(str) { + return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) +} + +/** + * 变浅颜色值 + * @param color 颜色值字符串 + * @param level 加深的程度,限0-1之间 + * @returns 返回处理后的颜色值 + */ +export function getLightColor(color, level) { + let reg = /^\#?[0-9A-Fa-f]{6}$/ + if (!reg.test(color)) return color + 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]) +} + +/** + * hex颜色转rgb颜色 + * @param str 颜色值字符串 + * @returns 返回处理后的颜色值 + */ +export function hexToRgb(str) { + let hexs = '' + let reg = /^\#?[0-9A-Fa-f]{6}$/ + if (!reg.test(str)) return str + 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, g, b) { + let reg = /^\d{1,3}$/ + if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return '' + 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('')}` +} + +/** + * 浏览器Web通知 + * @param { title: 'title' } optinos + */ +export function webNotify(optinos) { + const { show, isSupported } = useWebNotification({ + title: optinos.title, + dir: 'auto', + lang: 'en', + renotify: true, + tag: 'tag', + body: optinos.body, + icon: optinos.icon, + requireInteraction: true + }) + if (isSupported) { + show() + } +} diff --git a/src/utils/jsencrypt.js b/src/utils/jsencrypt.js new file mode 100644 index 0000000..a758068 --- /dev/null +++ b/src/utils/jsencrypt.js @@ -0,0 +1,22 @@ +import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' + +// 密钥对生成 http://web.chacuo.net/netrsakeypair + +const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALj0zjON+EVdBsnMcR4Uj+jOYgp5ZipftQZ1utW8KvVioz+RSaotF1JHt59q9SC/mZcWWpbpcEqQ3WyyyCC33msCAwEAAQ==' + +const privateKey = + 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAuPTOM434RV0GycxxHhSP6M5iCnlmKl+1BnW61bwq9WKjP5FJqi0XUke3n2r1IL+ZlxZalulwSpDdbLLIILfeawIDAQABAkB5PYAtq1KjpWddwPYlkbUEFsWNuCaQgExZ/7KJiN9gGjo/UfUZ3W39Orb8PITIYf1NbasReqgddAcsfJNyoDWBAiEA7K89DyTmbjNSmekdD3rejRDdMzzXYtcbo69ZjHoowMUCIQDIDN8eg6PcWk4kiRcRYcNEfriUJR7Fg07ellSPv821bwIhAJA5TEyxIJUgQwI0cZfgOELfdtrlBR5ek6IPlNKsEa89AiBbMVroexPQWC41A3VLjChKagXUKpO7b98dIqRLnyCz6wIgP3qpvnO4IOxY7f5XarfCVyIHZJAMt/R1f16P5OkKv+A=' + +// 加密 +export function encrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPublicKey(publicKey) // 设置公钥 + return encryptor.encrypt(txt) // 对数据进行加密 +} + +// 解密 +export function decrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPrivateKey(privateKey) // 设置私钥 + return encryptor.decrypt(txt) // 对数据进行解密 +} diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..568683f --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,226 @@ +import axios from 'axios' +import { ElMessageBox, ElMessage, ElLoading } from 'element-plus' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import useUserStore from '@/store/modules/user' +import { blobValidate, delEmptyQueryNodes } from '@/utils/ruoyi' +import { saveAs } from 'file-saver' + +let downloadLoadingInstance +// 解决后端跨域获取不到cookie问题 +// axios.defaults.withCredentials = true +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +// 创建axios实例 +const service = axios.create({ + // axios中请求配置有baseURL选项,表示请求URL公共部分 + baseURL: import.meta.env.VITE_APP_BASE_API, + // 超时 + timeout: 30000 +}) + +// request拦截器 +service.interceptors.request.use( + (config) => { + // 是否需要设置 token + if (getToken()) { + //将token放到请求头发送给服务器,将tokenkey放在请求头中 + config.headers['Authorization'] = 'Bearer ' + getToken() + config.headers['userid'] = useUserStore().userId + config.headers['userName'] = encodeURIComponent(useUserStore().userName) + } + const method = config?.method || 'get' + const header = config?.headers['Content-Type'] ?? '' + + if ((method.toLowerCase() === 'post' || method.toLowerCase() === 'put') && header != 'multipart/form-data') { + config.data = delEmptyQueryNodes(config.data) + } + return config + }, + (error) => { + console.log(error) + Promise.reject(error) + } +) + +// 响应拦截器 +service.interceptors.response.use( + (res) => { + if (res.status !== 200) { + Promise.reject('network error') + return + } + // 未设置状态码则默认成功状态 + const { code, msg } = res.data + // 二进制数据则直接返回 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { + return res + } + var token = res.headers['x-refresh-token'] + if (token) { + useUserStore().refreshToken(token) + } + if (code == 401) { + ElMessageBox.confirm('登录状态已过期,请重新登录', '系统提示', { + confirmButtonText: '重新登陆', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + useUserStore() + .logOut() + .then(() => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'index' + }) + }) + + return Promise.reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code == 0 || code == 1 || code == 110 || code == 101 || code == 403 || code == 500 || code == 429) { + ElMessage({ + message: msg, + type: 'error' + }) + return Promise.reject(res.data) + } else { + //返回标准 code/msg/data字段 + return res.data + } + }, + (error) => { + console.error('axios err', error) + var duration = 3000 + let { message, response } = error + + if (response.status == 404) { + message = '接口404' + } else if (response.status == 403) { + window.location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + '401' + } else if (message == 'Network Error') { + message = '后端接口连接异常' + } else if (message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message.includes('code 429')) { + message = '请求过于频繁,请稍后再试' + } else if (message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常,请联系管理员' + + if (import.meta.env.DEV) { + message = 'Oops,后端出错了,你不会连错误日志都不会看吧' + duration = 0 + } + } + ElMessage({ + message: message, + type: 'error', + duration: duration, + showClose: true, + grouping: true + }) + return Promise.reject({ code: 500, msg: message }) + } +) + +/** + * get方法,对应get请求 + * @param {String} url [请求的url地址] + * @param {Object} params [请求时携带的参数] + */ +export function get(url, params) { + return new Promise((resolve, reject) => { + service + .get(url, { + params: params + }) + .then((res) => { + resolve(res) + }) + .catch((err) => { + reject(err) + }) + }) +} + +export function post(url, params) { + return new Promise((resolve, reject) => { + service + .post(url, { + params: params + }) + .then((res) => { + resolve(res) + }) + .catch((err) => { + reject(err) + }) + }) +} + +/** + * 提交表单 + * @param {*} url + * @param {*} data + */ +export function postForm(url, data, config) { + return new Promise((resolve, reject) => { + service + .post(url, data, config) + .then((res) => { + resolve(res) + }) + .catch((err) => { + reject(err) + }) + }) +} + +/** + * 通用下载方法 + * @param {*} url 请求地址 + * @param {*} params 请求参数 + * @param {*} config 配置 + * @returns + */ +export async function downFile(url, params, config) { + downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' }) + + service + .get(url, { + params, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob', + ...config + }) + .then(async (resp) => { + const { data } = resp + + const isLogin = await blobValidate(data) + if (isLogin) { + var patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*') + var contentDisposition = decodeURI(resp.headers['content-disposition']) + var result = patt.exec(contentDisposition) + var fileName = result[1] + fileName = fileName.replace(/\"/g, '') + + const blob = new Blob([data]) + saveAs(blob, fileName) + } else { + const resText = await data.text() + const rspObj = JSON.parse(resText) + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + + ElMessage({ + message: errMsg, + type: 'error' + }) + } + }) + .catch(() => { + ElMessage({ + message: '下载文件出现错误,请联系管理员!', + type: 'error' + }) + }) + .finally(() => { + downloadLoadingInstance.close() + }) +} + +export default service diff --git a/src/utils/ruoyi.js b/src/utils/ruoyi.js new file mode 100644 index 0000000..c8ba1c9 --- /dev/null +++ b/src/utils/ruoyi.js @@ -0,0 +1,318 @@ +const baseURL = import.meta.env.VITE_APP_BASE_API +import dayjs from 'dayjs' +/** + * 通用js方法封装处理 + * Copyright (c) 2019 ruoyi + */ + +/** + * 日期格式化 + * @param {*} time + * @param {* } pattern 'YYYY-MM-DD HH:mm:ss' + * @returns + */ +export function parseTime(time, pattern = 'YYYY-MM-DD HH:mm:ss') { + if (arguments.length === 0 || !time) { + return null + } + + return dayjs(time).format(pattern) +} + +// 表单重置 +export function resetForm(refName) { + if (this.$refs[refName]) { + this.$refs[refName].resetFields() + } +} + +/** + * 添加日期范围 + * @param { beginTime: '', endTime: '', page: 1} params + * @param {*} dateRange 日期范围数组 + * @param {*} propName C#属性名首字母大写 + * @returns + */ +// 添加日期范围 +export function addDateRange(params, dateRange, propName) { + let search = params + search = typeof search === 'object' && search !== null && !Array.isArray(search) ? search : {} + dateRange = Array.isArray(dateRange) ? dateRange : [] + if (typeof propName === 'undefined') { + search['beginTime'] = dateRange[0] + search['endTime'] = dateRange[1] + } else { + search['begin' + propName] = dateRange[0] + search['end' + propName] = dateRange[1] + } + return search +} + +// 回显数据字典 +export function selectDictLabel(datas, value) { + if (value === undefined) { + return '' + } + var actions = [] + Object.keys(datas).some((key) => { + if (datas[key].dictValue == '' + value) { + actions.push(datas[key].dictLabel) + return true + } + }) + if (actions.length === 0) { + actions.push(value) + } + return actions.join('') +} + +// 回显数据字典(字符串数组) +export function selectDictLabels(datas, value, separator) { + if (value === undefined) { + return '' + } + var actions = [] + var currentSeparator = undefined === separator ? ',' : separator + var temp = value.split(currentSeparator) + Object.keys(value.split(currentSeparator)).some((val) => { + Object.keys(datas).some((key) => { + if (datas[key].value == '' + temp[val]) { + actions.push(datas[key].label + currentSeparator) + } + }) + }) + return actions.join('').substring(0, actions.join('').length - 1) +} +// 通用下载方法 +export function download(fileName) { + // window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true; + // window.open(baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true) + window.open(baseURL + fileName) +} + +// 字符串格式化(%s ) +export function sprintf(str) { + var args = arguments, + flag = true, + i = 1 + str = str.replace(/%s/g, function () { + var arg = args[i++] + if (typeof arg === 'undefined') { + flag = false + return '' + } + return arg + }) + return flag ? str : '' +} + +// 转换字符串,undefined,null等转化为"" +export function parseStrEmpty(str) { + if (!str || str == 'undefined' || str == 'null') { + return '' + } + return str +} + +// 数据合并 +export function mergeRecursive(source, target) { + for (var p in target) { + try { + if (target[p].constructor == Object) { + source[p] = mergeRecursive(source[p], target[p]) + } else { + source[p] = target[p] + } + } catch (e) { + source[p] = target[p] + } + } + return source +} + +/** + * 构造树型结构数据 + * @param {*} data 数据源 + * @param {*} id id字段 默认 'id' + * @param {*} parentId 父节点字段 默认 'parentId' + * @param {*} children 孩子节点字段 默认 'children' + */ +export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children') { + const childrenMap = new Map(); + const nodeMap = new Map(); + const tree = []; + + // 初始化节点映射 + data.forEach(item => { + nodeMap.set(item[id], item); + childrenMap.set(item[id], []); + }); + + // 构建树结构 + data.forEach(item => { + const pid = item[parentId]; + if (nodeMap.has(pid)) { + nodeMap.get(pid)[children] = childrenMap.get(pid); + nodeMap.get(pid)[children].push(item); + } else { + tree.push(item); + } + }); + + return tree; +} + +/** + * 将自定义数据转换成字典 + * @param {*} data 数据源 + * @param {*} dictLabel dictLabel + * @param {*} dictValue dictValue + */ +export function toDict(data, dictLabel, dictValue) { + let config = { + label: dictLabel || 'dictLabel', + value: dictValue || 'dictValue' + } + + var tree = [] + + for (let d of data) { + let label = d[config.label] + let value = d[config.value] + + tree.push({ dictLabel: label, dictValue: value }) + } + + return tree +} + +/** + * 参数处理 + * @param {*} params 参数 + */ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName] + var part = encodeURIComponent(propName) + '=' + if (value !== null && typeof value !== 'undefined') { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && typeof value[key] !== 'undefined') { + let params = propName + '[' + key + ']' + var subPart = encodeURIComponent(params) + '=' + result += subPart + encodeURIComponent(value[key]) + '&' + } + } + } else { + result += part + encodeURIComponent(value) + '&' + } + } + } + return result +} + +// 返回项目路径 +export function getNormalPath(p) { + if (p.length === 0 || !p || p == 'undefined') { + return p + } + let res = p.replace('//', '/') + if (res[res.length - 1] === '/') { + return res.slice(0, res.length - 1) + } + return res +} + +// 验证是否为blob格式 +export async function blobValidate(data) { + try { + const text = await data.text() + JSON.parse(text) + return false + } catch (error) { + return true + } +} + +// 转换字符串,undefined,null等转化为"" +export function praseStrEmpty(str) { + if (!str || str == 'undefined' || str == 'null') { + return '' + } + return str +} +export function praseStrZero(str) { + if (!str || str == 'undefined' || str == 'null') { + console.log('zero') + return 0 + } + return str +} + +/** + * 字符串是否为空 + * @param {*} obj + * @returns + */ +export function isEmpty(obj) { + if (typeof obj == 'undefined' || obj == null || obj === '') { + return true + } else { + return false + } +} + +/** + * 查找对象的唯一键值对(比如id)去判断是否存在某个数据中 + * @param {*} arr 数组 + * @param {*} key 对象键值名 + * @param {*} val + * @returns + */ +export function findItem(arr, key, val) { + for (let i = 0; i < arr.length; i++) { + if (arr[i][key] == val) { + return i + } + } + return -1 +} + +export function color16() { + //十六进制颜色随机 + const r = Math.floor(Math.random() * 256) + const g = Math.floor(Math.random() * 256) + const b = Math.floor(Math.random() * 256) + const color = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}` + return color +} + +/** + * 返回星期几 + * @param {*} num + * @returns + */ +export function getWeek(num = 0) { + var datas = dayjs().add(num, 'day').day() + var week = ['日', '一', '二', '三', '四', '五', '六'] + return '星期' + week[datas] +} + +// 移除空字符串,null, undefined +export const delEmptyQueryNodes = (obj = {}) => { + if (Array.isArray(obj)) { + return obj + } + const params = Object.keys(obj) + .filter((key) => obj[key] !== null && obj[key] !== undefined) + .reduce( + (acc, key) => ({ + ...acc, + [key]: obj[key] + }), + {} + ) + // console.log('过滤后参数=', params) + return params +} diff --git a/src/utils/scroll-to.js b/src/utils/scroll-to.js new file mode 100644 index 0000000..c5d8e04 --- /dev/null +++ b/src/utils/scroll-to.js @@ -0,0 +1,58 @@ +Math.easeInOutQuad = function(t, b, c, d) { + t /= d / 2 + if (t < 1) { + return c / 2 * t * t + b + } + t-- + return -c / 2 * (t * (t - 2) - 1) + b +} + +// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts +var requestAnimFrame = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } +})() + +/** + * Because it's so fucking difficult to detect the scrolling element, just move them all + * @param {number} amount + */ +function move(amount) { + document.documentElement.scrollTop = amount + document.body.parentNode.scrollTop = amount + document.body.scrollTop = amount +} + +function position() { + return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop +} + +/** + * @param {number} to + * @param {number} duration + * @param {Function} callback + */ +export function scrollTo(to, duration, callback) { + const start = position() + const change = to - start + const increment = 20 + let currentTime = 0 + duration = (typeof (duration) === 'undefined') ? 500 : duration + var animateScroll = function() { + // increment the time + currentTime += increment + // find the value with the quadratic in-out easing function + var val = Math.easeInOutQuad(currentTime, start, change, duration) + // move the document.body + move(val) + // do the animation unless its over + if (currentTime < duration) { + requestAnimFrame(animateScroll) + } else { + if (callback && typeof (callback) === 'function') { + // the animation is done so lets callback + callback() + } + } + } + animateScroll() +} diff --git a/src/utils/validate.js b/src/utils/validate.js new file mode 100644 index 0000000..1c63a29 --- /dev/null +++ b/src/utils/validate.js @@ -0,0 +1,103 @@ +/** + * 判断url是否是http或https + * @param {string} path + * @returns {Boolean} + */ +export function isHttp(url) { + if (url) { + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 + } + return false +} +export function isLink(url) { + if (url) { + return url.indexOf('/link') !== -1 + } + return false +} +/** + * 判断path是否为外链 + * @param {string} path + * @returns {Boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/** + * @param {string} url + * @returns {Boolean} + */ +export function validURL(url) { + const reg = + /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} + +/** + * @param {string} email + * @returns {Boolean} + */ +export function validEmail(email) { + const reg = + /^(([^<>()\[\]\\.,;:\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,}))$/ + return reg.test(email) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function isString(str) { + if (typeof str === 'string' || str instanceof String) { + return true + } + return false +} + +/** + * @param {Array} arg + * @returns {Boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} diff --git a/src/utils/wartermark.js b/src/utils/wartermark.js new file mode 100644 index 0000000..d0c78ad --- /dev/null +++ b/src/utils/wartermark.js @@ -0,0 +1,61 @@ +export const getmark = () => { + const setWatermark = (str) => { + const id = '1.23452384164.123412416' + + if (document.getElementById(id) !== null) { + document.body.removeChild(document.getElementById(id)) + } + + //创建一个画布 + const can = document.createElement('canvas') + //设置画布的长宽 + can.width = 200 + can.height = 120 + + const cans = can.getContext('2d') + //旋转角度 + cans.rotate((-15 * Math.PI) / 180) + cans.font = '18px Vedana' + //设置填充绘画的颜色、渐变或者模式 + cans.fillStyle = 'rgba(200, 200, 200, 0.30)' + //设置文本内容的当前对齐方式 + cans.textAlign = 'left' + //设置在绘制文本时使用的当前文本基线 + // cans.textBaseline = "Middle"; + //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置) + cans.fillText(str, can.width / 8, can.height / 2) + + const div = document.createElement('div') + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '30px' + div.style.left = '0px' + div.style.position = 'fixed' + div.style.zIndex = '100000' + 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 + } + + // 该方法只允许调用一次 + const watermark = (str) => { + let id = setWatermark(str) + setInterval(() => { + if (document.getElementById(id) === null) { + id = setWatermark(str) + } + }, 500) + window.onresize = () => { + setWatermark(str) + } + } + const removeWatermark = () => { + const id = '1.23452384164.123412416' + if (document.getElementById(id) !== null) { + document.body.removeChild(document.getElementById(id)) + } + } + return { setWatermark, watermark, removeWatermark } +} diff --git a/src/views/article/articleCategory.vue b/src/views/article/articleCategory.vue new file mode 100644 index 0000000..57d7490 --- /dev/null +++ b/src/views/article/articleCategory.vue @@ -0,0 +1,442 @@ + + + diff --git a/src/views/article/articleTopic.vue b/src/views/article/articleTopic.vue new file mode 100644 index 0000000..87a1760 --- /dev/null +++ b/src/views/article/articleTopic.vue @@ -0,0 +1,272 @@ + + + + diff --git a/src/views/article/manager.vue b/src/views/article/manager.vue new file mode 100644 index 0000000..125ee0a --- /dev/null +++ b/src/views/article/manager.vue @@ -0,0 +1,389 @@ + + diff --git a/src/views/article/publish.vue b/src/views/article/publish.vue new file mode 100644 index 0000000..cc36787 --- /dev/null +++ b/src/views/article/publish.vue @@ -0,0 +1,262 @@ + + + diff --git a/src/views/article/publishMoments.vue b/src/views/article/publishMoments.vue new file mode 100644 index 0000000..d23334e --- /dev/null +++ b/src/views/article/publishMoments.vue @@ -0,0 +1,163 @@ + + + diff --git a/src/views/components/CommonMenu/index.vue b/src/views/components/CommonMenu/index.vue new file mode 100644 index 0000000..20ba0f8 --- /dev/null +++ b/src/views/components/CommonMenu/index.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/views/components/Login/oauthLogin.vue b/src/views/components/Login/oauthLogin.vue new file mode 100644 index 0000000..8a31567 --- /dev/null +++ b/src/views/components/Login/oauthLogin.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/components/Login/phoneLogin.vue b/src/views/components/Login/phoneLogin.vue new file mode 100644 index 0000000..3712f20 --- /dev/null +++ b/src/views/components/Login/phoneLogin.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/src/views/components/Login/qrLogin.vue b/src/views/components/Login/qrLogin.vue new file mode 100644 index 0000000..629d8a1 --- /dev/null +++ b/src/views/components/Login/qrLogin.vue @@ -0,0 +1,100 @@ + + + diff --git a/src/views/components/dataScreen/doughnutCharts.vue b/src/views/components/dataScreen/doughnutCharts.vue new file mode 100644 index 0000000..6695876 --- /dev/null +++ b/src/views/components/dataScreen/doughnutCharts.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/components/dataScreen/full-screen-container.vue b/src/views/components/dataScreen/full-screen-container.vue new file mode 100644 index 0000000..cd32b26 --- /dev/null +++ b/src/views/components/dataScreen/full-screen-container.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/views/components/dataScreen/lineEcharts.vue b/src/views/components/dataScreen/lineEcharts.vue new file mode 100644 index 0000000..ce90102 --- /dev/null +++ b/src/views/components/dataScreen/lineEcharts.vue @@ -0,0 +1,106 @@ + + + diff --git a/src/views/components/dataScreen/migrationCharts/chinaMap.js b/src/views/components/dataScreen/migrationCharts/chinaMap.js new file mode 100644 index 0000000..917b199 --- /dev/null +++ b/src/views/components/dataScreen/migrationCharts/chinaMap.js @@ -0,0 +1,3043 @@ +export const geoJson = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + id: 'xin_jiang', + properties: { name: '新疆', cp: [84.9023, 41.748], childNum: 18 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [96.416, 42.7588], + [96.416, 42.7148], + [95.9766, 42.4951], + [96.0645, 42.3193], + [96.2402, 42.2314], + [95.9766, 41.9238], + [95.2734, 41.6162], + [95.1855, 41.792], + [94.5703, 41.4844], + [94.043, 41.0889], + [93.8672, 40.6934], + [93.0762, 40.6494], + [92.6367, 39.6387], + [92.373, 39.3311], + [92.373, 39.1113], + [92.373, 39.0234], + [90.1758, 38.4961], + [90.3516, 38.2324], + [90.6152, 38.3203], + [90.5273, 37.8369], + [91.0547, 37.4414], + [91.3184, 37.0898], + [90.7031, 36.7822], + [90.791, 36.6064], + [91.0547, 36.5186], + [91.0547, 36.0791], + [90.8789, 36.0352], + [90, 36.2549], + [89.9121, 36.0791], + [89.7363, 36.0791], + [89.209, 36.2988], + [88.7695, 36.3428], + [88.5938, 36.4746], + [87.3633, 36.4307], + [86.2207, 36.167], + [86.1328, 35.8594], + [85.6055, 35.6836], + [85.0781, 35.7275], + [84.1992, 35.376], + [83.1445, 35.4199], + [82.8809, 35.6836], + [82.4414, 35.7275], + [82.002, 35.332], + [81.6504, 35.2441], + [80.4199, 35.4199], + [80.2441, 35.2881], + [80.332, 35.1563], + [80.2441, 35.2002], + [79.8926, 34.8047], + [79.8047, 34.4971], + [79.1016, 34.4531], + [79.0137, 34.3213], + [78.2227, 34.7168], + [78.0469, 35.2441], + [78.0469, 35.5078], + [77.4316, 35.4639], + [76.8164, 35.6396], + [76.5527, 35.8594], + [76.2012, 35.8154], + [75.9375, 36.0352], + [76.0254, 36.4746], + [75.8496, 36.6943], + [75.498, 36.7383], + [75.4102, 36.958], + [75.0586, 37.002], + [74.8828, 36.9141], + [74.7949, 37.0459], + [74.5313, 37.0898], + [74.5313, 37.2217], + [74.8828, 37.2217], + [75.1465, 37.4414], + [74.8828, 37.5732], + [74.9707, 37.749], + [74.8828, 38.4521], + [74.3555, 38.6719], + [74.1797, 38.6719], + [74.0918, 38.54], + [73.8281, 38.584], + [73.7402, 38.8477], + [73.8281, 38.9795], + [73.4766, 39.375], + [73.916, 39.5068], + [73.916, 39.6826], + [73.8281, 39.7705], + [74.0039, 40.0342], + [74.8828, 40.3418], + [74.7949, 40.5176], + [75.2344, 40.4297], + [75.5859, 40.6494], + [75.7617, 40.2979], + [76.377, 40.3857], + [76.9043, 41.001], + [77.6074, 41.001], + [78.1348, 41.2207], + [78.1348, 41.3965], + [80.1563, 42.0557], + [80.2441, 42.2754], + [80.1563, 42.627], + [80.2441, 42.8467], + [80.5078, 42.8906], + [80.4199, 43.0664], + [80.7715, 43.1982], + [80.4199, 44.165], + [80.4199, 44.6045], + [79.9805, 44.8242], + [79.9805, 44.9561], + [81.7383, 45.3955], + [82.0898, 45.2197], + [82.5293, 45.2197], + [82.2656, 45.6592], + [83.0566, 47.2412], + [83.6719, 47.0215], + [84.7266, 47.0215], + [84.9023, 46.8896], + [85.5176, 47.0654], + [85.6934, 47.2852], + [85.5176, 48.1201], + [85.7813, 48.4277], + [86.5723, 48.5596], + [86.8359, 48.8232], + [86.748, 48.9551], + [86.8359, 49.1309], + [87.8027, 49.1748], + [87.8906, 48.999], + [87.7148, 48.9111], + [88.0664, 48.7354], + [87.9785, 48.6035], + [88.5059, 48.3838], + [88.6816, 48.1641], + [89.1211, 47.9883], + [89.5605, 48.0322], + [89.7363, 47.8564], + [90.0879, 47.8564], + [90.3516, 47.6807], + [90.5273, 47.2412], + [90.8789, 46.9775], + [91.0547, 46.582], + [90.8789, 46.3184], + [91.0547, 46.0107], + [90.7031, 45.7471], + [90.7031, 45.5273], + [90.8789, 45.2197], + [91.582, 45.0879], + [93.5156, 44.9561], + [94.7461, 44.3408], + [95.3613, 44.2969], + [95.3613, 44.0332], + [95.5371, 43.9014], + [95.8887, 43.2422], + [96.3281, 42.9346], + [96.416, 42.7588] + ] + ] + } + }, + { + type: 'Feature', + id: 'xi_zang', + properties: { name: '西藏', cp: [88.7695, 31.6846], childNum: 7 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [79.0137, 34.3213], + [79.1016, 34.4531], + [79.8047, 34.4971], + [79.8926, 34.8047], + [80.2441, 35.2002], + [80.332, 35.1563], + [80.2441, 35.2881], + [80.4199, 35.4199], + [81.6504, 35.2441], + [82.002, 35.332], + [82.4414, 35.7275], + [82.8809, 35.6836], + [83.1445, 35.4199], + [84.1992, 35.376], + [85.0781, 35.7275], + [85.6055, 35.6836], + [86.1328, 35.8594], + [86.2207, 36.167], + [87.3633, 36.4307], + [88.5938, 36.4746], + [88.7695, 36.3428], + [89.209, 36.2988], + [89.7363, 36.0791], + [89.3848, 36.0352], + [89.4727, 35.9033], + [89.7363, 35.7715], + [89.7363, 35.4199], + [89.4727, 35.376], + [89.4727, 35.2441], + [89.5605, 34.8926], + [89.8242, 34.8486], + [89.7363, 34.6729], + [89.8242, 34.3652], + [89.6484, 34.0137], + [90.0879, 33.4863], + [90.7031, 33.1348], + [91.4063, 33.1348], + [91.9336, 32.8271], + [92.1973, 32.8271], + [92.2852, 32.7393], + [92.9883, 32.7393], + [93.5156, 32.4756], + [93.7793, 32.5635], + [94.1309, 32.4316], + [94.6582, 32.6074], + [95.1855, 32.4316], + [95.0098, 32.2998], + [95.1855, 32.3438], + [95.2734, 32.2119], + [95.3613, 32.168], + [95.3613, 31.9922], + [95.4492, 31.8164], + [95.8008, 31.6846], + [95.9766, 31.8164], + [96.1523, 31.5967], + [96.2402, 31.9482], + [96.5039, 31.7285], + [96.8555, 31.6846], + [96.7676, 31.9922], + [97.2949, 32.0801], + [97.3828, 32.5635], + [97.7344, 32.5195], + [98.1738, 32.3438], + [98.4375, 31.8604], + [98.877, 31.4209], + [98.6133, 31.2012], + [98.9648, 30.7617], + [99.1406, 29.2676], + [98.9648, 29.1357], + [98.9648, 28.8281], + [98.7891, 28.8721], + [98.7891, 29.0039], + [98.7012, 28.916], + [98.6133, 28.5205], + [98.7891, 28.3447], + [98.7012, 28.2129], + [98.3496, 28.125], + [98.2617, 28.3887], + [98.1738, 28.125], + [97.5586, 28.5205], + [97.2949, 28.0811], + [97.3828, 27.9053], + [97.0313, 27.7295], + [96.5039, 28.125], + [95.7129, 28.2568], + [95.3613, 28.125], + [95.2734, 27.9492], + [94.2188, 27.5537], + [93.8672, 27.0264], + [93.6035, 26.9385], + [92.1094, 26.8506], + [92.0215, 27.4658], + [91.582, 27.5537], + [91.582, 27.9053], + [91.4063, 28.0371], + [91.0547, 27.8613], + [90.7031, 28.0811], + [89.8242, 28.2129], + [89.6484, 28.1689], + [89.1211, 27.5977], + [89.1211, 27.334], + [89.0332, 27.2021], + [88.7695, 27.4219], + [88.8574, 27.9932], + [88.6816, 28.125], + [88.1543, 27.9053], + [87.8906, 27.9492], + [87.7148, 27.8174], + [87.0996, 27.8174], + [86.748, 28.125], + [86.5723, 28.125], + [86.4844, 27.9053], + [86.1328, 28.125], + [86.0449, 27.9053], + [85.6934, 28.3447], + [85.6055, 28.2568], + [85.166, 28.3447], + [85.166, 28.6523], + [84.9023, 28.5645], + [84.4629, 28.7402], + [84.2871, 28.8721], + [84.1992, 29.2236], + [84.1113, 29.2676], + [83.584, 29.1797], + [83.2324, 29.5752], + [82.1777, 30.0586], + [82.0898, 30.3223], + [81.3867, 30.3662], + [81.2109, 30.0146], + [81.0352, 30.2344], + [80.0684, 30.5859], + [79.7168, 30.9375], + [79.0137, 31.0693], + [78.75, 31.333], + [78.8379, 31.5967], + [78.6621, 31.8164], + [78.75, 31.9043], + [78.4863, 32.124], + [78.3984, 32.5195], + [78.75, 32.6953], + [78.9258, 32.3438], + [79.2773, 32.5635], + [79.1016, 33.1787], + [78.6621, 33.6621], + [78.6621, 34.1016], + [78.9258, 34.1455], + [79.0137, 34.3213] + ] + ] + } + }, + { + type: 'Feature', + id: 'nei_meng_gu', + properties: { name: '内蒙古', cp: [117.5977, 44.3408], childNum: 12 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [97.207, 42.8027], + [99.4922, 42.583], + [100.8105, 42.6709], + [101.7773, 42.4951], + [102.041, 42.2314], + [102.7441, 42.1436], + [103.3594, 41.8799], + [103.8867, 41.792], + [104.502, 41.8799], + [104.502, 41.6602], + [105.0293, 41.5723], + [105.7324, 41.9238], + [107.4023, 42.4512], + [109.4238, 42.4512], + [110.3906, 42.7588], + [111.0059, 43.3301], + [111.9727, 43.6816], + [111.9727, 43.8135], + [111.4453, 44.3848], + [111.7969, 45], + [111.9727, 45.0879], + [113.6426, 44.7363], + [114.1699, 44.9561], + [114.5215, 45.3955], + [115.6641, 45.4395], + [116.1914, 45.7031], + [116.2793, 45.9668], + [116.543, 46.2744], + [117.334, 46.3623], + [117.4219, 46.582], + [117.7734, 46.5381], + [118.3008, 46.7578], + [118.7402, 46.7139], + [118.916, 46.7578], + [119.0918, 46.6699], + [119.707, 46.626], + [119.9707, 46.7139], + [119.707, 47.1973], + [118.4766, 47.9883], + [117.8613, 48.0322], + [117.334, 47.6807], + [116.8066, 47.9004], + [116.1914, 47.8564], + [115.9277, 47.6807], + [115.5762, 47.9004], + [115.4883, 48.1641], + [115.8398, 48.252], + [115.8398, 48.5596], + [116.7188, 49.834], + [117.7734, 49.5264], + [118.5645, 49.9219], + [119.2676, 50.0977], + [119.3555, 50.3174], + [119.1797, 50.3613], + [119.5313, 50.7568], + [119.5313, 50.8887], + [119.707, 51.0645], + [120.1465, 51.6797], + [120.6738, 51.9434], + [120.7617, 52.1191], + [120.7617, 52.251], + [120.5859, 52.3389], + [120.6738, 52.5146], + [120.4102, 52.6465], + [120.0586, 52.6025], + [120.0586, 52.7344], + [120.8496, 53.2617], + [121.4648, 53.3496], + [121.8164, 53.042], + [121.2012, 52.5586], + [121.6406, 52.4268], + [121.7285, 52.2949], + [121.9922, 52.2949], + [122.168, 52.5146], + [122.6953, 52.251], + [122.6074, 52.0752], + [122.959, 51.3281], + [123.3105, 51.2402], + [123.6621, 51.3721], + [124.3652, 51.2842], + [124.541, 51.3721], + [124.8926, 51.3721], + [125.0684, 51.6357], + [125.332, 51.6357], + [126.0352, 51.0205], + [125.7715, 50.7568], + [125.7715, 50.5371], + [125.332, 50.1416], + [125.1563, 49.834], + [125.2441, 49.1748], + [124.8047, 49.1309], + [124.4531, 48.1201], + [124.2773, 48.5156], + [122.4316, 47.373], + [123.0469, 46.7139], + [123.3984, 46.8896], + [123.3984, 46.9775], + [123.4863, 46.9775], + [123.5742, 46.8457], + [123.5742, 46.8896], + [123.5742, 46.6699], + [123.0469, 46.582], + [123.2227, 46.2305], + [122.7832, 46.0107], + [122.6953, 45.7031], + [122.4316, 45.8789], + [122.2559, 45.791], + [121.8164, 46.0107], + [121.7285, 45.7471], + [121.9043, 45.7031], + [122.2559, 45.2637], + [122.0801, 44.8682], + [122.3438, 44.2529], + [123.1348, 44.4727], + [123.4863, 43.7256], + [123.3105, 43.5059], + [123.6621, 43.374], + [123.5742, 43.0225], + [123.3105, 42.9785], + [123.1348, 42.8027], + [122.7832, 42.7148], + [122.3438, 42.8467], + [122.3438, 42.6709], + [121.9922, 42.7148], + [121.7285, 42.4512], + [121.4648, 42.4951], + [120.498, 42.0996], + [120.1465, 41.7041], + [119.8828, 42.1875], + [119.5313, 42.3633], + [119.3555, 42.2754], + [119.2676, 41.7041], + [119.4434, 41.6162], + [119.2676, 41.3086], + [118.3887, 41.3086], + [118.125, 41.748], + [118.3008, 41.792], + [118.3008, 42.0996], + [118.125, 42.0557], + [117.9492, 42.2314], + [118.0371, 42.4072], + [117.7734, 42.627], + [117.5098, 42.583], + [117.334, 42.4512], + [116.8945, 42.4072], + [116.8066, 42.0117], + [116.2793, 42.0117], + [116.0156, 41.792], + [115.9277, 41.9238], + [115.2246, 41.5723], + [114.9609, 41.6162], + [114.873, 42.0996], + [114.5215, 42.1436], + [114.1699, 41.792], + [114.2578, 41.5723], + [113.9063, 41.4404], + [113.9941, 41.2207], + [113.9063, 41.1328], + [114.082, 40.7373], + [114.082, 40.5176], + [113.8184, 40.5176], + [113.5547, 40.3418], + [113.2031, 40.3857], + [112.7637, 40.166], + [112.3242, 40.2539], + [111.9727, 39.5947], + [111.4453, 39.6387], + [111.3574, 39.4189], + [111.0938, 39.375], + [111.0938, 39.5947], + [110.6543, 39.2871], + [110.127, 39.4629], + [110.2148, 39.2871], + [109.8633, 39.2432], + [109.9512, 39.1553], + [108.9844, 38.3203], + [109.0723, 38.0127], + [108.8965, 37.9688], + [108.8086, 38.0127], + [108.7207, 37.7051], + [108.1934, 37.6172], + [107.666, 37.8809], + [107.3145, 38.1006], + [106.7871, 38.1885], + [106.5234, 38.3203], + [106.9629, 38.9795], + [106.7871, 39.375], + [106.3477, 39.2871], + [105.9082, 38.7158], + [105.8203, 37.793], + [104.3262, 37.4414], + [103.4473, 37.8369], + [103.3594, 38.0127], + [103.5352, 38.1445], + [103.4473, 38.3643], + [104.2383, 38.9795], + [104.0625, 39.4189], + [103.3594, 39.3311], + [103.0078, 39.1113], + [102.4805, 39.2432], + [101.8652, 39.1113], + [102.041, 38.8916], + [101.7773, 38.6719], + [101.3379, 38.7598], + [101.25, 39.0234], + [100.9863, 38.9355], + [100.8105, 39.4189], + [100.5469, 39.4189], + [100.0195, 39.7705], + [99.4922, 39.8584], + [100.1074, 40.2539], + [100.1953, 40.6494], + [99.9316, 41.001], + [99.2285, 40.8691], + [99.0527, 40.6934], + [98.9648, 40.7813], + [98.7891, 40.6055], + [98.5254, 40.7373], + [98.6133, 40.6494], + [98.3496, 40.5615], + [98.3496, 40.9131], + [97.4707, 41.4844], + [97.8223, 41.6162], + [97.8223, 41.748], + [97.207, 42.8027] + ] + ] + } + }, + { + type: 'Feature', + id: 'qing_hai', + properties: { name: '青海', cp: [96.2402, 35.4199], childNum: 8 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [89.7363, 36.0791], + [89.9121, 36.0791], + [90, 36.2549], + [90.8789, 36.0352], + [91.0547, 36.0791], + [91.0547, 36.5186], + [90.791, 36.6064], + [90.7031, 36.7822], + [91.3184, 37.0898], + [91.0547, 37.4414], + [90.5273, 37.8369], + [90.6152, 38.3203], + [90.3516, 38.2324], + [90.1758, 38.4961], + [92.373, 39.0234], + [92.373, 39.1113], + [93.1641, 39.1992], + [93.1641, 38.9795], + [93.6914, 38.9355], + [93.8672, 38.7158], + [94.3066, 38.7598], + [94.5703, 38.3643], + [95.0098, 38.4082], + [95.4492, 38.2764], + [95.7129, 38.3643], + [96.2402, 38.1006], + [96.416, 38.2324], + [96.6797, 38.1885], + [96.6797, 38.4521], + [97.1191, 38.584], + [97.0313, 39.1992], + [98.1738, 38.8037], + [98.3496, 39.0234], + [98.6133, 38.9355], + [98.7891, 39.0674], + [99.1406, 38.9355], + [99.8438, 38.3643], + [100.1953, 38.2764], + [100.0195, 38.4521], + [100.1074, 38.4961], + [100.459, 38.2764], + [100.7227, 38.2324], + [101.1621, 37.8369], + [101.5137, 37.8809], + [101.7773, 37.6172], + [101.9531, 37.7051], + [102.1289, 37.4414], + [102.5684, 37.1777], + [102.4805, 36.958], + [102.6563, 36.8262], + [102.5684, 36.7383], + [102.832, 36.3428], + [103.0078, 36.2549], + [102.9199, 36.0791], + [102.9199, 35.9033], + [102.6563, 35.7715], + [102.832, 35.5957], + [102.4805, 35.5957], + [102.3047, 35.4199], + [102.3926, 35.2002], + [101.9531, 34.8486], + [101.9531, 34.6289], + [102.2168, 34.4092], + [102.1289, 34.2773], + [101.6895, 34.1016], + [100.9863, 34.3652], + [100.8105, 34.2773], + [101.25, 33.6621], + [101.5137, 33.7061], + [101.6016, 33.5303], + [101.7773, 33.5303], + [101.6895, 33.3105], + [101.7773, 33.2227], + [101.6016, 33.1348], + [101.1621, 33.2227], + [101.25, 32.6953], + [100.7227, 32.6514], + [100.7227, 32.5195], + [100.3711, 32.7393], + [100.1074, 32.6514], + [100.1074, 32.8711], + [99.8438, 33.0029], + [99.7559, 32.7393], + [99.2285, 32.915], + [99.2285, 33.0469], + [98.877, 33.1787], + [98.4375, 34.0576], + [97.8223, 34.1895], + [97.6465, 34.1016], + [97.7344, 33.9258], + [97.3828, 33.8818], + [97.4707, 33.5742], + [97.7344, 33.3984], + [97.3828, 32.8711], + [97.4707, 32.6953], + [97.7344, 32.5195], + [97.3828, 32.5635], + [97.2949, 32.0801], + [96.7676, 31.9922], + [96.8555, 31.6846], + [96.5039, 31.7285], + [96.2402, 31.9482], + [96.1523, 31.5967], + [95.9766, 31.8164], + [95.8008, 31.6846], + [95.4492, 31.8164], + [95.3613, 31.9922], + [95.3613, 32.168], + [95.2734, 32.2119], + [95.1855, 32.3438], + [95.0098, 32.2998], + [95.1855, 32.4316], + [94.6582, 32.6074], + [94.1309, 32.4316], + [93.7793, 32.5635], + [93.5156, 32.4756], + [92.9883, 32.7393], + [92.2852, 32.7393], + [92.1973, 32.8271], + [91.9336, 32.8271], + [91.4063, 33.1348], + [90.7031, 33.1348], + [90.0879, 33.4863], + [89.6484, 34.0137], + [89.8242, 34.3652], + [89.7363, 34.6729], + [89.8242, 34.8486], + [89.5605, 34.8926], + [89.4727, 35.2441], + [89.4727, 35.376], + [89.7363, 35.4199], + [89.7363, 35.7715], + [89.4727, 35.9033], + [89.3848, 36.0352], + [89.7363, 36.0791] + ] + ] + } + }, + { + type: 'Feature', + id: 'si_chuan', + properties: { name: '四川', cp: [102.9199, 30.1904], childNum: 21 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [101.7773, 33.5303], + [101.8652, 33.5742], + [101.9531, 33.4424], + [101.8652, 33.0908], + [102.4805, 33.4424], + [102.2168, 33.9258], + [102.9199, 34.3213], + [103.0957, 34.1895], + [103.1836, 33.7939], + [104.1504, 33.6182], + [104.2383, 33.3984], + [104.4141, 33.3105], + [104.3262, 33.2227], + [104.4141, 33.0469], + [104.3262, 32.8711], + [104.4141, 32.7393], + [105.2051, 32.6074], + [105.3809, 32.7393], + [105.3809, 32.8711], + [105.4688, 32.915], + [105.5566, 32.7393], + [106.084, 32.8711], + [106.084, 32.7393], + [106.3477, 32.6514], + [107.0508, 32.6953], + [107.1387, 32.4756], + [107.2266, 32.4316], + [107.4023, 32.5195], + [108.0176, 32.168], + [108.2813, 32.2559], + [108.5449, 32.2119], + [108.3691, 32.168], + [108.2813, 31.9043], + [108.5449, 31.6846], + [108.1934, 31.5088], + [107.9297, 30.8496], + [107.4902, 30.8496], + [107.4023, 30.7617], + [107.4902, 30.6299], + [107.0508, 30.0146], + [106.7871, 30.0146], + [106.6113, 30.3223], + [106.2598, 30.1904], + [105.8203, 30.4541], + [105.6445, 30.2783], + [105.5566, 30.1025], + [105.7324, 29.8828], + [105.293, 29.5313], + [105.4688, 29.3115], + [105.7324, 29.2676], + [105.8203, 28.96], + [106.2598, 28.8721], + [106.3477, 28.5205], + [105.9961, 28.7402], + [105.6445, 28.4326], + [105.9082, 28.125], + [106.1719, 28.125], + [106.3477, 27.8174], + [105.6445, 27.6416], + [105.5566, 27.7734], + [105.293, 27.7295], + [105.2051, 27.9932], + [105.0293, 28.0811], + [104.8535, 27.9053], + [104.4141, 27.9492], + [104.3262, 28.0371], + [104.4141, 28.125], + [104.4141, 28.2568], + [104.2383, 28.4326], + [104.4141, 28.6084], + [103.8867, 28.6523], + [103.7988, 28.3008], + [103.4473, 28.125], + [103.4473, 27.7734], + [102.9199, 27.29], + [103.0078, 26.3672], + [102.6563, 26.1914], + [102.5684, 26.3672], + [102.1289, 26.1035], + [101.8652, 26.0596], + [101.6016, 26.2354], + [101.6895, 26.3672], + [101.4258, 26.5869], + [101.4258, 26.8066], + [101.4258, 26.7188], + [101.1621, 27.0264], + [101.1621, 27.1582], + [100.7227, 27.8613], + [100.3711, 27.8174], + [100.2832, 27.7295], + [100.0195, 28.125], + [100.1953, 28.3447], + [99.668, 28.8281], + [99.4043, 28.5205], + [99.4043, 28.1689], + [99.2285, 28.3008], + [99.1406, 29.2676], + [98.9648, 30.7617], + [98.6133, 31.2012], + [98.877, 31.4209], + [98.4375, 31.8604], + [98.1738, 32.3438], + [97.7344, 32.5195], + [97.4707, 32.6953], + [97.3828, 32.8711], + [97.7344, 33.3984], + [97.4707, 33.5742], + [97.3828, 33.8818], + [97.7344, 33.9258], + [97.6465, 34.1016], + [97.8223, 34.1895], + [98.4375, 34.0576], + [98.877, 33.1787], + [99.2285, 33.0469], + [99.2285, 32.915], + [99.7559, 32.7393], + [99.8438, 33.0029], + [100.1074, 32.8711], + [100.1074, 32.6514], + [100.3711, 32.7393], + [100.7227, 32.5195], + [100.7227, 32.6514], + [101.25, 32.6953], + [101.1621, 33.2227], + [101.6016, 33.1348], + [101.7773, 33.2227], + [101.6895, 33.3105], + [101.7773, 33.5303] + ] + ] + } + }, + { + type: 'Feature', + id: 'hei_long_jiang', + properties: { name: '黑龙江', cp: [128.1445, 48.5156], childNum: 13 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [121.4648, 53.3496], + [123.6621, 53.5693], + [124.8926, 53.0859], + [125.0684, 53.2178], + [125.5957, 53.0859], + [125.6836, 52.9102], + [126.123, 52.7783], + [126.0352, 52.6025], + [126.2109, 52.5146], + [126.3867, 52.2949], + [126.3867, 52.207], + [126.5625, 52.1631], + [126.4746, 51.9434], + [126.9141, 51.3721], + [126.8262, 51.2842], + [127.002, 51.3281], + [126.9141, 51.1084], + [127.2656, 50.7568], + [127.3535, 50.2734], + [127.6172, 50.2295], + [127.5293, 49.8779], + [127.793, 49.6143], + [128.7598, 49.5703], + [129.1113, 49.3506], + [129.4629, 49.4385], + [130.2539, 48.8672], + [130.6934, 48.8672], + [130.5176, 48.6475], + [130.8691, 48.2959], + [130.6934, 48.1201], + [131.0449, 47.6807], + [132.5391, 47.7246], + [132.627, 47.9443], + [133.0664, 48.1201], + [133.5059, 48.1201], + [134.209, 48.3838], + [135.0879, 48.4277], + [134.7363, 48.252], + [134.5605, 47.9883], + [134.7363, 47.6807], + [134.5605, 47.4609], + [134.3848, 47.4609], + [134.209, 47.2852], + [134.209, 47.1533], + [133.8574, 46.5381], + [133.9453, 46.2744], + [133.5059, 45.835], + [133.418, 45.5713], + [133.2422, 45.5273], + [133.0664, 45.1318], + [132.8906, 45.0439], + [131.9238, 45.3516], + [131.5723, 45.0439], + [131.0449, 44.8682], + [131.3086, 44.0771], + [131.2207, 43.7256], + [131.3086, 43.4619], + [130.8691, 43.418], + [130.5176, 43.6377], + [130.3418, 43.9893], + [129.9902, 43.8574], + [129.9023, 44.0332], + [129.8145, 43.9014], + [129.2871, 43.8135], + [129.1992, 43.5938], + [128.8477, 43.5498], + [128.4961, 44.165], + [128.4082, 44.4727], + [128.0566, 44.3408], + [128.0566, 44.1211], + [127.7051, 44.1211], + [127.5293, 44.6045], + [127.0898, 44.6045], + [127.002, 44.7803], + [127.0898, 45], + [126.9141, 45.1318], + [126.5625, 45.2637], + [126.0352, 45.1758], + [125.7715, 45.3076], + [125.6836, 45.5273], + [125.0684, 45.3955], + [124.8926, 45.5273], + [124.3652, 45.4395], + [124.0137, 45.7471], + [123.9258, 46.2305], + [123.2227, 46.2305], + [123.0469, 46.582], + [123.5742, 46.6699], + [123.5742, 46.8896], + [123.5742, 46.8457], + [123.4863, 46.9775], + [123.3984, 46.9775], + [123.3984, 46.8896], + [123.0469, 46.7139], + [122.4316, 47.373], + [124.2773, 48.5156], + [124.4531, 48.1201], + [124.8047, 49.1309], + [125.2441, 49.1748], + [125.1563, 49.834], + [125.332, 50.1416], + [125.7715, 50.5371], + [125.7715, 50.7568], + [126.0352, 51.0205], + [125.332, 51.6357], + [125.0684, 51.6357], + [124.8926, 51.3721], + [124.541, 51.3721], + [124.3652, 51.2842], + [123.6621, 51.3721], + [123.3105, 51.2402], + [122.959, 51.3281], + [122.6074, 52.0752], + [122.6953, 52.251], + [122.168, 52.5146], + [121.9922, 52.2949], + [121.7285, 52.2949], + [121.6406, 52.4268], + [121.2012, 52.5586], + [121.8164, 53.042], + [121.4648, 53.3496] + ] + ] + } + }, + { + type: 'Feature', + id: 'gan_su', + properties: { name: '甘肃', cp: [95.7129, 40.166], childNum: 14 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [96.416, 42.7148], + [97.207, 42.8027], + [97.8223, 41.748], + [97.8223, 41.6162], + [97.4707, 41.4844], + [98.3496, 40.9131], + [98.3496, 40.5615], + [98.6133, 40.6494], + [98.5254, 40.7373], + [98.7891, 40.6055], + [98.9648, 40.7813], + [99.0527, 40.6934], + [99.2285, 40.8691], + [99.9316, 41.001], + [100.1953, 40.6494], + [100.1074, 40.2539], + [99.4922, 39.8584], + [100.0195, 39.7705], + [100.5469, 39.4189], + [100.8105, 39.4189], + [100.9863, 38.9355], + [101.25, 39.0234], + [101.3379, 38.7598], + [101.7773, 38.6719], + [102.041, 38.8916], + [101.8652, 39.1113], + [102.4805, 39.2432], + [103.0078, 39.1113], + [103.3594, 39.3311], + [104.0625, 39.4189], + [104.2383, 38.9795], + [103.4473, 38.3643], + [103.5352, 38.1445], + [103.3594, 38.0127], + [103.4473, 37.8369], + [104.3262, 37.4414], + [104.5898, 37.4414], + [104.5898, 37.2217], + [104.8535, 37.2217], + [105.293, 36.8262], + [105.2051, 36.6943], + [105.4688, 36.123], + [105.293, 35.9912], + [105.3809, 35.7715], + [105.7324, 35.7275], + [105.8203, 35.5518], + [105.9961, 35.4639], + [105.9082, 35.4199], + [105.9961, 35.4199], + [106.084, 35.376], + [106.2598, 35.4199], + [106.3477, 35.2441], + [106.5234, 35.332], + [106.4355, 35.6836], + [106.6992, 35.6836], + [106.9629, 35.8154], + [106.875, 36.123], + [106.5234, 36.2549], + [106.5234, 36.4746], + [106.4355, 36.5625], + [106.6113, 36.7822], + [106.6113, 37.0898], + [107.3145, 37.0898], + [107.3145, 36.9141], + [108.7207, 36.3428], + [108.6328, 35.9912], + [108.5449, 35.8594], + [108.6328, 35.5518], + [108.5449, 35.2881], + [107.7539, 35.2881], + [107.7539, 35.1123], + [107.8418, 35.0244], + [107.666, 34.9365], + [107.2266, 34.8926], + [106.9629, 35.0684], + [106.6113, 35.0684], + [106.5234, 34.7607], + [106.3477, 34.585], + [106.6992, 34.3213], + [106.5234, 34.2773], + [106.6113, 34.1455], + [106.4355, 33.9258], + [106.5234, 33.5303], + [105.9961, 33.6182], + [105.7324, 33.3984], + [105.9961, 33.1787], + [105.9082, 33.0029], + [105.4688, 32.915], + [105.3809, 32.8711], + [105.3809, 32.7393], + [105.2051, 32.6074], + [104.4141, 32.7393], + [104.3262, 32.8711], + [104.4141, 33.0469], + [104.3262, 33.2227], + [104.4141, 33.3105], + [104.2383, 33.3984], + [104.1504, 33.6182], + [103.1836, 33.7939], + [103.0957, 34.1895], + [102.9199, 34.3213], + [102.2168, 33.9258], + [102.4805, 33.4424], + [101.8652, 33.0908], + [101.9531, 33.4424], + [101.8652, 33.5742], + [101.7773, 33.5303], + [101.6016, 33.5303], + [101.5137, 33.7061], + [101.25, 33.6621], + [100.8105, 34.2773], + [100.9863, 34.3652], + [101.6895, 34.1016], + [102.1289, 34.2773], + [102.2168, 34.4092], + [101.9531, 34.6289], + [101.9531, 34.8486], + [102.3926, 35.2002], + [102.3047, 35.4199], + [102.4805, 35.5957], + [102.832, 35.5957], + [102.6563, 35.7715], + [102.9199, 35.9033], + [102.9199, 36.0791], + [103.0078, 36.2549], + [102.832, 36.3428], + [102.5684, 36.7383], + [102.6563, 36.8262], + [102.4805, 36.958], + [102.5684, 37.1777], + [102.1289, 37.4414], + [101.9531, 37.7051], + [101.7773, 37.6172], + [101.5137, 37.8809], + [101.1621, 37.8369], + [100.7227, 38.2324], + [100.459, 38.2764], + [100.1074, 38.4961], + [100.0195, 38.4521], + [100.1953, 38.2764], + [99.8438, 38.3643], + [99.1406, 38.9355], + [98.7891, 39.0674], + [98.6133, 38.9355], + [98.3496, 39.0234], + [98.1738, 38.8037], + [97.0313, 39.1992], + [97.1191, 38.584], + [96.6797, 38.4521], + [96.6797, 38.1885], + [96.416, 38.2324], + [96.2402, 38.1006], + [95.7129, 38.3643], + [95.4492, 38.2764], + [95.0098, 38.4082], + [94.5703, 38.3643], + [94.3066, 38.7598], + [93.8672, 38.7158], + [93.6914, 38.9355], + [93.1641, 38.9795], + [93.1641, 39.1992], + [92.373, 39.1113], + [92.373, 39.3311], + [92.6367, 39.6387], + [93.0762, 40.6494], + [93.8672, 40.6934], + [94.043, 41.0889], + [94.5703, 41.4844], + [95.1855, 41.792], + [95.2734, 41.6162], + [95.9766, 41.9238], + [96.2402, 42.2314], + [96.0645, 42.3193], + [95.9766, 42.4951], + [96.416, 42.7148] + ] + ] + } + }, + { + type: 'Feature', + id: 'yun_nan', + properties: { name: '云南', cp: [101.8652, 25.1807], childNum: 16 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [98.1738, 28.125], + [98.2617, 28.3887], + [98.3496, 28.125], + [98.7012, 28.2129], + [98.7891, 28.3447], + [98.6133, 28.5205], + [98.7012, 28.916], + [98.7891, 29.0039], + [98.7891, 28.8721], + [98.9648, 28.8281], + [98.9648, 29.1357], + [99.1406, 29.2676], + [99.2285, 28.3008], + [99.4043, 28.1689], + [99.4043, 28.5205], + [99.668, 28.8281], + [100.1953, 28.3447], + [100.0195, 28.125], + [100.2832, 27.7295], + [100.3711, 27.8174], + [100.7227, 27.8613], + [101.1621, 27.1582], + [101.1621, 27.0264], + [101.4258, 26.7188], + [101.4258, 26.8066], + [101.4258, 26.5869], + [101.6895, 26.3672], + [101.6016, 26.2354], + [101.8652, 26.0596], + [102.1289, 26.1035], + [102.5684, 26.3672], + [102.6563, 26.1914], + [103.0078, 26.3672], + [102.9199, 27.29], + [103.4473, 27.7734], + [103.4473, 28.125], + [103.7988, 28.3008], + [103.8867, 28.6523], + [104.4141, 28.6084], + [104.2383, 28.4326], + [104.4141, 28.2568], + [104.4141, 28.125], + [104.3262, 28.0371], + [104.4141, 27.9492], + [104.8535, 27.9053], + [105.0293, 28.0811], + [105.2051, 27.9932], + [105.293, 27.7295], + [105.2051, 27.3779], + [104.5898, 27.334], + [104.4141, 27.4658], + [104.1504, 27.2461], + [103.8867, 27.4219], + [103.623, 27.0264], + [103.7109, 26.9824], + [103.7109, 26.7627], + [103.8867, 26.543], + [104.4141, 26.6748], + [104.6777, 26.4111], + [104.3262, 25.708], + [104.8535, 25.2246], + [104.5898, 25.0488], + [104.6777, 24.9609], + [104.502, 24.7412], + [104.6777, 24.3457], + [104.7656, 24.4775], + [105.0293, 24.4336], + [105.2051, 24.082], + [105.4688, 24.0381], + [105.5566, 24.126], + [105.9961, 24.126], + [106.1719, 23.8184], + [106.1719, 23.5547], + [105.6445, 23.4229], + [105.5566, 23.2031], + [105.293, 23.3789], + [104.8535, 23.1592], + [104.7656, 22.8516], + [104.3262, 22.6758], + [104.1504, 22.8076], + [103.9746, 22.5439], + [103.623, 22.7637], + [103.5352, 22.5879], + [103.3594, 22.8076], + [103.0957, 22.4561], + [102.4805, 22.7637], + [102.3047, 22.4121], + [101.8652, 22.3682], + [101.7773, 22.5], + [101.6016, 22.1924], + [101.8652, 21.6211], + [101.7773, 21.1377], + [101.6016, 21.2256], + [101.25, 21.1816], + [101.1621, 21.7529], + [100.6348, 21.4453], + [100.1074, 21.4893], + [99.9316, 22.0605], + [99.2285, 22.1484], + [99.4043, 22.5879], + [99.3164, 22.7197], + [99.4922, 23.0713], + [98.877, 23.2031], + [98.7012, 23.9502], + [98.877, 24.126], + [98.1738, 24.082], + [97.7344, 23.8623], + [97.5586, 23.9063], + [97.7344, 24.126], + [97.6465, 24.4336], + [97.5586, 24.4336], + [97.5586, 24.7412], + [97.7344, 24.8291], + [97.8223, 25.2686], + [98.1738, 25.4004], + [98.1738, 25.6201], + [98.3496, 25.5762], + [98.5254, 25.8398], + [98.7012, 25.8838], + [98.6133, 26.0596], + [98.7012, 26.1475], + [98.7891, 26.5869], + [98.7012, 27.5098], + [98.5254, 27.6416], + [98.3496, 27.5098], + [98.1738, 28.125] + ] + ] + } + }, + { + type: 'Feature', + id: 'guang_xi', + properties: { name: '广西', cp: [108.2813, 23.6426], childNum: 14 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.502, 24.7412], + [104.6777, 24.6094], + [105.2051, 24.9609], + [105.9961, 24.6533], + [106.1719, 24.7852], + [106.1719, 24.9609], + [106.875, 25.1807], + [107.0508, 25.2686], + [106.9629, 25.4883], + [107.2266, 25.6201], + [107.4902, 25.2246], + [107.7539, 25.2246], + [107.8418, 25.1367], + [108.1055, 25.2246], + [108.1934, 25.4443], + [108.3691, 25.5322], + [108.6328, 25.3125], + [108.6328, 25.5762], + [109.0723, 25.5322], + [108.9844, 25.752], + [109.3359, 25.708], + [109.5117, 26.0156], + [109.7754, 25.8838], + [109.9512, 26.1914], + [110.2148, 25.9717], + [110.5664, 26.3232], + [111.1816, 26.3232], + [111.2695, 26.2354], + [111.2695, 25.8838], + [111.4453, 25.8398], + [111.0059, 25.0049], + [111.0938, 24.9609], + [111.3574, 25.1367], + [111.5332, 24.6533], + [111.709, 24.7852], + [112.0605, 24.7412], + [111.8848, 24.6533], + [112.0605, 24.3457], + [111.8848, 24.2139], + [111.8848, 23.9941], + [111.7969, 23.8184], + [111.6211, 23.8184], + [111.6211, 23.6865], + [111.3574, 23.4668], + [111.4453, 23.0273], + [111.2695, 22.8076], + [110.7422, 22.5439], + [110.7422, 22.2803], + [110.6543, 22.1484], + [110.3027, 22.1484], + [110.3027, 21.8848], + [109.9512, 21.8408], + [109.8633, 21.665], + [109.7754, 21.6211], + [109.7754, 21.4014], + [109.5996, 21.4453], + [109.1602, 21.3574], + [109.248, 20.874], + [109.0723, 20.9619], + [109.0723, 21.5332], + [108.7207, 21.5332], + [108.6328, 21.665], + [108.2813, 21.4893], + [107.8418, 21.6211], + [107.4023, 21.6211], + [107.0508, 21.7969], + [107.0508, 21.9287], + [106.6992, 22.0166], + [106.6113, 22.4121], + [106.7871, 22.7637], + [106.6992, 22.8955], + [105.9082, 22.9395], + [105.5566, 23.0713], + [105.5566, 23.2031], + [105.6445, 23.4229], + [106.1719, 23.5547], + [106.1719, 23.8184], + [105.9961, 24.126], + [105.5566, 24.126], + [105.4688, 24.0381], + [105.2051, 24.082], + [105.0293, 24.4336], + [104.7656, 24.4775], + [104.6777, 24.3457], + [104.502, 24.7412] + ] + ] + } + }, + { + type: 'Feature', + id: 'hu_nan', + properties: { name: '湖南', cp: [111.5332, 27.3779], childNum: 14 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [109.248, 28.4766], + [109.248, 29.1357], + [109.5117, 29.6191], + [109.6875, 29.6191], + [109.7754, 29.751], + [110.4785, 29.6631], + [110.6543, 29.751], + [110.4785, 30.0146], + [110.8301, 30.1465], + [111.7969, 29.9268], + [112.2363, 29.5313], + [112.5, 29.6191], + [112.6758, 29.5752], + [112.9395, 29.7949], + [113.0273, 29.751], + [112.9395, 29.4873], + [113.0273, 29.4434], + [113.5547, 29.8389], + [113.5547, 29.707], + [113.7305, 29.5752], + [113.6426, 29.3115], + [113.7305, 29.0918], + [113.9063, 29.0479], + [114.1699, 28.8281], + [114.082, 28.5645], + [114.2578, 28.3447], + [113.7305, 27.9492], + [113.6426, 27.5977], + [113.6426, 27.3779], + [113.8184, 27.29], + [113.7305, 27.1143], + [113.9063, 26.9385], + [113.9063, 26.6309], + [114.082, 26.5869], + [113.9941, 26.1914], + [114.2578, 26.1475], + [113.9941, 26.0596], + [113.9063, 25.4443], + [113.6426, 25.3125], + [113.2031, 25.5322], + [112.8516, 25.3564], + [113.0273, 25.2246], + [113.0273, 24.9609], + [112.8516, 24.917], + [112.5879, 25.1367], + [112.2363, 25.1807], + [112.1484, 24.873], + [112.0605, 24.7412], + [111.709, 24.7852], + [111.5332, 24.6533], + [111.3574, 25.1367], + [111.0938, 24.9609], + [111.0059, 25.0049], + [111.4453, 25.8398], + [111.2695, 25.8838], + [111.2695, 26.2354], + [111.1816, 26.3232], + [110.5664, 26.3232], + [110.2148, 25.9717], + [109.9512, 26.1914], + [109.7754, 25.8838], + [109.5117, 26.0156], + [109.4238, 26.2793], + [109.248, 26.3232], + [109.4238, 26.5869], + [109.3359, 26.7188], + [109.5117, 26.8066], + [109.5117, 27.0264], + [109.3359, 27.1582], + [108.8965, 27.0264], + [108.8086, 27.1143], + [109.4238, 27.5977], + [109.3359, 27.9053], + [109.3359, 28.2568], + [109.248, 28.4766] + ] + ] + } + }, + { + type: 'Feature', + id: 'shan_xi_1', + properties: { name: '陕西', cp: [109.5996, 35.6396], childNum: 10 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [105.4688, 32.915], + [105.9082, 33.0029], + [105.9961, 33.1787], + [105.7324, 33.3984], + [105.9961, 33.6182], + [106.5234, 33.5303], + [106.4355, 33.9258], + [106.6113, 34.1455], + [106.5234, 34.2773], + [106.6992, 34.3213], + [106.3477, 34.585], + [106.5234, 34.7607], + [106.6113, 35.0684], + [106.9629, 35.0684], + [107.2266, 34.8926], + [107.666, 34.9365], + [107.8418, 35.0244], + [107.7539, 35.1123], + [107.7539, 35.2881], + [108.5449, 35.2881], + [108.6328, 35.5518], + [108.5449, 35.8594], + [108.6328, 35.9912], + [108.7207, 36.3428], + [107.3145, 36.9141], + [107.3145, 37.0898], + [107.3145, 37.6172], + [107.666, 37.8809], + [108.1934, 37.6172], + [108.7207, 37.7051], + [108.8086, 38.0127], + [108.8965, 37.9688], + [109.0723, 38.0127], + [108.9844, 38.3203], + [109.9512, 39.1553], + [109.8633, 39.2432], + [110.2148, 39.2871], + [110.127, 39.4629], + [110.6543, 39.2871], + [111.0938, 39.5947], + [111.0938, 39.375], + [111.1816, 39.2432], + [110.918, 38.7158], + [110.8301, 38.4961], + [110.4785, 38.1885], + [110.4785, 37.9688], + [110.8301, 37.6611], + [110.3906, 37.002], + [110.4785, 36.123], + [110.5664, 35.6396], + [110.2148, 34.8926], + [110.2148, 34.6729], + [110.3906, 34.585], + [110.4785, 34.2334], + [110.6543, 34.1455], + [110.6543, 33.8379], + [111.0059, 33.5303], + [111.0059, 33.2666], + [110.7422, 33.1348], + [110.5664, 33.2666], + [110.3027, 33.1787], + [109.5996, 33.2666], + [109.4238, 33.1348], + [109.7754, 33.0469], + [109.7754, 32.915], + [110.127, 32.7393], + [110.127, 32.6074], + [109.6875, 32.6074], + [109.5117, 32.4316], + [109.5996, 31.7285], + [109.248, 31.7285], + [109.0723, 31.9482], + [108.5449, 32.2119], + [108.2813, 32.2559], + [108.0176, 32.168], + [107.4023, 32.5195], + [107.2266, 32.4316], + [107.1387, 32.4756], + [107.0508, 32.6953], + [106.3477, 32.6514], + [106.084, 32.7393], + [106.084, 32.8711], + [105.5566, 32.7393], + [105.4688, 32.915] + ] + ] + } + }, + { + type: 'Feature', + id: 'guang_dong', + properties: { name: '广东', cp: [113.4668, 22.8076], childNum: 21 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [109.7754, 21.4014], + [109.7754, 21.6211], + [109.8633, 21.665], + [109.9512, 21.8408], + [110.3027, 21.8848], + [110.3027, 22.1484], + [110.6543, 22.1484], + [110.7422, 22.2803], + [110.7422, 22.5439], + [111.2695, 22.8076], + [111.4453, 23.0273], + [111.3574, 23.4668], + [111.6211, 23.6865], + [111.6211, 23.8184], + [111.7969, 23.8184], + [111.8848, 23.9941], + [111.8848, 24.2139], + [112.0605, 24.3457], + [111.8848, 24.6533], + [112.0605, 24.7412], + [112.1484, 24.873], + [112.2363, 25.1807], + [112.5879, 25.1367], + [112.8516, 24.917], + [113.0273, 24.9609], + [113.0273, 25.2246], + [112.8516, 25.3564], + [113.2031, 25.5322], + [113.6426, 25.3125], + [113.9063, 25.4443], + [113.9941, 25.2686], + [114.6094, 25.4004], + [114.7852, 25.2686], + [114.6973, 25.1367], + [114.4336, 24.9609], + [114.1699, 24.6973], + [114.4336, 24.5215], + [115.4004, 24.7852], + [115.8398, 24.5654], + [115.752, 24.7852], + [115.9277, 24.917], + [116.2793, 24.7852], + [116.3672, 24.873], + [116.543, 24.6094], + [116.7188, 24.6533], + [116.9824, 24.1699], + [116.9824, 23.9063], + [117.1582, 23.5547], + [117.334, 23.2471], + [116.8945, 23.3789], + [116.6309, 23.1152], + [116.543, 22.8516], + [115.9277, 22.7197], + [115.6641, 22.7637], + [115.5762, 22.6318], + [115.0488, 22.6758], + [114.6094, 22.3682], + [114.3457, 22.5439], + [113.9941, 22.5], + [113.8184, 22.1924], + [114.3457, 22.1484], + [114.4336, 22.0166], + [114.082, 21.9287], + [113.9941, 21.7969], + [113.5547, 22.0166], + [113.1152, 21.8408], + [112.9395, 21.5771], + [112.4121, 21.4453], + [112.2363, 21.5332], + [111.5332, 21.4893], + [111.2695, 21.3574], + [110.7422, 21.3574], + [110.6543, 21.2256], + [110.7422, 20.918], + [110.4785, 20.874], + [110.6543, 20.2588], + [110.5664, 20.2588], + [110.3906, 20.127], + [110.0391, 20.127], + [109.8633, 20.127], + [109.8633, 20.3027], + [109.5996, 20.918], + [109.7754, 21.4014], + [109.7754, 21.4014] + ], + [ + [113.5986, 22.1649], + [113.6096, 22.1265], + [113.5547, 22.11], + [113.5437, 22.2034], + [113.5767, 22.2034], + [113.5986, 22.1649] + ] + ] + } + }, + { + type: 'Feature', + id: 'ji_lin', + properties: { name: '吉林', cp: [126.4746, 43.5938], childNum: 9 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [123.2227, 46.2305], + [123.9258, 46.2305], + [124.0137, 45.7471], + [124.3652, 45.4395], + [124.8926, 45.5273], + [125.0684, 45.3955], + [125.6836, 45.5273], + [125.7715, 45.3076], + [126.0352, 45.1758], + [126.5625, 45.2637], + [126.9141, 45.1318], + [127.0898, 45], + [127.002, 44.7803], + [127.0898, 44.6045], + [127.5293, 44.6045], + [127.7051, 44.1211], + [128.0566, 44.1211], + [128.0566, 44.3408], + [128.4082, 44.4727], + [128.4961, 44.165], + [128.8477, 43.5498], + [129.1992, 43.5938], + [129.2871, 43.8135], + [129.8145, 43.9014], + [129.9023, 44.0332], + [129.9902, 43.8574], + [130.3418, 43.9893], + [130.5176, 43.6377], + [130.8691, 43.418], + [131.3086, 43.4619], + [131.3086, 43.3301], + [131.1328, 42.9346], + [130.4297, 42.7148], + [130.6055, 42.6709], + [130.6055, 42.4512], + [130.2539, 42.7588], + [130.2539, 42.8906], + [130.166, 42.9785], + [129.9023, 43.0225], + [129.7266, 42.4951], + [129.375, 42.4512], + [128.9355, 42.0117], + [128.0566, 42.0117], + [128.3203, 41.5723], + [128.1445, 41.3525], + [127.0898, 41.5283], + [127.1777, 41.5723], + [126.9141, 41.792], + [126.6504, 41.6602], + [126.4746, 41.3965], + [126.123, 40.957], + [125.6836, 40.8691], + [125.5957, 40.9131], + [125.7715, 41.2207], + [125.332, 41.6602], + [125.332, 41.9678], + [125.4199, 42.0996], + [125.332, 42.1436], + [124.8926, 42.8027], + [124.8926, 43.0664], + [124.7168, 43.0664], + [124.4531, 42.8467], + [124.2773, 43.2422], + [123.8379, 43.4619], + [123.6621, 43.374], + [123.3105, 43.5059], + [123.4863, 43.7256], + [123.1348, 44.4727], + [122.3438, 44.2529], + [122.0801, 44.8682], + [122.2559, 45.2637], + [121.9043, 45.7031], + [121.7285, 45.7471], + [121.8164, 46.0107], + [122.2559, 45.791], + [122.4316, 45.8789], + [122.6953, 45.7031], + [122.7832, 46.0107], + [123.2227, 46.2305] + ] + ] + } + }, + { + type: 'Feature', + id: 'he_bei', + properties: { name: '河北', cp: [115.4004, 37.9688], childNum: 11 }, + geometry: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [114.5215, 39.5068], + [114.3457, 39.8584], + [113.9941, 39.9902], + [114.5215, 40.3418], + [114.3457, 40.3857], + [114.2578, 40.6055], + [114.082, 40.7373], + [113.9063, 41.1328], + [113.9941, 41.2207], + [113.9063, 41.4404], + [114.2578, 41.5723], + [114.1699, 41.792], + [114.5215, 42.1436], + [114.873, 42.0996], + [114.9609, 41.6162], + [115.2246, 41.5723], + [115.9277, 41.9238], + [116.0156, 41.792], + [116.2793, 42.0117], + [116.8066, 42.0117], + [116.8945, 42.4072], + [117.334, 42.4512], + [117.5098, 42.583], + [117.7734, 42.627], + [118.0371, 42.4072], + [117.9492, 42.2314], + [118.125, 42.0557], + [118.3008, 42.0996], + [118.3008, 41.792], + [118.125, 41.748], + [118.3887, 41.3086], + [119.2676, 41.3086], + [118.8281, 40.8252], + [119.2676, 40.5176], + [119.5313, 40.5615], + [119.707, 40.1221], + [119.8828, 39.9463], + [119.5313, 39.6826], + [119.4434, 39.4189], + [118.916, 39.0674], + [118.4766, 38.9355], + [118.125, 39.0234], + [118.0371, 39.1992], + [118.0371, 39.2432], + [117.8613, 39.4189], + [117.9492, 39.5947], + [117.6855, 39.5947], + [117.5098, 39.7705], + [117.5098, 39.9902], + [117.6855, 39.9902], + [117.6855, 40.0781], + [117.4219, 40.21], + [117.2461, 40.5176], + [117.4219, 40.6494], + [116.9824, 40.6934], + [116.6309, 41.0449], + [116.3672, 40.9131], + [116.4551, 40.7813], + [116.1914, 40.7813], + [116.1035, 40.6055], + [115.752, 40.5615], + [115.9277, 40.2539], + [115.4004, 39.9463], + [115.4883, 39.6387], + [115.752, 39.5068], + [116.1914, 39.5947], + [116.3672, 39.4629], + [116.543, 39.5947], + [116.8066, 39.5947], + [116.8945, 39.1113], + [116.7188, 38.9355], + [116.7188, 38.8037], + [117.2461, 38.54], + [117.5977, 38.6279], + [117.9492, 38.3203], + [117.4219, 37.8369], + [116.8066, 37.8369], + [116.4551, 37.4854], + [116.2793, 37.5732], + [116.2793, 37.3535], + [116.0156, 37.3535], + [115.752, 36.9141], + [115.3125, 36.5186], + [115.4883, 36.167], + [115.3125, 36.0791], + [115.1367, 36.2109], + [114.9609, 36.0791], + [114.873, 36.123], + [113.7305, 36.3428], + [113.4668, 36.6504], + [113.7305, 36.8701], + [113.7305, 37.1338], + [114.1699, 37.6611], + [113.9941, 37.7051], + [113.8184, 38.1445], + [113.5547, 38.2764], + [113.5547, 38.54], + [113.8184, 38.8037], + [113.8184, 38.9355], + [113.9063, 39.0234], + [114.3457, 39.0674], + [114.5215, 39.5068] + ] + ], + [ + [ + [117.2461, 40.0781], + [117.1582, 39.8145], + [117.1582, 39.6387], + [116.8945, 39.6826], + [116.8945, 39.8145], + [116.8066, 39.9902], + [117.2461, 40.0781] + ] + ] + ] + } + }, + { + type: 'Feature', + id: 'hu_bei', + properties: { name: '湖北', cp: [112.2363, 31.1572], childNum: 17 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [110.2148, 31.1572], + [110.127, 31.377], + [109.6875, 31.5527], + [109.7754, 31.6846], + [109.5996, 31.7285], + [109.5117, 32.4316], + [109.6875, 32.6074], + [110.127, 32.6074], + [110.127, 32.7393], + [109.7754, 32.915], + [109.7754, 33.0469], + [109.4238, 33.1348], + [109.5996, 33.2666], + [110.3027, 33.1787], + [110.5664, 33.2666], + [110.7422, 33.1348], + [111.0059, 33.2666], + [111.5332, 32.6074], + [112.3242, 32.3438], + [113.2031, 32.4316], + [113.4668, 32.2998], + [113.7305, 32.4316], + [113.8184, 31.8604], + [113.9941, 31.7725], + [114.1699, 31.8604], + [114.5215, 31.7725], + [114.6094, 31.5527], + [114.7852, 31.4648], + [115.1367, 31.5967], + [115.2246, 31.4209], + [115.4004, 31.4209], + [115.5762, 31.2012], + [116.0156, 31.0254], + [115.752, 30.6738], + [116.1035, 30.1904], + [116.1035, 29.8389], + [115.9277, 29.707], + [115.4883, 29.7949], + [114.873, 29.3994], + [114.2578, 29.3555], + [113.9063, 29.0479], + [113.7305, 29.0918], + [113.6426, 29.3115], + [113.7305, 29.5752], + [113.5547, 29.707], + [113.5547, 29.8389], + [113.0273, 29.4434], + [112.9395, 29.4873], + [113.0273, 29.751], + [112.9395, 29.7949], + [112.6758, 29.5752], + [112.5, 29.6191], + [112.2363, 29.5313], + [111.7969, 29.9268], + [110.8301, 30.1465], + [110.4785, 30.0146], + [110.6543, 29.751], + [110.4785, 29.6631], + [109.7754, 29.751], + [109.6875, 29.6191], + [109.5117, 29.6191], + [109.248, 29.1357], + [109.0723, 29.3555], + [108.9844, 29.3115], + [108.6328, 29.8389], + [108.457, 29.7949], + [108.5449, 30.2344], + [108.457, 30.4102], + [108.6328, 30.5859], + [108.8086, 30.498], + [109.0723, 30.6299], + [109.1602, 30.542], + [109.248, 30.6299], + [109.4238, 30.542], + [109.8633, 30.8936], + [110.0391, 30.8057], + [110.2148, 31.1572] + ] + ] + } + }, + { + type: 'Feature', + id: 'gui_zhou', + properties: { name: '贵州', cp: [106.6113, 26.9385], childNum: 9 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.1504, 27.2461], + [104.4141, 27.4658], + [104.5898, 27.334], + [105.2051, 27.3779], + [105.293, 27.7295], + [105.5566, 27.7734], + [105.6445, 27.6416], + [106.3477, 27.8174], + [106.1719, 28.125], + [105.9082, 28.125], + [105.6445, 28.4326], + [105.9961, 28.7402], + [106.3477, 28.5205], + [106.5234, 28.5645], + [106.4355, 28.7842], + [106.5234, 28.7842], + [106.6113, 28.6523], + [106.6113, 28.5205], + [106.6992, 28.4766], + [106.875, 28.7842], + [107.4023, 28.8721], + [107.4023, 29.1797], + [107.5781, 29.2236], + [107.8418, 29.1357], + [107.8418, 29.0039], + [108.2813, 29.0918], + [108.3691, 28.6523], + [108.5449, 28.6523], + [108.5449, 28.3887], + [108.7207, 28.4766], + [108.7207, 28.2129], + [109.0723, 28.2129], + [109.248, 28.4766], + [109.3359, 28.2568], + [109.3359, 27.9053], + [109.4238, 27.5977], + [108.8086, 27.1143], + [108.8965, 27.0264], + [109.3359, 27.1582], + [109.5117, 27.0264], + [109.5117, 26.8066], + [109.3359, 26.7188], + [109.4238, 26.5869], + [109.248, 26.3232], + [109.4238, 26.2793], + [109.5117, 26.0156], + [109.3359, 25.708], + [108.9844, 25.752], + [109.0723, 25.5322], + [108.6328, 25.5762], + [108.6328, 25.3125], + [108.3691, 25.5322], + [108.1934, 25.4443], + [108.1055, 25.2246], + [107.8418, 25.1367], + [107.7539, 25.2246], + [107.4902, 25.2246], + [107.2266, 25.6201], + [106.9629, 25.4883], + [107.0508, 25.2686], + [106.875, 25.1807], + [106.1719, 24.9609], + [106.1719, 24.7852], + [105.9961, 24.6533], + [105.2051, 24.9609], + [104.6777, 24.6094], + [104.502, 24.7412], + [104.6777, 24.9609], + [104.5898, 25.0488], + [104.8535, 25.2246], + [104.3262, 25.708], + [104.6777, 26.4111], + [104.4141, 26.6748], + [103.8867, 26.543], + [103.7109, 26.7627], + [103.7109, 26.9824], + [103.623, 27.0264], + [103.8867, 27.4219], + [104.1504, 27.2461] + ] + ] + } + }, + { + type: 'Feature', + id: 'shan_dong', + properties: { name: '山东', cp: [118.7402, 36.4307], childNum: 17 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [115.4883, 36.167], + [115.3125, 36.5186], + [115.752, 36.9141], + [116.0156, 37.3535], + [116.2793, 37.3535], + [116.2793, 37.5732], + [116.4551, 37.4854], + [116.8066, 37.8369], + [117.4219, 37.8369], + [117.9492, 38.3203], + [118.125, 38.1445], + [118.916, 38.1445], + [119.3555, 37.6611], + [119.0039, 37.5293], + [119.0039, 37.3535], + [119.3555, 37.1338], + [119.707, 37.1338], + [119.8828, 37.3975], + [120.498, 37.8369], + [120.5859, 38.1445], + [120.9375, 38.4521], + [121.0254, 37.8369], + [121.2012, 37.6611], + [121.9043, 37.4854], + [122.168, 37.6172], + [122.2559, 37.4854], + [122.6074, 37.4854], + [122.6953, 37.3535], + [122.6074, 36.9141], + [122.4316, 36.7822], + [121.8164, 36.8701], + [121.7285, 36.6943], + [121.1133, 36.6064], + [121.1133, 36.4307], + [121.377, 36.2549], + [120.7617, 36.167], + [120.9375, 35.8594], + [120.6738, 36.0352], + [119.707, 35.4639], + [119.9707, 34.9805], + [119.3555, 35.0244], + [119.2676, 35.1123], + [118.916, 35.0244], + [118.7402, 34.7168], + [118.4766, 34.6729], + [118.3887, 34.4092], + [118.2129, 34.4092], + [118.125, 34.6289], + [117.9492, 34.6729], + [117.5977, 34.4531], + [117.334, 34.585], + [117.2461, 34.4531], + [116.8066, 34.9365], + [116.4551, 34.8926], + [116.3672, 34.6289], + [116.1914, 34.585], + [115.5762, 34.585], + [115.4004, 34.8486], + [114.7852, 35.0684], + [115.0488, 35.376], + [115.2246, 35.4199], + [115.4883, 35.7275], + [116.1035, 36.0791], + [115.3125, 35.8154], + [115.4883, 36.167] + ] + ] + } + }, + { + type: 'Feature', + id: 'jiang_xi', + properties: { name: '江西', cp: [116.0156, 27.29], childNum: 11 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [114.2578, 28.3447], + [114.082, 28.5645], + [114.1699, 28.8281], + [113.9063, 29.0479], + [114.2578, 29.3555], + [114.873, 29.3994], + [115.4883, 29.7949], + [115.9277, 29.707], + [116.1035, 29.8389], + [116.2793, 29.7949], + [116.7188, 30.0586], + [116.8945, 29.9268], + [116.7188, 29.751], + [116.7188, 29.6191], + [117.1582, 29.707], + [117.0703, 29.8389], + [117.1582, 29.9268], + [117.5098, 29.6191], + [118.0371, 29.5752], + [118.2129, 29.3994], + [118.0371, 29.1797], + [118.0371, 29.0479], + [118.3887, 28.7842], + [118.4766, 28.3447], + [118.4766, 28.3008], + [118.3008, 28.0811], + [117.7734, 27.8174], + [117.5098, 27.9932], + [116.9824, 27.6416], + [117.1582, 27.29], + [117.0703, 27.1143], + [116.543, 26.8066], + [116.6309, 26.4551], + [116.3672, 26.2354], + [116.4551, 26.1035], + [116.1914, 25.8838], + [116.0156, 25.2686], + [115.8398, 25.2246], + [115.9277, 24.917], + [115.752, 24.7852], + [115.8398, 24.5654], + [115.4004, 24.7852], + [114.4336, 24.5215], + [114.1699, 24.6973], + [114.4336, 24.9609], + [114.6973, 25.1367], + [114.7852, 25.2686], + [114.6094, 25.4004], + [113.9941, 25.2686], + [113.9063, 25.4443], + [113.9941, 26.0596], + [114.2578, 26.1475], + [113.9941, 26.1914], + [114.082, 26.5869], + [113.9063, 26.6309], + [113.9063, 26.9385], + [113.7305, 27.1143], + [113.8184, 27.29], + [113.6426, 27.3779], + [113.6426, 27.5977], + [113.7305, 27.9492], + [114.2578, 28.3447] + ] + ] + } + }, + { + type: 'Feature', + id: 'he_nan', + properties: { name: '河南', cp: [113.4668, 33.8818], childNum: 17 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [110.3906, 34.585], + [110.8301, 34.6289], + [111.1816, 34.8047], + [111.5332, 34.8486], + [111.7969, 35.0684], + [112.0605, 35.0684], + [112.0605, 35.2881], + [112.7637, 35.2002], + [113.1152, 35.332], + [113.6426, 35.6836], + [113.7305, 36.3428], + [114.873, 36.123], + [114.9609, 36.0791], + [115.1367, 36.2109], + [115.3125, 36.0791], + [115.4883, 36.167], + [115.3125, 35.8154], + [116.1035, 36.0791], + [115.4883, 35.7275], + [115.2246, 35.4199], + [115.0488, 35.376], + [114.7852, 35.0684], + [115.4004, 34.8486], + [115.5762, 34.585], + [116.1914, 34.585], + [116.1914, 34.4092], + [116.543, 34.2773], + [116.6309, 33.9258], + [116.1914, 33.7061], + [116.0156, 33.9697], + [115.6641, 34.0576], + [115.5762, 33.9258], + [115.5762, 33.6621], + [115.4004, 33.5303], + [115.3125, 33.1787], + [114.873, 33.1348], + [114.873, 33.0029], + [115.1367, 32.8711], + [115.2246, 32.6074], + [115.5762, 32.4316], + [115.8398, 32.5195], + [115.9277, 31.7725], + [115.4883, 31.6846], + [115.4004, 31.4209], + [115.2246, 31.4209], + [115.1367, 31.5967], + [114.7852, 31.4648], + [114.6094, 31.5527], + [114.5215, 31.7725], + [114.1699, 31.8604], + [113.9941, 31.7725], + [113.8184, 31.8604], + [113.7305, 32.4316], + [113.4668, 32.2998], + [113.2031, 32.4316], + [112.3242, 32.3438], + [111.5332, 32.6074], + [111.0059, 33.2666], + [111.0059, 33.5303], + [110.6543, 33.8379], + [110.6543, 34.1455], + [110.4785, 34.2334], + [110.3906, 34.585] + ] + ] + } + }, + { + type: 'Feature', + id: 'liao_ning', + properties: { name: '辽宁', cp: [122.3438, 41.0889], childNum: 14 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [119.2676, 41.3086], + [119.4434, 41.6162], + [119.2676, 41.7041], + [119.3555, 42.2754], + [119.5313, 42.3633], + [119.8828, 42.1875], + [120.1465, 41.7041], + [120.498, 42.0996], + [121.4648, 42.4951], + [121.7285, 42.4512], + [121.9922, 42.7148], + [122.3438, 42.6709], + [122.3438, 42.8467], + [122.7832, 42.7148], + [123.1348, 42.8027], + [123.3105, 42.9785], + [123.5742, 43.0225], + [123.6621, 43.374], + [123.8379, 43.4619], + [124.2773, 43.2422], + [124.4531, 42.8467], + [124.7168, 43.0664], + [124.8926, 43.0664], + [124.8926, 42.8027], + [125.332, 42.1436], + [125.4199, 42.0996], + [125.332, 41.9678], + [125.332, 41.6602], + [125.7715, 41.2207], + [125.5957, 40.9131], + [125.6836, 40.8691], + [124.541, 40.21], + [124.1016, 39.6826], + [123.3984, 39.6826], + [123.1348, 39.4189], + [123.1348, 39.0234], + [122.0801, 39.0234], + [121.5527, 38.7158], + [121.1133, 38.6719], + [120.9375, 38.9795], + [121.377, 39.1992], + [121.2012, 39.5508], + [122.0801, 40.3857], + [121.9922, 40.6934], + [121.7285, 40.8252], + [121.2012, 40.8252], + [120.5859, 40.21], + [119.8828, 39.9463], + [119.707, 40.1221], + [119.5313, 40.5615], + [119.2676, 40.5176], + [118.8281, 40.8252], + [119.2676, 41.3086] + ] + ] + } + }, + { + type: 'Feature', + id: 'shan_xi_2', + properties: { name: '山西', cp: [112.4121, 37.6611], childNum: 11 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [110.918, 38.7158], + [111.1816, 39.2432], + [111.0938, 39.375], + [111.3574, 39.4189], + [111.4453, 39.6387], + [111.9727, 39.5947], + [112.3242, 40.2539], + [112.7637, 40.166], + [113.2031, 40.3857], + [113.5547, 40.3418], + [113.8184, 40.5176], + [114.082, 40.5176], + [114.082, 40.7373], + [114.2578, 40.6055], + [114.3457, 40.3857], + [114.5215, 40.3418], + [113.9941, 39.9902], + [114.3457, 39.8584], + [114.5215, 39.5068], + [114.3457, 39.0674], + [113.9063, 39.0234], + [113.8184, 38.9355], + [113.8184, 38.8037], + [113.5547, 38.54], + [113.5547, 38.2764], + [113.8184, 38.1445], + [113.9941, 37.7051], + [114.1699, 37.6611], + [113.7305, 37.1338], + [113.7305, 36.8701], + [113.4668, 36.6504], + [113.7305, 36.3428], + [113.6426, 35.6836], + [113.1152, 35.332], + [112.7637, 35.2002], + [112.0605, 35.2881], + [112.0605, 35.0684], + [111.7969, 35.0684], + [111.5332, 34.8486], + [111.1816, 34.8047], + [110.8301, 34.6289], + [110.3906, 34.585], + [110.2148, 34.6729], + [110.2148, 34.8926], + [110.5664, 35.6396], + [110.4785, 36.123], + [110.3906, 37.002], + [110.8301, 37.6611], + [110.4785, 37.9688], + [110.4785, 38.1885], + [110.8301, 38.4961], + [110.918, 38.7158] + ] + ] + } + }, + { + type: 'Feature', + id: 'an_hui', + properties: { name: '安徽', cp: [117.2461, 32.0361], childNum: 17 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [116.6309, 33.9258], + [116.543, 34.2773], + [116.1914, 34.4092], + [116.1914, 34.585], + [116.3672, 34.6289], + [116.8945, 34.4092], + [117.1582, 34.0576], + [117.5977, 34.0137], + [117.7734, 33.7061], + [118.125, 33.75], + [117.9492, 33.2227], + [118.0371, 33.1348], + [118.2129, 33.2227], + [118.3008, 32.7832], + [118.7402, 32.7393], + [118.916, 32.959], + [119.1797, 32.8271], + [119.1797, 32.4756], + [118.5645, 32.5635], + [118.6523, 32.2119], + [118.4766, 32.168], + [118.3887, 31.9482], + [118.916, 31.5527], + [118.7402, 31.377], + [118.8281, 31.2451], + [119.3555, 31.2891], + [119.4434, 31.1572], + [119.6191, 31.1133], + [119.6191, 31.0693], + [119.4434, 30.6738], + [119.2676, 30.6299], + [119.3555, 30.4102], + [118.916, 30.3223], + [118.916, 29.9707], + [118.7402, 29.707], + [118.2129, 29.3994], + [118.0371, 29.5752], + [117.5098, 29.6191], + [117.1582, 29.9268], + [117.0703, 29.8389], + [117.1582, 29.707], + [116.7188, 29.6191], + [116.7188, 29.751], + [116.8945, 29.9268], + [116.7188, 30.0586], + [116.2793, 29.7949], + [116.1035, 29.8389], + [116.1035, 30.1904], + [115.752, 30.6738], + [116.0156, 31.0254], + [115.5762, 31.2012], + [115.4004, 31.4209], + [115.4883, 31.6846], + [115.9277, 31.7725], + [115.8398, 32.5195], + [115.5762, 32.4316], + [115.2246, 32.6074], + [115.1367, 32.8711], + [114.873, 33.0029], + [114.873, 33.1348], + [115.3125, 33.1787], + [115.4004, 33.5303], + [115.5762, 33.6621], + [115.5762, 33.9258], + [115.6641, 34.0576], + [116.0156, 33.9697], + [116.1914, 33.7061], + [116.6309, 33.9258] + ] + ] + } + }, + { + type: 'Feature', + id: 'fu_jian', + properties: { name: '福建', cp: [118.3008, 25.9277], childNum: 9 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [118.4766, 28.3008], + [118.8281, 28.2568], + [118.7402, 28.0371], + [118.916, 27.4658], + [119.2676, 27.4219], + [119.6191, 27.6855], + [119.7949, 27.29], + [120.2344, 27.4219], + [120.4102, 27.1582], + [120.7617, 27.0264], + [120.6738, 26.8945], + [120.2344, 26.8506], + [120.2344, 26.7188], + [120.4102, 26.6748], + [120.498, 26.3672], + [120.2344, 26.2793], + [120.4102, 26.1475], + [120.0586, 26.1914], + [119.9707, 25.9277], + [119.7949, 25.9277], + [119.9707, 25.4004], + [119.7949, 25.2686], + [119.5313, 25.1367], + [119.4434, 25.0049], + [119.2676, 25.0928], + [118.916, 24.8291], + [118.6523, 24.5215], + [118.4766, 24.5215], + [118.4766, 24.4336], + [118.2129, 24.3457], + [118.2129, 24.1699], + [117.8613, 23.9941], + [117.7734, 23.7744], + [117.5098, 23.5986], + [117.1582, 23.5547], + [116.9824, 23.9063], + [116.9824, 24.1699], + [116.7188, 24.6533], + [116.543, 24.6094], + [116.3672, 24.873], + [116.2793, 24.7852], + [115.9277, 24.917], + [115.8398, 25.2246], + [116.0156, 25.2686], + [116.1914, 25.8838], + [116.4551, 26.1035], + [116.3672, 26.2354], + [116.6309, 26.4551], + [116.543, 26.8066], + [117.0703, 27.1143], + [117.1582, 27.29], + [116.9824, 27.6416], + [117.5098, 27.9932], + [117.7734, 27.8174], + [118.3008, 28.0811], + [118.4766, 28.3008] + ] + ] + } + }, + { + type: 'Feature', + id: 'zhe_jiang', + properties: { name: '浙江', cp: [120.498, 29.0918], childNum: 11 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [118.2129, 29.3994], + [118.7402, 29.707], + [118.916, 29.9707], + [118.916, 30.3223], + [119.3555, 30.4102], + [119.2676, 30.6299], + [119.4434, 30.6738], + [119.6191, 31.0693], + [119.6191, 31.1133], + [119.9707, 31.1572], + [120.498, 30.8057], + [120.9375, 31.0254], + [121.2891, 30.6738], + [121.9922, 30.8057], + [122.6953, 30.8936], + [122.8711, 30.7178], + [122.959, 30.1465], + [122.6074, 30.1025], + [122.6074, 29.9268], + [122.168, 29.5313], + [122.3438, 28.8721], + [121.9922, 28.8721], + [121.9922, 28.4326], + [121.7285, 28.3447], + [121.7285, 28.2129], + [121.4648, 28.2129], + [121.5527, 28.0371], + [121.2891, 27.9492], + [121.1133, 27.4219], + [120.6738, 27.334], + [120.6738, 27.1582], + [120.9375, 27.0264], + [120.7617, 27.0264], + [120.4102, 27.1582], + [120.2344, 27.4219], + [119.7949, 27.29], + [119.6191, 27.6855], + [119.2676, 27.4219], + [118.916, 27.4658], + [118.7402, 28.0371], + [118.8281, 28.2568], + [118.4766, 28.3008], + [118.4766, 28.3447], + [118.3887, 28.7842], + [118.0371, 29.0479], + [118.0371, 29.1797], + [118.2129, 29.3994] + ] + ] + } + }, + { + type: 'Feature', + id: 'jiang_su', + properties: { name: '江苏', cp: [120.0586, 32.915], childNum: 13 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [116.3672, 34.6289], + [116.4551, 34.8926], + [116.8066, 34.9365], + [117.2461, 34.4531], + [117.334, 34.585], + [117.5977, 34.4531], + [117.9492, 34.6729], + [118.125, 34.6289], + [118.2129, 34.4092], + [118.3887, 34.4092], + [118.4766, 34.6729], + [118.7402, 34.7168], + [118.916, 35.0244], + [119.2676, 35.1123], + [119.3555, 35.0244], + [119.3555, 34.8486], + [119.707, 34.585], + [120.3223, 34.3652], + [120.9375, 33.0469], + [121.0254, 32.6514], + [121.377, 32.4756], + [121.4648, 32.168], + [121.9043, 31.9922], + [121.9922, 31.6846], + [121.9922, 31.5967], + [121.2012, 31.8604], + [121.1133, 31.7285], + [121.377, 31.5088], + [121.2012, 31.4648], + [120.9375, 31.0254], + [120.498, 30.8057], + [119.9707, 31.1572], + [119.6191, 31.1133], + [119.4434, 31.1572], + [119.3555, 31.2891], + [118.8281, 31.2451], + [118.7402, 31.377], + [118.916, 31.5527], + [118.3887, 31.9482], + [118.4766, 32.168], + [118.6523, 32.2119], + [118.5645, 32.5635], + [119.1797, 32.4756], + [119.1797, 32.8271], + [118.916, 32.959], + [118.7402, 32.7393], + [118.3008, 32.7832], + [118.2129, 33.2227], + [118.0371, 33.1348], + [117.9492, 33.2227], + [118.125, 33.75], + [117.7734, 33.7061], + [117.5977, 34.0137], + [117.1582, 34.0576], + [116.8945, 34.4092], + [116.3672, 34.6289] + ] + ] + } + }, + { + type: 'Feature', + id: 'chong_qing', + properties: { name: '重庆', cp: [107.7539, 30.1904], childNum: 40 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [108.5449, 31.6846], + [108.2813, 31.9043], + [108.3691, 32.168], + [108.5449, 32.2119], + [109.0723, 31.9482], + [109.248, 31.7285], + [109.5996, 31.7285], + [109.7754, 31.6846], + [109.6875, 31.5527], + [110.127, 31.377], + [110.2148, 31.1572], + [110.0391, 30.8057], + [109.8633, 30.8936], + [109.4238, 30.542], + [109.248, 30.6299], + [109.1602, 30.542], + [109.0723, 30.6299], + [108.8086, 30.498], + [108.6328, 30.5859], + [108.457, 30.4102], + [108.5449, 30.2344], + [108.457, 29.7949], + [108.6328, 29.8389], + [108.9844, 29.3115], + [109.0723, 29.3555], + [109.248, 29.1357], + [109.248, 28.4766], + [109.0723, 28.2129], + [108.7207, 28.2129], + [108.7207, 28.4766], + [108.5449, 28.3887], + [108.5449, 28.6523], + [108.3691, 28.6523], + [108.2813, 29.0918], + [107.8418, 29.0039], + [107.8418, 29.1357], + [107.5781, 29.2236], + [107.4023, 29.1797], + [107.4023, 28.8721], + [106.875, 28.7842], + [106.6992, 28.4766], + [106.6113, 28.5205], + [106.6113, 28.6523], + [106.5234, 28.7842], + [106.4355, 28.7842], + [106.5234, 28.5645], + [106.3477, 28.5205], + [106.2598, 28.8721], + [105.8203, 28.96], + [105.7324, 29.2676], + [105.4688, 29.3115], + [105.293, 29.5313], + [105.7324, 29.8828], + [105.5566, 30.1025], + [105.6445, 30.2783], + [105.8203, 30.4541], + [106.2598, 30.1904], + [106.6113, 30.3223], + [106.7871, 30.0146], + [107.0508, 30.0146], + [107.4902, 30.6299], + [107.4023, 30.7617], + [107.4902, 30.8496], + [107.9297, 30.8496], + [108.1934, 31.5088], + [108.5449, 31.6846] + ] + ] + } + }, + { + type: 'Feature', + id: 'ning_xia', + properties: { name: '宁夏', cp: [105.9961, 37.3096], childNum: 5 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [104.3262, 37.4414], + [105.8203, 37.793], + [105.9082, 38.7158], + [106.3477, 39.2871], + [106.7871, 39.375], + [106.9629, 38.9795], + [106.5234, 38.3203], + [106.7871, 38.1885], + [107.3145, 38.1006], + [107.666, 37.8809], + [107.3145, 37.6172], + [107.3145, 37.0898], + [106.6113, 37.0898], + [106.6113, 36.7822], + [106.4355, 36.5625], + [106.5234, 36.4746], + [106.5234, 36.2549], + [106.875, 36.123], + [106.9629, 35.8154], + [106.6992, 35.6836], + [106.4355, 35.6836], + [106.5234, 35.332], + [106.3477, 35.2441], + [106.2598, 35.4199], + [106.084, 35.376], + [105.9961, 35.4199], + [106.084, 35.4639], + [105.9961, 35.4639], + [105.8203, 35.5518], + [105.7324, 35.7275], + [105.3809, 35.7715], + [105.293, 35.9912], + [105.4688, 36.123], + [105.2051, 36.6943], + [105.293, 36.8262], + [104.8535, 37.2217], + [104.5898, 37.2217], + [104.5898, 37.4414], + [104.3262, 37.4414] + ] + ] + } + }, + { + type: 'Feature', + id: 'hai_nan', + properties: { name: '海南', cp: [109.9512, 19.2041], childNum: 18 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [108.6328, 19.3799], + [109.0723, 19.6436], + [109.248, 19.9512], + [109.5996, 20.0391], + [110.0391, 20.127], + [110.3906, 20.127], + [110.5664, 20.2588], + [110.6543, 20.2588], + [111.0938, 19.9512], + [111.2695, 19.9951], + [110.6543, 19.1602], + [110.5664, 18.6768], + [110.2148, 18.5889], + [110.0391, 18.3691], + [109.8633, 18.3691], + [109.6875, 18.1055], + [108.9844, 18.2813], + [108.6328, 18.457], + [108.6328, 19.3799] + ] + ] + } + }, + { + type: 'Feature', + id: 'tai_wan', + properties: { name: '台湾', cp: [121.0254, 23.5986], childNum: 1 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [121.9043, 25.0488], + [121.9922, 25.0049], + [121.8164, 24.7412], + [121.9043, 24.5654], + [121.6406, 24.0381], + [121.377, 23.1152], + [121.0254, 22.6758], + [120.8496, 22.0605], + [120.7617, 21.9287], + [120.6738, 22.3242], + [120.2344, 22.5879], + [120.0586, 23.0713], + [120.1465, 23.6865], + [121.0254, 25.0488], + [121.5527, 25.3125], + [121.9043, 25.0488] + ] + ] + } + }, + { + type: 'Feature', + id: 'bei_jing', + properties: { name: '北京', cp: [116.4551, 40.2539], childNum: 19 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [117.4219, 40.21], + [117.334, 40.1221], + [117.2461, 40.0781], + [116.8066, 39.9902], + [116.8945, 39.8145], + [116.8945, 39.6826], + [116.8066, 39.5947], + [116.543, 39.5947], + [116.3672, 39.4629], + [116.1914, 39.5947], + [115.752, 39.5068], + [115.4883, 39.6387], + [115.4004, 39.9463], + [115.9277, 40.2539], + [115.752, 40.5615], + [116.1035, 40.6055], + [116.1914, 40.7813], + [116.4551, 40.7813], + [116.3672, 40.9131], + [116.6309, 41.0449], + [116.9824, 40.6934], + [117.4219, 40.6494], + [117.2461, 40.5176], + [117.4219, 40.21] + ] + ] + } + }, + { + type: 'Feature', + id: 'tian_jin', + properties: { name: '天津', cp: [117.4219, 39.4189], childNum: 18 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [116.8066, 39.5947], + [116.8945, 39.6826], + [117.1582, 39.6387], + [117.1582, 39.8145], + [117.2461, 40.0781], + [117.334, 40.1221], + [117.4219, 40.21], + [117.6855, 40.0781], + [117.6855, 39.9902], + [117.5098, 39.9902], + [117.5098, 39.7705], + [117.6855, 39.5947], + [117.9492, 39.5947], + [117.8613, 39.4189], + [118.0371, 39.2432], + [118.0371, 39.1992], + [117.8613, 39.1113], + [117.5977, 38.6279], + [117.2461, 38.54], + [116.7188, 38.8037], + [116.7188, 38.9355], + [116.8945, 39.1113], + [116.8066, 39.5947] + ] + ] + } + }, + { + type: 'Feature', + id: 'shang_hai', + properties: { name: '上海', cp: [121.4648, 31.2891], childNum: 19 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [120.9375, 31.0254], + [121.2012, 31.4648], + [121.377, 31.5088], + [121.1133, 31.7285], + [121.2012, 31.8604], + [121.9922, 31.5967], + [121.9043, 31.1572], + [121.9922, 30.8057], + [121.2891, 30.6738], + [120.9375, 31.0254] + ] + ] + } + }, + { + type: 'Feature', + id: 'xiang_gang', + properties: { name: '香港', cp: [114.2578, 22.3242], childNum: 1 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [114.6094, 22.4121], + [114.5215, 22.1484], + [114.3457, 22.1484], + [113.9063, 22.1484], + [113.8184, 22.1924], + [113.9063, 22.4121], + [114.1699, 22.5439], + [114.3457, 22.5439], + [114.4336, 22.5439], + [114.4336, 22.4121], + [114.6094, 22.4121] + ] + ] + } + }, + { + type: 'Feature', + id: 'ao_men', + properties: { name: '澳门', cp: [113.5547, 22.1484], childNum: 1 }, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [113.5986, 22.1649], + [113.6096, 22.1265], + [113.5547, 22.11], + [113.5437, 22.2034], + [113.5767, 22.2034], + [113.5986, 22.1649] + ] + ] + } + } + ] +} diff --git a/src/views/components/dataScreen/migrationCharts/data.js b/src/views/components/dataScreen/migrationCharts/data.js new file mode 100644 index 0000000..7b6eeb4 --- /dev/null +++ b/src/views/components/dataScreen/migrationCharts/data.js @@ -0,0 +1,39 @@ +// logo所在城市数据 +export const cityIconData = [ + // { + // adcode: 650000, + // name: '新疆维吾尔自治区', + // value: [88.999903, 43.607078] + // }, + // { + // // adcode: 150000, + // name: '内蒙古自治区', + // value: [119.24787, 42.205741] + // }, + // , + // { + // // adcode: 150000, + // name: '内蒙古自治区', + // value: [110.627161, 41.16628] + // }, + // { + // // adcode: 540000, + // name: '西藏自治区', + // value: [89.483714, 30.251951] + // }, + // { + // // adcode: 630000, + // name: '青海省', + // value: [102.064693, 37.084008] + // }, + // { + // // adcode: 530000, + // name: '云南省', + // value: [102.187665, 25.083688] + // }, + // { + // // adcode: 610000, + // name: '陕西省', + // value: [109.20663, 35.018625] + // } +] diff --git a/src/views/components/dataScreen/migrationCharts/index.vue b/src/views/components/dataScreen/migrationCharts/index.vue new file mode 100644 index 0000000..5e52b08 --- /dev/null +++ b/src/views/components/dataScreen/migrationCharts/index.vue @@ -0,0 +1,318 @@ + + + diff --git a/src/views/components/dataScreen/simpleGauge.vue b/src/views/components/dataScreen/simpleGauge.vue new file mode 100644 index 0000000..8f5b63c --- /dev/null +++ b/src/views/components/dataScreen/simpleGauge.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/views/components/dictData.vue b/src/views/components/dictData.vue new file mode 100644 index 0000000..fbb2552 --- /dev/null +++ b/src/views/components/dictData.vue @@ -0,0 +1,416 @@ + + diff --git a/src/views/components/form/menuForm.vue b/src/views/components/form/menuForm.vue new file mode 100644 index 0000000..78421a7 --- /dev/null +++ b/src/views/components/form/menuForm.vue @@ -0,0 +1,333 @@ + + diff --git a/src/views/components/form/publishNoticeForm.vue b/src/views/components/form/publishNoticeForm.vue new file mode 100644 index 0000000..2697829 --- /dev/null +++ b/src/views/components/form/publishNoticeForm.vue @@ -0,0 +1,184 @@ + + diff --git a/src/views/components/icons/index.vue b/src/views/components/icons/index.vue new file mode 100644 index 0000000..9f1c9cd --- /dev/null +++ b/src/views/components/icons/index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/views/components/msgList.vue b/src/views/components/msgList.vue new file mode 100644 index 0000000..c3ea715 --- /dev/null +++ b/src/views/components/msgList.vue @@ -0,0 +1,179 @@ + + + + diff --git a/src/views/components/starBackground.vue b/src/views/components/starBackground.vue new file mode 100644 index 0000000..8456a24 --- /dev/null +++ b/src/views/components/starBackground.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/views/dashboard/BarChart.vue b/src/views/dashboard/BarChart.vue new file mode 100644 index 0000000..1dc3980 --- /dev/null +++ b/src/views/dashboard/BarChart.vue @@ -0,0 +1,99 @@ + + + diff --git a/src/views/dashboard/LineChart.vue b/src/views/dashboard/LineChart.vue new file mode 100644 index 0000000..5bbb456 --- /dev/null +++ b/src/views/dashboard/LineChart.vue @@ -0,0 +1,121 @@ + + + diff --git a/src/views/dashboard/PanelGroup.vue b/src/views/dashboard/PanelGroup.vue new file mode 100644 index 0000000..125702c --- /dev/null +++ b/src/views/dashboard/PanelGroup.vue @@ -0,0 +1,202 @@ + + + + + diff --git a/src/views/dashboard/PieChart.vue b/src/views/dashboard/PieChart.vue new file mode 100644 index 0000000..b06bdf2 --- /dev/null +++ b/src/views/dashboard/PieChart.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/views/dashboard/RaddarChart.vue b/src/views/dashboard/RaddarChart.vue new file mode 100644 index 0000000..1d9dd30 --- /dev/null +++ b/src/views/dashboard/RaddarChart.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/views/dashboard/WordCloud.vue b/src/views/dashboard/WordCloud.vue new file mode 100644 index 0000000..9b9bbb5 --- /dev/null +++ b/src/views/dashboard/WordCloud.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/dataScreen/index.scss b/src/views/dataScreen/index.scss new file mode 100644 index 0000000..daa2597 --- /dev/null +++ b/src/views/dataScreen/index.scss @@ -0,0 +1,169 @@ +.m-data-screen { + width: 1920px; + height: 1080px; + box-sizing: border-box; + overflow: hidden; + //background: url("/static/screen/bg.png") no-repeat center center; + background: #041c4a; + .header { + box-sizing: border-box; + width: 100%; + height: 91px; + background: url('@/assets/images/charts/header-bg.png'); + background-size: contain; + background-repeat: no-repeat; + display: flex; + align-items: center; + justify-content: center; + .header-bg-title { + font-size: 42px; + font-weight: normal; + font-stretch: normal; + letter-spacing: 2px; + color: #ffffff; + margin-bottom: 14px; + } + .date { + top: 25px; + line-height: 68px; + font-size: 18px; + position: absolute; + letter-spacing: 0px; + color: #87caff; + right: 20px; + } + } + .circle-bg { + animation: rotate 5s infinite linear; + } + @keyframes rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } + } + .center { + padding-left: 40px; + padding-right: 50px; + padding-bottom: 40px; + padding-top: 50px; + display: flex; + align-items: center; + justify-content: space-between; + .circle-bg { + animation: rotate 5s infinite linear; + } + @keyframes rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } + } + .item { + display: flex; + /*align-items: center;*/ + .item-icon { + width: 117px; + height: 109px; + } + .item-icon1 { + background: url('@/assets/images/charts/center-inner1.png') no-repeat center 43%; + } + .item-icon2 { + background: url('@/assets/images/charts/center-inner1.png') no-repeat center 43%; + } + .item-icon3 { + background: url('@/assets/images/charts/center-inner1.png') no-repeat center 43%; + } + .item-right { + margin-left: 20px; + .item-right-inner { + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + } + .text-title { + font-size: 20px; + letter-spacing: 1px; + color: #ffffff; + /*margin-bottom: 6px;*/ + /*height: 20px;*/ + } + .text-number { + font-size: 44px; + letter-spacing: 2px; + color: #00e4ff; + } + .text-der { + overflow: hidden; + box-sizing: border-box; + display: flex; + font-size: 16px; + color: #ffffff; + letter-spacing: 1px; + align-items: center; + .left { + margin-right: 10px; + } + img { + margin-right: 4px; + margin-top: 4px; + width: 11px; + height: 15px; + } + .right { + color: #00e4ff; + } + } + } + } + } + .footer { + position: relative; + padding: 0 30px 0 24px; + display: flex; + + .left { + box-sizing: border-box; + padding: 32px 0; + width: 568px; + //height: 701px; + + background-size: contain; + background-repeat: no-repeat; + } + .middle { + flex: 1; + position: relative; + .migration { + width: 100%; + height: 900px; + position: absolute; + } + } + .right { + width: 568px; + align-items: flex-end; + box-sizing: border-box; + padding: 32px 0; + display: flex; + flex-direction: column; + justify-content: space-between; + background-size: contain; + background-repeat: no-repeat; + } + .item-complex { + width: 558px; + height: 362px; + background-image: url('@/assets/images/charts/charts-bg.png'); + background-color: #042750; + background-size: contain; + background-repeat: no-repeat; + } + } +} diff --git a/src/views/dataScreen/index.vue b/src/views/dataScreen/index.vue new file mode 100644 index 0000000..1545a55 --- /dev/null +++ b/src/views/dataScreen/index.vue @@ -0,0 +1,129 @@ + + + diff --git a/src/views/error/401.vue b/src/views/error/401.vue new file mode 100644 index 0000000..1ba3792 --- /dev/null +++ b/src/views/error/401.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..f205303 --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/src/views/error/Error.vue b/src/views/error/Error.vue new file mode 100644 index 0000000..64505cf --- /dev/null +++ b/src/views/error/Error.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/views/index.vue b/src/views/index.vue new file mode 100644 index 0000000..e29bb4e --- /dev/null +++ b/src/views/index.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/src/views/index_v1.vue b/src/views/index_v1.vue new file mode 100644 index 0000000..e1c2bd6 --- /dev/null +++ b/src/views/index_v1.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/src/views/login.vue b/src/views/login.vue new file mode 100644 index 0000000..a70b3af --- /dev/null +++ b/src/views/login.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/src/views/monitor/SmsLog.vue b/src/views/monitor/SmsLog.vue new file mode 100644 index 0000000..b62742d --- /dev/null +++ b/src/views/monitor/SmsLog.vue @@ -0,0 +1,207 @@ + + + + diff --git a/src/views/monitor/SqlDiffLog.vue b/src/views/monitor/SqlDiffLog.vue new file mode 100644 index 0000000..d5f30fb --- /dev/null +++ b/src/views/monitor/SqlDiffLog.vue @@ -0,0 +1,335 @@ + + + + diff --git a/src/views/monitor/UserOnlineLog.vue b/src/views/monitor/UserOnlineLog.vue new file mode 100644 index 0000000..59cac42 --- /dev/null +++ b/src/views/monitor/UserOnlineLog.vue @@ -0,0 +1,198 @@ + + + + diff --git a/src/views/monitor/cache/index.vue b/src/views/monitor/cache/index.vue new file mode 100644 index 0000000..b0e2744 --- /dev/null +++ b/src/views/monitor/cache/index.vue @@ -0,0 +1,195 @@ + + + diff --git a/src/views/monitor/job/index.vue b/src/views/monitor/job/index.vue new file mode 100644 index 0000000..95eda6f --- /dev/null +++ b/src/views/monitor/job/index.vue @@ -0,0 +1,720 @@ + + + diff --git a/src/views/monitor/job/log.vue b/src/views/monitor/job/log.vue new file mode 100644 index 0000000..3175e07 --- /dev/null +++ b/src/views/monitor/job/log.vue @@ -0,0 +1,260 @@ + + + diff --git a/src/views/monitor/logininfor/index.vue b/src/views/monitor/logininfor/index.vue new file mode 100644 index 0000000..38340e9 --- /dev/null +++ b/src/views/monitor/logininfor/index.vue @@ -0,0 +1,196 @@ + + + diff --git a/src/views/monitor/onlineuser/index.vue b/src/views/monitor/onlineuser/index.vue new file mode 100644 index 0000000..7824256 --- /dev/null +++ b/src/views/monitor/onlineuser/index.vue @@ -0,0 +1,157 @@ + + + + diff --git a/src/views/monitor/operlog/index.vue b/src/views/monitor/operlog/index.vue new file mode 100644 index 0000000..84db809 --- /dev/null +++ b/src/views/monitor/operlog/index.vue @@ -0,0 +1,367 @@ + + + diff --git a/src/views/monitor/server/index.vue b/src/views/monitor/server/index.vue new file mode 100644 index 0000000..279f814 --- /dev/null +++ b/src/views/monitor/server/index.vue @@ -0,0 +1,299 @@ + + + + diff --git a/src/views/public/BannerConfig.vue b/src/views/public/BannerConfig.vue new file mode 100644 index 0000000..a78b803 --- /dev/null +++ b/src/views/public/BannerConfig.vue @@ -0,0 +1,425 @@ + + + + diff --git a/src/views/redirect/index.vue b/src/views/redirect/index.vue new file mode 100644 index 0000000..ff34a98 --- /dev/null +++ b/src/views/redirect/index.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/views/register.vue b/src/views/register.vue new file mode 100644 index 0000000..d7f2682 --- /dev/null +++ b/src/views/register.vue @@ -0,0 +1,221 @@ + + + + + diff --git a/src/views/socialLogin.vue b/src/views/socialLogin.vue new file mode 100644 index 0000000..dc247fe --- /dev/null +++ b/src/views/socialLogin.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/views/system/commonLang/index.vue b/src/views/system/commonLang/index.vue new file mode 100644 index 0000000..61ad85c --- /dev/null +++ b/src/views/system/commonLang/index.vue @@ -0,0 +1,468 @@ + + + + diff --git a/src/views/system/config/index.vue b/src/views/system/config/index.vue new file mode 100644 index 0000000..a035cc0 --- /dev/null +++ b/src/views/system/config/index.vue @@ -0,0 +1,258 @@ + + + diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue new file mode 100644 index 0000000..ea0c0f9 --- /dev/null +++ b/src/views/system/dept/index.vue @@ -0,0 +1,304 @@ + + + diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue new file mode 100644 index 0000000..e7ccdab --- /dev/null +++ b/src/views/system/dict/index.vue @@ -0,0 +1,323 @@ + + + diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..901bd30 --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,334 @@ + + + diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue new file mode 100644 index 0000000..93a114a --- /dev/null +++ b/src/views/system/notice/index.vue @@ -0,0 +1,219 @@ + + + + diff --git a/src/views/system/oauth/thirdAccount.vue b/src/views/system/oauth/thirdAccount.vue new file mode 100644 index 0000000..78a0c80 --- /dev/null +++ b/src/views/system/oauth/thirdAccount.vue @@ -0,0 +1,358 @@ + + + + diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue new file mode 100644 index 0000000..4abe1b5 --- /dev/null +++ b/src/views/system/post/index.vue @@ -0,0 +1,252 @@ + + + diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..39fe8de --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,669 @@ + + + + diff --git a/src/views/system/roleusers/index.vue b/src/views/system/roleusers/index.vue new file mode 100644 index 0000000..d34de4d --- /dev/null +++ b/src/views/system/roleusers/index.vue @@ -0,0 +1,300 @@ + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..8b4905a --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,655 @@ + + + + diff --git a/src/views/system/user/profile/index.vue b/src/views/system/user/profile/index.vue new file mode 100644 index 0000000..62e721e --- /dev/null +++ b/src/views/system/user/profile/index.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/src/views/system/user/profile/loginLog.vue b/src/views/system/user/profile/loginLog.vue new file mode 100644 index 0000000..191eb49 --- /dev/null +++ b/src/views/system/user/profile/loginLog.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/views/system/user/profile/operLog.vue b/src/views/system/user/profile/operLog.vue new file mode 100644 index 0000000..fe44c67 --- /dev/null +++ b/src/views/system/user/profile/operLog.vue @@ -0,0 +1,115 @@ + + + diff --git a/src/views/system/user/profile/resetPwd.vue b/src/views/system/user/profile/resetPwd.vue new file mode 100644 index 0000000..d095e54 --- /dev/null +++ b/src/views/system/user/profile/resetPwd.vue @@ -0,0 +1,64 @@ + + + diff --git a/src/views/system/user/profile/userAvatar.vue b/src/views/system/user/profile/userAvatar.vue new file mode 100644 index 0000000..f48902b --- /dev/null +++ b/src/views/system/user/profile/userAvatar.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/src/views/system/user/profile/userInfo.vue b/src/views/system/user/profile/userInfo.vue new file mode 100644 index 0000000..4dae5c4 --- /dev/null +++ b/src/views/system/user/profile/userInfo.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/views/tool/build/index.vue b/src/views/tool/build/index.vue new file mode 100644 index 0000000..1ebb0c7 --- /dev/null +++ b/src/views/tool/build/index.vue @@ -0,0 +1,15 @@ + + diff --git a/src/views/tool/codeCompare.vue b/src/views/tool/codeCompare.vue new file mode 100644 index 0000000..a279a8a --- /dev/null +++ b/src/views/tool/codeCompare.vue @@ -0,0 +1,56 @@ + + diff --git a/src/views/tool/email/emailLog.vue b/src/views/tool/email/emailLog.vue new file mode 100644 index 0000000..091b08a --- /dev/null +++ b/src/views/tool/email/emailLog.vue @@ -0,0 +1,261 @@ + + + + diff --git a/src/views/tool/email/emailTpl.vue b/src/views/tool/email/emailTpl.vue new file mode 100644 index 0000000..e169357 --- /dev/null +++ b/src/views/tool/email/emailTpl.vue @@ -0,0 +1,269 @@ + + + + diff --git a/src/views/tool/email/sendEmail.vue b/src/views/tool/email/sendEmail.vue new file mode 100644 index 0000000..96be8d4 --- /dev/null +++ b/src/views/tool/email/sendEmail.vue @@ -0,0 +1,204 @@ + + + diff --git a/src/views/tool/file/index.vue b/src/views/tool/file/index.vue new file mode 100644 index 0000000..aee90bf --- /dev/null +++ b/src/views/tool/file/index.vue @@ -0,0 +1,515 @@ + + + diff --git a/src/views/tool/gen/basicInfoForm.vue b/src/views/tool/gen/basicInfoForm.vue new file mode 100644 index 0000000..695e995 --- /dev/null +++ b/src/views/tool/gen/basicInfoForm.vue @@ -0,0 +1,46 @@ + + diff --git a/src/views/tool/gen/editTable.vue b/src/views/tool/gen/editTable.vue new file mode 100644 index 0000000..9af5643 --- /dev/null +++ b/src/views/tool/gen/editTable.vue @@ -0,0 +1,330 @@ + + + diff --git a/src/views/tool/gen/genInfoForm.vue b/src/views/tool/gen/genInfoForm.vue new file mode 100644 index 0000000..17681a6 --- /dev/null +++ b/src/views/tool/gen/genInfoForm.vue @@ -0,0 +1,516 @@ + + + diff --git a/src/views/tool/gen/importTable.vue b/src/views/tool/gen/importTable.vue new file mode 100644 index 0000000..7ca03d9 --- /dev/null +++ b/src/views/tool/gen/importTable.vue @@ -0,0 +1,110 @@ + + + diff --git a/src/views/tool/gen/index.vue b/src/views/tool/gen/index.vue new file mode 100644 index 0000000..bee1122 --- /dev/null +++ b/src/views/tool/gen/index.vue @@ -0,0 +1,311 @@ + + + + diff --git a/src/views/tool/swagger/index.vue b/src/views/tool/swagger/index.vue new file mode 100644 index 0000000..0e82527 --- /dev/null +++ b/src/views/tool/swagger/index.vue @@ -0,0 +1,30 @@ +