commit 0b3ec3e9445aad614707f086556988aa1315b7a9 Author: 王成明 <15110151257@163.com> Date: Sat Feb 8 09:23:28 2025 +0800 初始化 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.development b/.env.development new file mode 100644 index 0000000..25e7152 --- /dev/null +++ b/.env.development @@ -0,0 +1,20 @@ +# 页面标题 +VUE_APP_TITLE = 人机适配性高维数据管理平台 + +# 开发环境配置 +ENV = 'development' + +# 若依管理系统/开发环境 +VUE_APP_BASE_API = '/dev-api' + +# 应用访问路径 例如使用前缀 /admin/ +VUE_APP_CONTEXT_PATH = '/' + +# 监控地址 +VUE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/login' + +# xxl-job 控制台地址 +VUE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin' + +# 路由懒加载 +VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..b7b95ab --- /dev/null +++ b/.env.production @@ -0,0 +1,19 @@ +# 页面标题 +VUE_APP_TITLE = 人机适配性高维数据管理平台 + +# 生产环境配置 +ENV = 'production' + +# 若依管理系统/生产环境 +VUE_APP_BASE_API = '/prod-api' + +# 应用访问路径 例如使用前缀 /admin/ +VUE_APP_CONTEXT_PATH = '/' + +# 监控地址 +VUE_APP_MONITRO_ADMIN = '/admin/login' + +# xxl-job 控制台地址 +VUE_APP_XXL_JOB_ADMIN = '/xxl-job-admin' + + diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..89be6f6 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,10 @@ +# 忽略build目录下类型为js的文件的语法检查 +build/*.js +# 忽略src/assets目录下文件的语法检查 +src/assets +# 忽略public目录下文件的语法检查 +public +# 忽略当前目录下为js的文件的语法检查 +*.js +# 忽略当前目录下为vue的文件的语法检查 +*.vue \ 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/.gitignore b/.gitignore new file mode 100644 index 0000000..82c3521 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +**/*.log + +tests/**/coverage/ +tests/e2e/reports +selenium-debug.log + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.local + +package-lock.json +yarn.lock +dist.zip diff --git a/README.md b/README.md new file mode 100644 index 0000000..00c0ab8 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +## 开发 + +```bash +# 克隆项目 +git clone https://gitee.com/y_project/RuoYi-Vue + +# 进入项目目录 +cd ruoyi-ui + +# 安装依赖 +npm install + +# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 +npm install --registry=https://registry.npmmirror.com + +# 启动服务 +npm run dev +``` + +浏览器访问 http://localhost:80 + +## 发布 + +```bash +# 构建测试环境 +npm run build:stage + +# 构建生产环境 +npm run build:prod +``` \ No newline at end of file diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..b99f001 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + presets: [ + // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app + '@vue/cli-plugin-babel/preset' + ], + 'env': { + 'development': { + // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). + // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. + 'plugins': ['dynamic-import-node'] + } + } +} diff --git a/bin/build.bat b/bin/build.bat new file mode 100644 index 0000000..dda590d --- /dev/null +++ b/bin/build.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] Weḅdistļ +echo. + +%~d0 +cd %~dp0 + +cd .. +npm run build:prod + +pause \ No newline at end of file diff --git a/bin/package.bat b/bin/package.bat new file mode 100644 index 0000000..2f22a4a --- /dev/null +++ b/bin/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [信息] 安装Web工程,生成node_modules文件。 +echo. + +%~d0 +cd %~dp0 + +cd .. +npm install --registry=https://registry.npmmirror.com + +pause diff --git a/bin/run-web.bat b/bin/run-web.bat new file mode 100644 index 0000000..0318c52 --- /dev/null +++ b/bin/run-web.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [信息] 使用 Vue CLI 命令运行 Web 工程。 +echo. + +%~d0 +cd %~dp0 + +cd .. +npm run dev + +pause \ No newline at end of file diff --git a/build/index.js b/build/index.js new file mode 100644 index 0000000..0c57de2 --- /dev/null +++ b/build/index.js @@ -0,0 +1,35 @@ +const { run } = require('runjs') +const chalk = require('chalk') +const config = require('../vue.config.js') +const rawArgv = process.argv.slice(2) +const args = rawArgv.join(' ') + +if (process.env.npm_config_preview || rawArgv.includes('--preview')) { + const report = rawArgv.includes('--report') + + run(`vue-cli-service build ${args}`) + + const port = 9526 + const publicPath = config.publicPath + + var connect = require('connect') + var serveStatic = require('serve-static') + const app = connect() + + app.use( + publicPath, + serveStatic('./dist', { + index: ['index.html', '/'] + }) + ) + + app.listen(port, function () { + console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) + if (report) { + console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) + } + + }) +} else { + run(`vue-cli-service build ${args}`) +} diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..54abd39 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "target": "ES2020", + "jsx": "react", + "allowImportingTsExtensions": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1cffbd6 --- /dev/null +++ b/package.json @@ -0,0 +1,107 @@ +{ + "name": "ruoyi-vue-plus", + "version": "4.7.0", + "description": "人机适配性高维数据管理平台", + "author": "LionLi", + "license": "MIT", + "scripts": { + "dev": "vue-cli-service serve", + "build:prod": "vue-cli-service build", + "preview": "node build/index.js --preview", + "lint": "eslint --ext .js,.vue src" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "src/**/*.{js,vue}": [ + "eslint --fix", + "git add" + ] + }, + "keywords": [ + "vue", + "admin", + "dashboard", + "element-ui", + "boilerplate", + "admin-template", + "management-system" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/dromara/RuoYi-Vue-Plus.git" + }, + "dependencies": { + "@logicflow/core": "^2.0.7", + "@logicflow/extension": "^2.0.11", + "@riophae/vue-treeselect": "0.4.0", + "@tweenjs/tween.js": "^25.0.0", + "axios": "0.24.0", + "bignumber.js": "^9.1.2", + "clipboard": "2.0.8", + "core-js": "3.25.3", + "dayjs": "^1.11.10", + "echarts": "^5.4.1", + "el-table-virtual-scroll": "^2.0.1", + "element-ui": "2.15.12", + "file-saver": "2.0.5", + "fuse.js": "6.4.3", + "highlight.js": "9.18.5", + "html2canvas": "^1.4.1", + "js-beautify": "1.13.0", + "js-cookie": "3.0.1", + "jsencrypt": "3.0.0-rc.1", + "jspdf": "^2.5.1", + "lodash": "^4.17.21", + "mathlive-chinese": "^0.98.6", + "nprogress": "0.2.0", + "quill": "1.3.7", + "screenfull": "5.0.2", + "sortablejs": "1.10.2", + "three": "^0.164.1", + "vue": "2.6.12", + "vue-color": "^2.8.1", + "vue-count-to": "1.0.13", + "vue-cropper": "0.5.5", + "vue-echarts": "^6.7.1", + "vue-meta": "2.4.0", + "vue-resize": "^1.0.1", + "vue-router": "3.4.9", + "vuedraggable": "2.24.3", + "vuex": "3.6.0" + }, + "devDependencies": { + "@types/three": "^0.164.0", + "@vue/cli-plugin-babel": "4.4.6", + "@vue/cli-plugin-eslint": "4.4.6", + "@vue/cli-service": "4.4.6", + "@vue/composition-api": "^1.7.2", + "@vue/runtime-dom": "^3.4.23", + "babel-eslint": "10.1.0", + "babel-plugin-dynamic-import-node": "2.3.3", + "chalk": "4.1.0", + "compression-webpack-plugin": "5.0.2", + "connect": "3.6.6", + "eslint": "7.15.0", + "eslint-plugin-vue": "7.2.0", + "html-webpack-plugin": "^5.6.2", + "lint-staged": "10.5.3", + "runjs": "4.4.2", + "sass": "1.32.13", + "sass-loader": "10.1.1", + "script-ext-html-webpack-plugin": "2.1.5", + "svg-sprite-loader": "5.1.1", + "vue-template-compiler": "2.6.12" + }, + "engines": { + "node": ">=8.9", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ] +} diff --git a/public/J-20.glb b/public/J-20.glb new file mode 100644 index 0000000..1f92007 Binary files /dev/null and b/public/J-20.glb differ diff --git a/public/PL-15E.glb b/public/PL-15E.glb new file mode 100644 index 0000000..4fb0564 Binary files /dev/null and b/public/PL-15E.glb differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..5a9408d Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/fonts/KaTeX_AMS-Regular.woff2 b/public/fonts/KaTeX_AMS-Regular.woff2 new file mode 100644 index 0000000..0acaaff Binary files /dev/null and b/public/fonts/KaTeX_AMS-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Caligraphic-Bold.woff2 b/public/fonts/KaTeX_Caligraphic-Bold.woff2 new file mode 100644 index 0000000..f390922 Binary files /dev/null and b/public/fonts/KaTeX_Caligraphic-Bold.woff2 differ diff --git a/public/fonts/KaTeX_Caligraphic-Regular.woff2 b/public/fonts/KaTeX_Caligraphic-Regular.woff2 new file mode 100644 index 0000000..75344a1 Binary files /dev/null and b/public/fonts/KaTeX_Caligraphic-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Fraktur-Bold.woff2 b/public/fonts/KaTeX_Fraktur-Bold.woff2 new file mode 100644 index 0000000..395f28b Binary files /dev/null and b/public/fonts/KaTeX_Fraktur-Bold.woff2 differ diff --git a/public/fonts/KaTeX_Fraktur-Regular.woff2 b/public/fonts/KaTeX_Fraktur-Regular.woff2 new file mode 100644 index 0000000..735f694 Binary files /dev/null and b/public/fonts/KaTeX_Fraktur-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Main-Bold.woff2 b/public/fonts/KaTeX_Main-Bold.woff2 new file mode 100644 index 0000000..ab2ad21 Binary files /dev/null and b/public/fonts/KaTeX_Main-Bold.woff2 differ diff --git a/public/fonts/KaTeX_Main-BoldItalic.woff2 b/public/fonts/KaTeX_Main-BoldItalic.woff2 new file mode 100644 index 0000000..5931794 Binary files /dev/null and b/public/fonts/KaTeX_Main-BoldItalic.woff2 differ diff --git a/public/fonts/KaTeX_Main-Italic.woff2 b/public/fonts/KaTeX_Main-Italic.woff2 new file mode 100644 index 0000000..b50920e Binary files /dev/null and b/public/fonts/KaTeX_Main-Italic.woff2 differ diff --git a/public/fonts/KaTeX_Main-Regular.woff2 b/public/fonts/KaTeX_Main-Regular.woff2 new file mode 100644 index 0000000..eb24a7b Binary files /dev/null and b/public/fonts/KaTeX_Main-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Math-BoldItalic.woff2 b/public/fonts/KaTeX_Math-BoldItalic.woff2 new file mode 100644 index 0000000..2965702 Binary files /dev/null and b/public/fonts/KaTeX_Math-BoldItalic.woff2 differ diff --git a/public/fonts/KaTeX_Math-Italic.woff2 b/public/fonts/KaTeX_Math-Italic.woff2 new file mode 100644 index 0000000..215c143 Binary files /dev/null and b/public/fonts/KaTeX_Math-Italic.woff2 differ diff --git a/public/fonts/KaTeX_SansSerif-Bold.woff2 b/public/fonts/KaTeX_SansSerif-Bold.woff2 new file mode 100644 index 0000000..cfaa3bd Binary files /dev/null and b/public/fonts/KaTeX_SansSerif-Bold.woff2 differ diff --git a/public/fonts/KaTeX_SansSerif-Italic.woff2 b/public/fonts/KaTeX_SansSerif-Italic.woff2 new file mode 100644 index 0000000..349c06d Binary files /dev/null and b/public/fonts/KaTeX_SansSerif-Italic.woff2 differ diff --git a/public/fonts/KaTeX_SansSerif-Regular.woff2 b/public/fonts/KaTeX_SansSerif-Regular.woff2 new file mode 100644 index 0000000..a90eea8 Binary files /dev/null and b/public/fonts/KaTeX_SansSerif-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Script-Regular.woff2 b/public/fonts/KaTeX_Script-Regular.woff2 new file mode 100644 index 0000000..b3048fc Binary files /dev/null and b/public/fonts/KaTeX_Script-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Size1-Regular.woff2 b/public/fonts/KaTeX_Size1-Regular.woff2 new file mode 100644 index 0000000..c5a8462 Binary files /dev/null and b/public/fonts/KaTeX_Size1-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Size2-Regular.woff2 b/public/fonts/KaTeX_Size2-Regular.woff2 new file mode 100644 index 0000000..e1bccfe Binary files /dev/null and b/public/fonts/KaTeX_Size2-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Size3-Regular.woff2 b/public/fonts/KaTeX_Size3-Regular.woff2 new file mode 100644 index 0000000..249a286 Binary files /dev/null and b/public/fonts/KaTeX_Size3-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Size4-Regular.woff2 b/public/fonts/KaTeX_Size4-Regular.woff2 new file mode 100644 index 0000000..680c130 Binary files /dev/null and b/public/fonts/KaTeX_Size4-Regular.woff2 differ diff --git a/public/fonts/KaTeX_Typewriter-Regular.woff2 b/public/fonts/KaTeX_Typewriter-Regular.woff2 new file mode 100644 index 0000000..771f1af Binary files /dev/null and b/public/fonts/KaTeX_Typewriter-Regular.woff2 differ diff --git a/public/html/ie.html b/public/html/ie.html new file mode 100644 index 0000000..052ffcd --- /dev/null +++ b/public/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/public/images/menu/icon-component.svg b/public/images/menu/icon-component.svg new file mode 100644 index 0000000..3d94d1b --- /dev/null +++ b/public/images/menu/icon-component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-documentation.svg b/public/images/menu/icon-documentation.svg new file mode 100644 index 0000000..3a5a7f2 --- /dev/null +++ b/public/images/menu/icon-documentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-home.svg b/public/images/menu/icon-home.svg new file mode 100644 index 0000000..c3e3d2c --- /dev/null +++ b/public/images/menu/icon-home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-monitor.svg b/public/images/menu/icon-monitor.svg new file mode 100644 index 0000000..bc308cb --- /dev/null +++ b/public/images/menu/icon-monitor.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-shopping.svg b/public/images/menu/icon-shopping.svg new file mode 100644 index 0000000..0fa63c1 --- /dev/null +++ b/public/images/menu/icon-shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-system.svg b/public/images/menu/icon-system.svg new file mode 100644 index 0000000..6027fd6 --- /dev/null +++ b/public/images/menu/icon-system.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/menu/icon-tool.svg b/public/images/menu/icon-tool.svg new file mode 100644 index 0000000..48e0e35 --- /dev/null +++ b/public/images/menu/icon-tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..bf01e7d --- /dev/null +++ b/public/index.html @@ -0,0 +1,211 @@ + + + + + + + + + + + 人机适配性高维数据管理平台 + + + + + +
+
+
+
+
+
正在加载系统资源,请耐心等待
+
+
+ + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/public/sounds/keypress-delete.wav b/public/sounds/keypress-delete.wav new file mode 100644 index 0000000..e4a4af7 Binary files /dev/null and b/public/sounds/keypress-delete.wav differ diff --git a/public/sounds/keypress-return.wav b/public/sounds/keypress-return.wav new file mode 100644 index 0000000..8b666ce Binary files /dev/null and b/public/sounds/keypress-return.wav differ diff --git a/public/sounds/keypress-spacebar.wav b/public/sounds/keypress-spacebar.wav new file mode 100644 index 0000000..84743a0 Binary files /dev/null and b/public/sounds/keypress-spacebar.wav differ diff --git a/public/sounds/keypress-standard.wav b/public/sounds/keypress-standard.wav new file mode 100644 index 0000000..42dcef5 Binary files /dev/null and b/public/sounds/keypress-standard.wav differ diff --git a/public/sounds/plonk.wav b/public/sounds/plonk.wav new file mode 100644 index 0000000..ea05fc8 Binary files /dev/null and b/public/sounds/plonk.wav differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..1536a8a --- /dev/null +++ b/src/App.vue @@ -0,0 +1,118 @@ + + + + diff --git a/src/api/common.js b/src/api/common.js new file mode 100644 index 0000000..762ad20 --- /dev/null +++ b/src/api/common.js @@ -0,0 +1,52 @@ +import request from "@/utils/request"; +import qs from "querystring"; + +export const getAction = (url, params) => { + return request({ + url, + params, + method: "get", + }); +}; + +export const postAction = (url, data) => { + return request({ + url, + data, + method: "post", + }); +}; + +export const putAction = (url, data) => { + return request({ + url, + data, + method: "put", + }); +}; + +export const deleteAction = (url, data) => { + return request({ + url, + data, + method: "delete", + }); +}; + +export const exportFile = (url, data) => { + return request({ + url, + data, + method: "post", + responseType: "blob", + }); +}; + +export const exportFile1 = (url, params) => { + console.log(`${url}`); + return request({ + url: `${url}`, + method: "get", + responseType: "blob", + }); +}; diff --git a/src/api/demo/demo.js b/src/api/demo/demo.js new file mode 100644 index 0000000..04d4025 --- /dev/null +++ b/src/api/demo/demo.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 查询测试单表列表 +export function listDemo(query) { + return request({ + url: '/demo/demo/list', + method: 'get', + params: query + }) +} + +// 自定义分页接口 +export function pageDemo(query) { + return request({ + url: '/demo/demo/page', + method: 'get', + params: query + }) +} + +// 查询测试单表详细 +export function getDemo(id) { + return request({ + url: '/demo/demo/' + id, + method: 'get' + }) +} + +// 新增测试单表 +export function addDemo(data) { + return request({ + url: '/demo/demo', + method: 'post', + data: data + }) +} + +// 修改测试单表 +export function updateDemo(data) { + return request({ + url: '/demo/demo', + method: 'put', + data: data + }) +} + +// 删除测试单表 +export function delDemo(id) { + return request({ + url: '/demo/demo/' + id, + method: 'delete' + }) +} + diff --git a/src/api/demo/tree.js b/src/api/demo/tree.js new file mode 100644 index 0000000..4c7ebc0 --- /dev/null +++ b/src/api/demo/tree.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询测试树表列表 +export function listTree(query) { + return request({ + url: '/demo/tree/list', + method: 'get', + params: query + }) +} + +// 查询测试树表详细 +export function getTree(id) { + return request({ + url: '/demo/tree/' + id, + method: 'get' + }) +} + +// 新增测试树表 +export function addTree(data) { + return request({ + url: '/demo/tree', + method: 'post', + data: data + }) +} + +// 修改测试树表 +export function updateTree(data) { + return request({ + url: '/demo/tree', + method: 'put', + data: data + }) +} + +// 删除测试树表 +export function delTree(id) { + return request({ + url: '/demo/tree/' + id, + method: 'delete' + }) +} diff --git a/src/api/login.js b/src/api/login.js new file mode 100644 index 0000000..3c5bcfe --- /dev/null +++ b/src/api/login.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' + +// 登录方法 +export function login(username, password, code, uuid) { + const data = { + username, + password, + code, + uuid + } + return request({ + url: '/login', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 注册方法 +export function register(data) { + return request({ + url: '/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 获取用户详细信息 +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', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} + +// 短信验证码 +export function getCodeSms() { + return request({ + url: '/captchaSms', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} diff --git a/src/api/menu.js b/src/api/menu.js new file mode 100644 index 0000000..faef101 --- /dev/null +++ b/src/api/menu.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 获取路由 +export const getRouters = () => { + return request({ + url: '/getRouters', + method: 'get' + }) +} \ No newline at end of file diff --git a/src/api/monitor/cache.js b/src/api/monitor/cache.js new file mode 100644 index 0000000..5cf0517 --- /dev/null +++ b/src/api/monitor/cache.js @@ -0,0 +1,57 @@ +import request from '@/utils/request' + +// 查询缓存详细 +export function getCache() { + return request({ + url: '/monitor/cache', + method: 'get' + }) +} + +// 查询缓存名称列表 +export function listCacheName() { + return request({ + url: '/monitor/cache/getNames', + method: 'get' + }) +} + +// 查询缓存键名列表 +export function listCacheKey(cacheName) { + return request({ + url: '/monitor/cache/getKeys/' + cacheName, + method: 'get' + }) +} + +// 查询缓存内容 +export function getCacheValue(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey, + method: 'get' + }) +} + +// 清理指定名称缓存 +export function clearCacheName(cacheName) { + return request({ + url: '/monitor/cache/clearCacheName/' + cacheName, + method: 'delete' + }) +} + +// 清理指定键名缓存 +export function clearCacheKey(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/clearCacheKey/'+ cacheName + "/" + cacheKey, + method: 'delete' + }) +} + +// 清理全部缓存 +export function clearCacheAll() { + return request({ + url: '/monitor/cache/clearCacheAll', + method: 'delete' + }) +} diff --git a/src/api/monitor/logininfor.js b/src/api/monitor/logininfor.js new file mode 100644 index 0000000..4d112b7 --- /dev/null +++ b/src/api/monitor/logininfor.js @@ -0,0 +1,34 @@ +import request from '@/utils/request' + +// 查询登录日志列表 +export function list(query) { + return request({ + url: '/monitor/logininfor/list', + method: 'get', + params: query + }) +} + +// 删除登录日志 +export function delLogininfor(infoId) { + return request({ + url: '/monitor/logininfor/' + infoId, + method: 'delete' + }) +} + +// 解锁用户登录状态 +export function unlockLogininfor(userName) { + return request({ + url: '/monitor/logininfor/unlock/' + userName, + method: 'get' + }) +} + +// 清空登录日志 +export function cleanLogininfor() { + return request({ + url: '/monitor/logininfor/clean', + method: 'delete' + }) +} diff --git a/src/api/monitor/online.js b/src/api/monitor/online.js new file mode 100644 index 0000000..bd22137 --- /dev/null +++ b/src/api/monitor/online.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 查询在线用户列表 +export function list(query) { + return request({ + url: '/monitor/online/list', + method: 'get', + params: query + }) +} + +// 强退用户 +export function forceLogout(tokenId) { + return request({ + url: '/monitor/online/' + tokenId, + method: 'delete' + }) +} diff --git a/src/api/monitor/operlog.js b/src/api/monitor/operlog.js new file mode 100644 index 0000000..a04bca8 --- /dev/null +++ b/src/api/monitor/operlog.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 查询操作日志列表 +export function list(query) { + return request({ + url: '/monitor/operlog/list', + method: 'get', + params: query + }) +} + +// 删除操作日志 +export function delOperlog(operId) { + return request({ + url: '/monitor/operlog/' + operId, + method: 'delete' + }) +} + +// 清空操作日志 +export function cleanOperlog() { + return request({ + url: '/monitor/operlog/clean', + method: 'delete' + }) +} diff --git a/src/api/system/config.js b/src/api/system/config.js new file mode 100644 index 0000000..02f0cfc --- /dev/null +++ b/src/api/system/config.js @@ -0,0 +1,73 @@ +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 updateConfigByKey(key, value) { + return request({ + url: '/system/config/updateByKey', + method: 'put', + data: { + configKey: key, + configValue: value + } + }) +} + +// 删除参数配置 +export function delConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'delete' + }) +} + +// 刷新参数缓存 +export function refreshCache() { + return request({ + url: '/system/config/refreshCache', + method: 'delete' + }) +} + diff --git a/src/api/system/dept.js b/src/api/system/dept.js new file mode 100644 index 0000000..331c4b2 --- /dev/null +++ b/src/api/system/dept.js @@ -0,0 +1,52 @@ +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 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' + }) +} diff --git a/src/api/system/dict/data.js b/src/api/system/dict/data.js new file mode 100644 index 0000000..6c9eb79 --- /dev/null +++ b/src/api/system/dict/data.js @@ -0,0 +1,52 @@ +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/' + dictCode, + method: 'get' + }) +} + +// 根据字典类型查询字典数据信息 +export function getDicts(dictType) { + 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 delData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'delete' + }) +} diff --git a/src/api/system/dict/type.js b/src/api/system/dict/type.js new file mode 100644 index 0000000..a0254ba --- /dev/null +++ b/src/api/system/dict/type.js @@ -0,0 +1,60 @@ +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', + method: 'post', + data: data + }) +} + +// 修改字典类型 +export function updateType(data) { + return request({ + url: '/system/dict/type', + method: 'put', + data: data + }) +} + +// 删除字典类型 +export function delType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'delete' + }) +} + +// 刷新字典缓存 +export function refreshCache() { + return request({ + url: '/system/dict/type/refreshCache', + method: 'delete' + }) +} + +// 获取字典选择框列表 +export function optionselect() { + return request({ + url: '/system/dict/type/optionselect', + method: 'get' + }) +} diff --git a/src/api/system/menu.js b/src/api/system/menu.js new file mode 100644 index 0000000..f6415c6 --- /dev/null +++ b/src/api/system/menu.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询菜单列表 +export function listMenu(query) { + return request({ + url: '/system/menu/list', + method: 'get', + params: query + }) +} + +// 查询菜单详细 +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 function addMenu(data) { + return request({ + url: '/system/menu', + method: 'post', + data: data + }) +} + +// 修改菜单 +export function updateMenu(data) { + return request({ + url: '/system/menu', + method: 'put', + data: data + }) +} + +// 删除菜单 +export function delMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/src/api/system/notice.js b/src/api/system/notice.js new file mode 100644 index 0000000..c274ea5 --- /dev/null +++ b/src/api/system/notice.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询公告列表 +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' + }) +} \ No newline at end of file diff --git a/src/api/system/oss.js b/src/api/system/oss.js new file mode 100644 index 0000000..7d80026 --- /dev/null +++ b/src/api/system/oss.js @@ -0,0 +1,27 @@ +import request from '@/utils/request' + +// 查询OSS对象存储列表 +export function listOss(query) { + return request({ + url: '/system/oss/list', + method: 'get', + params: query + }) +} + +// 查询OSS对象基于id串 +export function listByIds(ossId) { + return request({ + url: '/system/oss/listByIds/' + ossId, + method: 'get' + }) +} + +// 删除OSS对象存储 +export function delOss(ossId) { + return request({ + url: '/system/oss/' + ossId, + method: 'delete' + }) +} + diff --git a/src/api/system/ossConfig.js b/src/api/system/ossConfig.js new file mode 100644 index 0000000..f290762 --- /dev/null +++ b/src/api/system/ossConfig.js @@ -0,0 +1,58 @@ +import request from '@/utils/request' + +// 查询对象存储配置列表 +export function listOssConfig(query) { + return request({ + url: '/system/oss/config/list', + method: 'get', + params: query + }) +} + +// 查询对象存储配置详细 +export function getOssConfig(ossConfigId) { + return request({ + url: '/system/oss/config/' + ossConfigId, + method: 'get' + }) +} + +// 新增对象存储配置 +export function addOssConfig(data) { + return request({ + url: '/system/oss/config', + method: 'post', + data: data + }) +} + +// 修改对象存储配置 +export function updateOssConfig(data) { + return request({ + url: '/system/oss/config', + method: 'put', + data: data + }) +} + +// 删除对象存储配置 +export function delOssConfig(ossConfigId) { + return request({ + url: '/system/oss/config/' + ossConfigId, + method: 'delete' + }) +} + +// 对象存储状态修改 +export function changeOssConfigStatus(ossConfigId, status, configKey) { + const data = { + ossConfigId, + status, + configKey + } + return request({ + url: '/system/oss/config/changeStatus', + method: 'put', + data: data + }) +} diff --git a/src/api/system/post.js b/src/api/system/post.js new file mode 100644 index 0000000..1a8e9ca --- /dev/null +++ b/src/api/system/post.js @@ -0,0 +1,44 @@ +import request 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' + }) +} diff --git a/src/api/system/role.js b/src/api/system/role.js new file mode 100644 index 0000000..f13e6f4 --- /dev/null +++ b/src/api/system/role.js @@ -0,0 +1,119 @@ +import request 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 function addRole(data) { + return request({ + url: '/system/role', + method: 'post', + data: data + }) +} + +// 修改角色 +export function updateRole(data) { + return request({ + url: '/system/role', + 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 allocatedUserList(query) { + return request({ + url: '/system/role/authUser/allocatedList', + method: 'get', + params: query + }) +} + +// 查询角色未授权用户列表 +export function unallocatedUserList(query) { + return request({ + url: '/system/role/authUser/unallocatedList', + method: 'get', + params: query + }) +} + +// 取消用户授权角色 +export function authUserCancel(data) { + return request({ + url: '/system/role/authUser/cancel', + method: 'put', + data: data + }) +} + +// 批量取消用户授权角色 +export function authUserCancelAll(data) { + return request({ + url: '/system/role/authUser/cancelAll', + method: 'put', + params: data + }) +} + +// 授权用户选择 +export function authUserSelectAll(data) { + return request({ + url: '/system/role/authUser/selectAll', + method: 'put', + params: data + }) +} + +// 根据角色ID查询部门树结构 +export function deptTreeSelect(roleId) { + return request({ + url: '/system/role/deptTree/' + roleId, + method: 'get' + }) +} diff --git a/src/api/system/user.js b/src/api/system/user.js new file mode 100644 index 0000000..f2f76ef --- /dev/null +++ b/src/api/system/user.js @@ -0,0 +1,135 @@ +import request from '@/utils/request' +import { parseStrEmpty } from "@/utils/ruoyi"; + +// 查询用户列表 +export function listUser(query) { + return request({ + url: '/system/user/list', + method: 'get', + params: query + }) +} + +// 查询用户详细 +export function getUser(userId) { + return request({ + url: '/system/user/' + parseStrEmpty(userId), + method: 'get' + }) +} + +// 新增用户 +export function addUser(data) { + return request({ + url: '/system/user', + method: 'post', + data: data + }) +} + +// 修改用户 +export function updateUser(data) { + return request({ + url: '/system/user', + method: 'put', + data: data + }) +} + +// 删除用户 +export function delUser(userId) { + return request({ + url: '/system/user/' + userId, + method: 'delete' + }) +} + +// 用户密码重置 +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 + }) +} + +// 查询授权角色 +export function getAuthRole(userId) { + return request({ + url: '/system/user/authRole/' + userId, + method: 'get' + }) +} + +// 保存授权角色 +export function updateAuthRole(data) { + return request({ + url: '/system/user/authRole', + method: 'put', + params: data + }) +} + +// 查询部门下拉树结构 +export function deptTreeSelect() { + return request({ + url: '/system/user/deptTree', + method: 'get' + }) +} diff --git a/src/api/tool/gen.js b/src/api/tool/gen.js new file mode 100644 index 0000000..65ddfea --- /dev/null +++ b/src/api/tool/gen.js @@ -0,0 +1,86 @@ +import request from '@/utils/request' + +// 查询生成表数据 +export function listTable(query) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/list', + method: 'get', + params: query + }) +} + +// 查询db数据库列表 +export function listDbTable(query) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/db/list', + method: 'get', + params: query + }) +} + +// 查询表详细信息 +export function getGenTable(tableId) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/' + tableId, + method: 'get' + }) +} + +// 修改代码生成信息 +export function updateGenTable(data) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen', + method: 'put', + data: data + }) +} + +// 导入表 +export function importTable(data) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/importTable', + method: 'post', + params: data + }) +} + +// 预览生成代码 +export function previewTable(tableId) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/preview/' + tableId, + method: 'get' + }) +} + +// 删除表数据 +export function delTable(tableId) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/' + tableId, + method: 'delete' + }) +} + +// 生成代码(自定义路径) +export function genCode(tableName) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/genCode/' + tableName, + method: 'get' + }) +} + +// 同步数据库 +export function synchDb(tableName) { + return request({ + headers: { 'datasource': localStorage.getItem("dataName") }, + url: '/tool/gen/synchDb/' + tableName, + method: 'get' + }) +} 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/font/Alibaba-PuHuiTi-Bold.otf b/src/assets/font/Alibaba-PuHuiTi-Bold.otf new file mode 100644 index 0000000..2ed2026 Binary files /dev/null and b/src/assets/font/Alibaba-PuHuiTi-Bold.otf differ diff --git a/src/assets/font/Alibaba-PuHuiTi-Heavy.otf b/src/assets/font/Alibaba-PuHuiTi-Heavy.otf new file mode 100644 index 0000000..28c3b45 Binary files /dev/null and b/src/assets/font/Alibaba-PuHuiTi-Heavy.otf differ diff --git a/src/assets/font/Alibaba-PuHuiTi-Light.otf b/src/assets/font/Alibaba-PuHuiTi-Light.otf new file mode 100644 index 0000000..3f4a6e3 Binary files /dev/null and b/src/assets/font/Alibaba-PuHuiTi-Light.otf differ diff --git a/src/assets/font/Alibaba-PuHuiTi-Medium.otf b/src/assets/font/Alibaba-PuHuiTi-Medium.otf new file mode 100644 index 0000000..a308250 Binary files /dev/null and b/src/assets/font/Alibaba-PuHuiTi-Medium.otf differ diff --git a/src/assets/font/Alibaba-PuHuiTi-Regular.otf b/src/assets/font/Alibaba-PuHuiTi-Regular.otf new file mode 100644 index 0000000..5960ba1 Binary files /dev/null and b/src/assets/font/Alibaba-PuHuiTi-Regular.otf differ diff --git a/src/assets/font/SourceHanSansCN-Bold.otf b/src/assets/font/SourceHanSansCN-Bold.otf new file mode 100644 index 0000000..4b3429a Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Bold.otf differ diff --git a/src/assets/font/SourceHanSansCN-ExtraLight.otf b/src/assets/font/SourceHanSansCN-ExtraLight.otf new file mode 100644 index 0000000..5cad7ff Binary files /dev/null and b/src/assets/font/SourceHanSansCN-ExtraLight.otf differ diff --git a/src/assets/font/SourceHanSansCN-Heavy.otf b/src/assets/font/SourceHanSansCN-Heavy.otf new file mode 100644 index 0000000..58e1ca5 Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Heavy.otf differ diff --git a/src/assets/font/SourceHanSansCN-Light.otf b/src/assets/font/SourceHanSansCN-Light.otf new file mode 100644 index 0000000..1cff8e6 Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Light.otf differ diff --git a/src/assets/font/SourceHanSansCN-Medium.otf b/src/assets/font/SourceHanSansCN-Medium.otf new file mode 100644 index 0000000..53e03e0 Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Medium.otf differ diff --git a/src/assets/font/SourceHanSansCN-Normal.otf b/src/assets/font/SourceHanSansCN-Normal.otf new file mode 100644 index 0000000..091f56d Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Normal.otf differ diff --git a/src/assets/font/SourceHanSansCN-Regular.otf b/src/assets/font/SourceHanSansCN-Regular.otf new file mode 100644 index 0000000..886f82f Binary files /dev/null and b/src/assets/font/SourceHanSansCN-Regular.otf differ diff --git a/src/assets/icons/index.js b/src/assets/icons/index.js new file mode 100644 index 0000000..2c6b309 --- /dev/null +++ b/src/assets/icons/index.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import SvgIcon from '@/components/SvgIcon'// svg component + +// register globally +Vue.component('svg-icon', SvgIcon) + +const req = require.context('./svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys().map(requireContext) +requireAll(req) diff --git a/src/assets/icons/svg/404.svg b/src/assets/icons/svg/404.svg new file mode 100644 index 0000000..6df5019 --- /dev/null +++ b/src/assets/icons/svg/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/bpmn-empty-state.svg b/src/assets/icons/svg/bpmn-empty-state.svg new file mode 100644 index 0000000..e86cfd0 --- /dev/null +++ b/src/assets/icons/svg/bpmn-empty-state.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/icons/svg/bpmn-icon-association.svg b/src/assets/icons/svg/bpmn-icon-association.svg new file mode 100644 index 0000000..f0cae69 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-association.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-business-rule-task.svg b/src/assets/icons/svg/bpmn-icon-business-rule-task.svg new file mode 100644 index 0000000..a083982 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-business-rule-task.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/icons/svg/bpmn-icon-call-activity.svg b/src/assets/icons/svg/bpmn-icon-call-activity.svg new file mode 100644 index 0000000..3041385 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-call-activity.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-collaboration.svg b/src/assets/icons/svg/bpmn-icon-collaboration.svg new file mode 100644 index 0000000..d125e12 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-collaboration.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/icons/svg/bpmn-icon-conditional-flow.svg b/src/assets/icons/svg/bpmn-icon-conditional-flow.svg new file mode 100644 index 0000000..5400c5b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-conditional-flow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-connection.svg b/src/assets/icons/svg/bpmn-icon-connection.svg new file mode 100644 index 0000000..da05686 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-connection.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-data-input-output-association.svg b/src/assets/icons/svg/bpmn-icon-data-input-output-association.svg new file mode 100644 index 0000000..4f15872 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-data-input-output-association.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/svg/bpmn-icon-data-input.svg b/src/assets/icons/svg/bpmn-icon-data-input.svg new file mode 100644 index 0000000..c3a6290 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-data-input.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-data-object.svg b/src/assets/icons/svg/bpmn-icon-data-object.svg new file mode 100644 index 0000000..c113fbc --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-data-object.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-data-output.svg b/src/assets/icons/svg/bpmn-icon-data-output.svg new file mode 100644 index 0000000..c01591c --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-data-output.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-data-store.svg b/src/assets/icons/svg/bpmn-icon-data-store.svg new file mode 100644 index 0000000..a09d62c --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-data-store.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-default-flow.svg b/src/assets/icons/svg/bpmn-icon-default-flow.svg new file mode 100644 index 0000000..b79e4a9 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-default-flow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-cancel.svg b/src/assets/icons/svg/bpmn-icon-end-event-cancel.svg new file mode 100644 index 0000000..c0b7c48 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-cancel.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-compensation.svg b/src/assets/icons/svg/bpmn-icon-end-event-compensation.svg new file mode 100644 index 0000000..fd49978 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-compensation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-error.svg b/src/assets/icons/svg/bpmn-icon-end-event-error.svg new file mode 100644 index 0000000..8242962 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-error.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-escalation.svg b/src/assets/icons/svg/bpmn-icon-end-event-escalation.svg new file mode 100644 index 0000000..ed25b7a --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-link.svg b/src/assets/icons/svg/bpmn-icon-end-event-link.svg new file mode 100644 index 0000000..a59062d --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-link.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-message.svg b/src/assets/icons/svg/bpmn-icon-end-event-message.svg new file mode 100644 index 0000000..6e3a35e --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-multiple.svg b/src/assets/icons/svg/bpmn-icon-end-event-multiple.svg new file mode 100644 index 0000000..d4bdeeb --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-none.svg b/src/assets/icons/svg/bpmn-icon-end-event-none.svg new file mode 100644 index 0000000..9a802c7 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-none.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-signal.svg b/src/assets/icons/svg/bpmn-icon-end-event-signal.svg new file mode 100644 index 0000000..8d546c1 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-end-event-terminate.svg b/src/assets/icons/svg/bpmn-icon-end-event-terminate.svg new file mode 100644 index 0000000..f2b958a --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-end-event-terminate.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-event-subprocess-expanded.svg b/src/assets/icons/svg/bpmn-icon-event-subprocess-expanded.svg new file mode 100644 index 0000000..25d344e --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-event-subprocess-expanded.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-complex.svg b/src/assets/icons/svg/bpmn-icon-gateway-complex.svg new file mode 100644 index 0000000..392618f --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-complex.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-eventbased.svg b/src/assets/icons/svg/bpmn-icon-gateway-eventbased.svg new file mode 100644 index 0000000..9c7eddc --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-eventbased.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-none.svg b/src/assets/icons/svg/bpmn-icon-gateway-none.svg new file mode 100644 index 0000000..652f58c --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-none.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-or.svg b/src/assets/icons/svg/bpmn-icon-gateway-or.svg new file mode 100644 index 0000000..2dc1aa3 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-or.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-parallel.svg b/src/assets/icons/svg/bpmn-icon-gateway-parallel.svg new file mode 100644 index 0000000..25e4413 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-parallel.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-gateway-xor.svg b/src/assets/icons/svg/bpmn-icon-gateway-xor.svg new file mode 100644 index 0000000..c077770 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-gateway-xor.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-group.svg b/src/assets/icons/svg/bpmn-icon-group.svg new file mode 100644 index 0000000..0e3624d --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-group.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-cancel.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-cancel.svg new file mode 100644 index 0000000..a9bc77b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-cancel.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-compensation.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-compensation.svg new file mode 100644 index 0000000..bdc0285 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-compensation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-condition.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-condition.svg new file mode 100644 index 0000000..49f8d7a --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-condition.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-error.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-error.svg new file mode 100644 index 0000000..d158de0 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-error.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-escalation.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-escalation.svg new file mode 100644 index 0000000..acd0956 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-link.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-link.svg new file mode 100644 index 0000000..0355de0 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-link.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-message.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-message.svg new file mode 100644 index 0000000..0bd75bc --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-multiple.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-multiple.svg new file mode 100644 index 0000000..8043c92 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-condition.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-condition.svg new file mode 100644 index 0000000..d53fd5a --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-condition.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-escalation.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-escalation.svg new file mode 100644 index 0000000..b391196 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-message.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-message.svg new file mode 100644 index 0000000..e3b7c5e --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-multiple.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-multiple.svg new file mode 100644 index 0000000..5fd199e --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-parallel.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-parallel.svg new file mode 100644 index 0000000..64f3f33 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-parallel.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-signal.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-signal.svg new file mode 100644 index 0000000..2a1263f --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-timer.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-timer.svg new file mode 100644 index 0000000..58655ba --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-non-interrupting-timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-parallel-multiple.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-parallel-multiple.svg new file mode 100644 index 0000000..83d5862 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-parallel-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-signal.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-signal.svg new file mode 100644 index 0000000..5190d22 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-timer.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-timer.svg new file mode 100644 index 0000000..2b20e28 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-catch-timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-none.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-none.svg new file mode 100644 index 0000000..80b05f1 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-none.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-compensation.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-compensation.svg new file mode 100644 index 0000000..e55a5a8 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-compensation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-escalation.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-escalation.svg new file mode 100644 index 0000000..e933de1 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-link.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-link.svg new file mode 100644 index 0000000..9d9f043 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-link.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-message.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-message.svg new file mode 100644 index 0000000..c350053 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-multiple.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-multiple.svg new file mode 100644 index 0000000..e6b0471 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-signal.svg b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-signal.svg new file mode 100644 index 0000000..b8cf330 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-intermediate-event-throw-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-lane.svg b/src/assets/icons/svg/bpmn-icon-lane.svg new file mode 100644 index 0000000..dd3e944 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-lane.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-manual-task.svg b/src/assets/icons/svg/bpmn-icon-manual-task.svg new file mode 100644 index 0000000..dc8a638 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-manual-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-message-flow.svg b/src/assets/icons/svg/bpmn-icon-message-flow.svg new file mode 100644 index 0000000..b22bc92 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-message-flow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-participant.svg b/src/assets/icons/svg/bpmn-icon-participant.svg new file mode 100644 index 0000000..9d1e21b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-participant.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-process.svg b/src/assets/icons/svg/bpmn-icon-process.svg new file mode 100644 index 0000000..8103053 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-process.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-receive-task.svg b/src/assets/icons/svg/bpmn-icon-receive-task.svg new file mode 100644 index 0000000..bd7aaef --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-receive-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-script-task.svg b/src/assets/icons/svg/bpmn-icon-script-task.svg new file mode 100644 index 0000000..4dcb900 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-script-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-send-task.svg b/src/assets/icons/svg/bpmn-icon-send-task.svg new file mode 100644 index 0000000..2d4fc95 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-send-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-service-task.svg b/src/assets/icons/svg/bpmn-icon-service-task.svg new file mode 100644 index 0000000..e6bf51f --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-service-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-compensation.svg b/src/assets/icons/svg/bpmn-icon-start-event-compensation.svg new file mode 100644 index 0000000..6ab859c --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-compensation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-condition.svg b/src/assets/icons/svg/bpmn-icon-start-event-condition.svg new file mode 100644 index 0000000..e6c4dd7 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-condition.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-error.svg b/src/assets/icons/svg/bpmn-icon-start-event-error.svg new file mode 100644 index 0000000..b347afb --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-error.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-escalation.svg b/src/assets/icons/svg/bpmn-icon-start-event-escalation.svg new file mode 100644 index 0000000..97991ec --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-message.svg b/src/assets/icons/svg/bpmn-icon-start-event-message.svg new file mode 100644 index 0000000..54b9e49 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-multiple.svg b/src/assets/icons/svg/bpmn-icon-start-event-multiple.svg new file mode 100644 index 0000000..dae0f61 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-condition.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-condition.svg new file mode 100644 index 0000000..4e7d8d2 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-condition.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-escalation.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-escalation.svg new file mode 100644 index 0000000..0d31752 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-escalation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-message.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-message.svg new file mode 100644 index 0000000..574367b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-message.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-multiple.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-multiple.svg new file mode 100644 index 0000000..8e8b2b9 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-parallel-multiple.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-parallel-multiple.svg new file mode 100644 index 0000000..75d35b8 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-parallel-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-signal.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-signal.svg new file mode 100644 index 0000000..4fbee92 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-timer.svg b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-timer.svg new file mode 100644 index 0000000..e7d797b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-non-interrupting-timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-none.svg b/src/assets/icons/svg/bpmn-icon-start-event-none.svg new file mode 100644 index 0000000..a54e94a --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-none.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-parallel-multiple.svg b/src/assets/icons/svg/bpmn-icon-start-event-parallel-multiple.svg new file mode 100644 index 0000000..3b5b16e --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-parallel-multiple.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-signal.svg b/src/assets/icons/svg/bpmn-icon-start-event-signal.svg new file mode 100644 index 0000000..4dbd0bc --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-start-event-timer.svg b/src/assets/icons/svg/bpmn-icon-start-event-timer.svg new file mode 100644 index 0000000..da36f97 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-start-event-timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-subprocess-collapsed.svg b/src/assets/icons/svg/bpmn-icon-subprocess-collapsed.svg new file mode 100644 index 0000000..e83cf1c --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-subprocess-collapsed.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-subprocess-expanded.svg b/src/assets/icons/svg/bpmn-icon-subprocess-expanded.svg new file mode 100644 index 0000000..4469ea1 --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-subprocess-expanded.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-task-none.svg b/src/assets/icons/svg/bpmn-icon-task-none.svg new file mode 100644 index 0000000..8a1c6cf --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-task-none.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-text-annotation.svg b/src/assets/icons/svg/bpmn-icon-text-annotation.svg new file mode 100644 index 0000000..9900edb --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-text-annotation.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-transaction.svg b/src/assets/icons/svg/bpmn-icon-transaction.svg new file mode 100644 index 0000000..8769f6b --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-transaction.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-icon-user-task.svg b/src/assets/icons/svg/bpmn-icon-user-task.svg new file mode 100644 index 0000000..ef41afc --- /dev/null +++ b/src/assets/icons/svg/bpmn-icon-user-task.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/svg/bpmn-multiple-state.svg b/src/assets/icons/svg/bpmn-multiple-state.svg new file mode 100644 index 0000000..958818e --- /dev/null +++ b/src/assets/icons/svg/bpmn-multiple-state.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/icons/svg/bug.svg b/src/assets/icons/svg/bug.svg new file mode 100644 index 0000000..05a150d --- /dev/null +++ b/src/assets/icons/svg/bug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/build.svg b/src/assets/icons/svg/build.svg new file mode 100644 index 0000000..97c4688 --- /dev/null +++ b/src/assets/icons/svg/build.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/button.svg b/src/assets/icons/svg/button.svg new file mode 100644 index 0000000..904fddc --- /dev/null +++ b/src/assets/icons/svg/button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/cascader.svg b/src/assets/icons/svg/cascader.svg new file mode 100644 index 0000000..e256024 --- /dev/null +++ b/src/assets/icons/svg/cascader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/chart.svg b/src/assets/icons/svg/chart.svg new file mode 100644 index 0000000..27728fb --- /dev/null +++ b/src/assets/icons/svg/chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/checkbox.svg b/src/assets/icons/svg/checkbox.svg new file mode 100644 index 0000000..013fd3a --- /dev/null +++ b/src/assets/icons/svg/checkbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/clipboard.svg b/src/assets/icons/svg/clipboard.svg new file mode 100644 index 0000000..90923ff --- /dev/null +++ b/src/assets/icons/svg/clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/code.svg b/src/assets/icons/svg/code.svg new file mode 100644 index 0000000..5f9c5ab --- /dev/null +++ b/src/assets/icons/svg/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/color.svg b/src/assets/icons/svg/color.svg new file mode 100644 index 0000000..44a81aa --- /dev/null +++ b/src/assets/icons/svg/color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/component.svg b/src/assets/icons/svg/component.svg new file mode 100644 index 0000000..29c3458 --- /dev/null +++ b/src/assets/icons/svg/component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/dashboard.svg b/src/assets/icons/svg/dashboard.svg new file mode 100644 index 0000000..5317d37 --- /dev/null +++ b/src/assets/icons/svg/dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/date-range.svg b/src/assets/icons/svg/date-range.svg new file mode 100644 index 0000000..fda571e --- /dev/null +++ b/src/assets/icons/svg/date-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/date.svg b/src/assets/icons/svg/date.svg new file mode 100644 index 0000000..52dc73e --- /dev/null +++ b/src/assets/icons/svg/date.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/dict.svg b/src/assets/icons/svg/dict.svg new file mode 100644 index 0000000..4849377 --- /dev/null +++ b/src/assets/icons/svg/dict.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/documentation.svg b/src/assets/icons/svg/documentation.svg new file mode 100644 index 0000000..7043122 --- /dev/null +++ b/src/assets/icons/svg/documentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/download.svg b/src/assets/icons/svg/download.svg new file mode 100644 index 0000000..c896951 --- /dev/null +++ b/src/assets/icons/svg/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/drag.svg b/src/assets/icons/svg/drag.svg new file mode 100644 index 0000000..4185d3c --- /dev/null +++ b/src/assets/icons/svg/drag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/druid.svg b/src/assets/icons/svg/druid.svg new file mode 100644 index 0000000..a2b4b4e --- /dev/null +++ b/src/assets/icons/svg/druid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/edit.svg b/src/assets/icons/svg/edit.svg new file mode 100644 index 0000000..d26101f --- /dev/null +++ b/src/assets/icons/svg/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/education.svg b/src/assets/icons/svg/education.svg new file mode 100644 index 0000000..7bfb01d --- /dev/null +++ b/src/assets/icons/svg/education.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/email.svg b/src/assets/icons/svg/email.svg new file mode 100644 index 0000000..74d25e2 --- /dev/null +++ b/src/assets/icons/svg/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/example.svg b/src/assets/icons/svg/example.svg new file mode 100644 index 0000000..46f42b5 --- /dev/null +++ b/src/assets/icons/svg/example.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/excel.svg b/src/assets/icons/svg/excel.svg new file mode 100644 index 0000000..74d97b8 --- /dev/null +++ b/src/assets/icons/svg/excel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/exit-fullscreen.svg b/src/assets/icons/svg/exit-fullscreen.svg new file mode 100644 index 0000000..485c128 --- /dev/null +++ b/src/assets/icons/svg/exit-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/eye-open.svg b/src/assets/icons/svg/eye-open.svg new file mode 100644 index 0000000..88dcc98 --- /dev/null +++ b/src/assets/icons/svg/eye-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/eye.svg b/src/assets/icons/svg/eye.svg new file mode 100644 index 0000000..16ed2d8 --- /dev/null +++ b/src/assets/icons/svg/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/form.svg b/src/assets/icons/svg/form.svg new file mode 100644 index 0000000..dcbaa18 --- /dev/null +++ b/src/assets/icons/svg/form.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/fullscreen.svg b/src/assets/icons/svg/fullscreen.svg new file mode 100644 index 0000000..0e86b6f --- /dev/null +++ b/src/assets/icons/svg/fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/github.svg b/src/assets/icons/svg/github.svg new file mode 100644 index 0000000..db0a0d4 --- /dev/null +++ b/src/assets/icons/svg/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/guide.svg b/src/assets/icons/svg/guide.svg new file mode 100644 index 0000000..b271001 --- /dev/null +++ b/src/assets/icons/svg/guide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/icon-rect.svg b/src/assets/icons/svg/icon-rect.svg new file mode 100644 index 0000000..11c3787 --- /dev/null +++ b/src/assets/icons/svg/icon-rect.svg @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/src/assets/icons/svg/icon.svg b/src/assets/icons/svg/icon.svg new file mode 100644 index 0000000..82be8ee --- /dev/null +++ b/src/assets/icons/svg/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/input.svg b/src/assets/icons/svg/input.svg new file mode 100644 index 0000000..ab91381 --- /dev/null +++ b/src/assets/icons/svg/input.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/international.svg b/src/assets/icons/svg/international.svg new file mode 100644 index 0000000..e9b56ee --- /dev/null +++ b/src/assets/icons/svg/international.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/job.svg b/src/assets/icons/svg/job.svg new file mode 100644 index 0000000..2a93a25 --- /dev/null +++ b/src/assets/icons/svg/job.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/language.svg b/src/assets/icons/svg/language.svg new file mode 100644 index 0000000..0082b57 --- /dev/null +++ b/src/assets/icons/svg/language.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/link.svg b/src/assets/icons/svg/link.svg new file mode 100644 index 0000000..48197ba --- /dev/null +++ b/src/assets/icons/svg/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/list.svg b/src/assets/icons/svg/list.svg new file mode 100644 index 0000000..20259ed --- /dev/null +++ b/src/assets/icons/svg/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/lock.svg b/src/assets/icons/svg/lock.svg new file mode 100644 index 0000000..74fee54 --- /dev/null +++ b/src/assets/icons/svg/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/log.svg b/src/assets/icons/svg/log.svg new file mode 100644 index 0000000..d879d33 --- /dev/null +++ b/src/assets/icons/svg/log.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/logininfor.svg b/src/assets/icons/svg/logininfor.svg new file mode 100644 index 0000000..267f844 --- /dev/null +++ b/src/assets/icons/svg/logininfor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/message.svg b/src/assets/icons/svg/message.svg new file mode 100644 index 0000000..14ca817 --- /dev/null +++ b/src/assets/icons/svg/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/money.svg b/src/assets/icons/svg/money.svg new file mode 100644 index 0000000..c1580de --- /dev/null +++ b/src/assets/icons/svg/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/monitor.svg b/src/assets/icons/svg/monitor.svg new file mode 100644 index 0000000..bc308cb --- /dev/null +++ b/src/assets/icons/svg/monitor.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/nested.svg b/src/assets/icons/svg/nested.svg new file mode 100644 index 0000000..06713a8 --- /dev/null +++ b/src/assets/icons/svg/nested.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/number.svg b/src/assets/icons/svg/number.svg new file mode 100644 index 0000000..ad5ce9a --- /dev/null +++ b/src/assets/icons/svg/number.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/online.svg b/src/assets/icons/svg/online.svg new file mode 100644 index 0000000..330a202 --- /dev/null +++ b/src/assets/icons/svg/online.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/password.svg b/src/assets/icons/svg/password.svg new file mode 100644 index 0000000..6c64def --- /dev/null +++ b/src/assets/icons/svg/password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/pdf.svg b/src/assets/icons/svg/pdf.svg new file mode 100644 index 0000000..957aa0c --- /dev/null +++ b/src/assets/icons/svg/pdf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/people.svg b/src/assets/icons/svg/people.svg new file mode 100644 index 0000000..2bd54ae --- /dev/null +++ b/src/assets/icons/svg/people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/peoples.svg b/src/assets/icons/svg/peoples.svg new file mode 100644 index 0000000..aab852e --- /dev/null +++ b/src/assets/icons/svg/peoples.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/phone.svg b/src/assets/icons/svg/phone.svg new file mode 100644 index 0000000..ab8e8c4 --- /dev/null +++ b/src/assets/icons/svg/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/post.svg b/src/assets/icons/svg/post.svg new file mode 100644 index 0000000..2922c61 --- /dev/null +++ b/src/assets/icons/svg/post.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/qq.svg b/src/assets/icons/svg/qq.svg new file mode 100644 index 0000000..ee13d4e --- /dev/null +++ b/src/assets/icons/svg/qq.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/question.svg b/src/assets/icons/svg/question.svg new file mode 100644 index 0000000..cf75bd4 --- /dev/null +++ b/src/assets/icons/svg/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/radio.svg b/src/assets/icons/svg/radio.svg new file mode 100644 index 0000000..0cde345 --- /dev/null +++ b/src/assets/icons/svg/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/rate.svg b/src/assets/icons/svg/rate.svg new file mode 100644 index 0000000..aa3b14d --- /dev/null +++ b/src/assets/icons/svg/rate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/redis-list.svg b/src/assets/icons/svg/redis-list.svg new file mode 100644 index 0000000..98a15b2 --- /dev/null +++ b/src/assets/icons/svg/redis-list.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/redis.svg b/src/assets/icons/svg/redis.svg new file mode 100644 index 0000000..2f1d62d --- /dev/null +++ b/src/assets/icons/svg/redis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/row.svg b/src/assets/icons/svg/row.svg new file mode 100644 index 0000000..0780992 --- /dev/null +++ b/src/assets/icons/svg/row.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/search.svg b/src/assets/icons/svg/search.svg new file mode 100644 index 0000000..84233dd --- /dev/null +++ b/src/assets/icons/svg/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/select.svg b/src/assets/icons/svg/select.svg new file mode 100644 index 0000000..d628382 --- /dev/null +++ b/src/assets/icons/svg/select.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/server.svg b/src/assets/icons/svg/server.svg new file mode 100644 index 0000000..eb287e3 --- /dev/null +++ b/src/assets/icons/svg/server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/shopping.svg b/src/assets/icons/svg/shopping.svg new file mode 100644 index 0000000..87513e7 --- /dev/null +++ b/src/assets/icons/svg/shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/size.svg b/src/assets/icons/svg/size.svg new file mode 100644 index 0000000..ddb25b8 --- /dev/null +++ b/src/assets/icons/svg/size.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/skill.svg b/src/assets/icons/svg/skill.svg new file mode 100644 index 0000000..a3b7312 --- /dev/null +++ b/src/assets/icons/svg/skill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/slider.svg b/src/assets/icons/svg/slider.svg new file mode 100644 index 0000000..fbe4f39 --- /dev/null +++ b/src/assets/icons/svg/slider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/star.svg b/src/assets/icons/svg/star.svg new file mode 100644 index 0000000..6cf86e6 --- /dev/null +++ b/src/assets/icons/svg/star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/swagger.svg b/src/assets/icons/svg/swagger.svg new file mode 100644 index 0000000..05d4e7b --- /dev/null +++ b/src/assets/icons/svg/swagger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/switch.svg b/src/assets/icons/svg/switch.svg new file mode 100644 index 0000000..0ba61e3 --- /dev/null +++ b/src/assets/icons/svg/switch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/system.svg b/src/assets/icons/svg/system.svg new file mode 100644 index 0000000..5992593 --- /dev/null +++ b/src/assets/icons/svg/system.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/tab.svg b/src/assets/icons/svg/tab.svg new file mode 100644 index 0000000..b4b48e4 --- /dev/null +++ b/src/assets/icons/svg/tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/table.svg b/src/assets/icons/svg/table.svg new file mode 100644 index 0000000..0e3dc9d --- /dev/null +++ b/src/assets/icons/svg/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/textarea.svg b/src/assets/icons/svg/textarea.svg new file mode 100644 index 0000000..2709f29 --- /dev/null +++ b/src/assets/icons/svg/textarea.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/theme.svg b/src/assets/icons/svg/theme.svg new file mode 100644 index 0000000..5982a2f --- /dev/null +++ b/src/assets/icons/svg/theme.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/time-range.svg b/src/assets/icons/svg/time-range.svg new file mode 100644 index 0000000..13c1202 --- /dev/null +++ b/src/assets/icons/svg/time-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/time.svg b/src/assets/icons/svg/time.svg new file mode 100644 index 0000000..b376e32 --- /dev/null +++ b/src/assets/icons/svg/time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/tool.svg b/src/assets/icons/svg/tool.svg new file mode 100644 index 0000000..48e0e35 --- /dev/null +++ b/src/assets/icons/svg/tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/tree-table.svg b/src/assets/icons/svg/tree-table.svg new file mode 100644 index 0000000..8aafdb8 --- /dev/null +++ b/src/assets/icons/svg/tree-table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/tree.svg b/src/assets/icons/svg/tree.svg new file mode 100644 index 0000000..dd4b7dd --- /dev/null +++ b/src/assets/icons/svg/tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/upload.svg b/src/assets/icons/svg/upload.svg new file mode 100644 index 0000000..bae49c0 --- /dev/null +++ b/src/assets/icons/svg/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/user.svg b/src/assets/icons/svg/user.svg new file mode 100644 index 0000000..0ba0716 --- /dev/null +++ b/src/assets/icons/svg/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/validCode.svg b/src/assets/icons/svg/validCode.svg new file mode 100644 index 0000000..4fe305a --- /dev/null +++ b/src/assets/icons/svg/validCode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/wechat.svg b/src/assets/icons/svg/wechat.svg new file mode 100644 index 0000000..c586e55 --- /dev/null +++ b/src/assets/icons/svg/wechat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svg/zip.svg b/src/assets/icons/svg/zip.svg new file mode 100644 index 0000000..f806fc4 --- /dev/null +++ b/src/assets/icons/svg/zip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/svgo.yml b/src/assets/icons/svgo.yml new file mode 100644 index 0000000..d11906a --- /dev/null +++ b/src/assets/icons/svgo.yml @@ -0,0 +1,22 @@ +# replace default config + +# multipass: true +# full: true + +plugins: + + # - name + # + # or: + # - name: false + # - name: true + # + # or: + # - name: + # param1: 1 + # param2: 2 + +- removeAttrs: + attrs: + - 'fill' + - 'fill-rule' diff --git a/src/assets/images/avatar.svg b/src/assets/images/avatar.svg new file mode 100644 index 0000000..7708c0c --- /dev/null +++ b/src/assets/images/avatar.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/assets/images/bg-dot.png b/src/assets/images/bg-dot.png new file mode 100644 index 0000000..1610b77 Binary files /dev/null and b/src/assets/images/bg-dot.png differ diff --git a/src/assets/images/damage-tree/and.svg b/src/assets/images/damage-tree/and.svg new file mode 100644 index 0000000..5d0b55d --- /dev/null +++ b/src/assets/images/damage-tree/and.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/end-circle.svg b/src/assets/images/damage-tree/end-circle.svg new file mode 100644 index 0000000..4c10e7b --- /dev/null +++ b/src/assets/images/damage-tree/end-circle.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/line-marker.svg b/src/assets/images/damage-tree/line-marker.svg new file mode 100644 index 0000000..23ccbf5 --- /dev/null +++ b/src/assets/images/damage-tree/line-marker.svg @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/or.svg b/src/assets/images/damage-tree/or.svg new file mode 100644 index 0000000..7b65e83 --- /dev/null +++ b/src/assets/images/damage-tree/or.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/rect-fill.svg b/src/assets/images/damage-tree/rect-fill.svg new file mode 100644 index 0000000..71ba611 --- /dev/null +++ b/src/assets/images/damage-tree/rect-fill.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/rect.svg b/src/assets/images/damage-tree/rect.svg new file mode 100644 index 0000000..3f83ef1 --- /dev/null +++ b/src/assets/images/damage-tree/rect.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/damage-tree/select.svg b/src/assets/images/damage-tree/select.svg new file mode 100644 index 0000000..9ed83b3 --- /dev/null +++ b/src/assets/images/damage-tree/select.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/dark.svg b/src/assets/images/dark.svg new file mode 100644 index 0000000..f646bd7 --- /dev/null +++ b/src/assets/images/dark.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/empty.png b/src/assets/images/empty.png new file mode 100644 index 0000000..f49d4e7 Binary files /dev/null and b/src/assets/images/empty.png differ diff --git a/src/assets/images/icon-add.png b/src/assets/images/icon-add.png new file mode 100644 index 0000000..cf17ffe Binary files /dev/null and b/src/assets/images/icon-add.png differ diff --git a/src/assets/images/icon-avatar.png b/src/assets/images/icon-avatar.png new file mode 100644 index 0000000..601da84 Binary files /dev/null and b/src/assets/images/icon-avatar.png differ diff --git a/src/assets/images/icon-date.png b/src/assets/images/icon-date.png new file mode 100644 index 0000000..49f2625 Binary files /dev/null and b/src/assets/images/icon-date.png differ diff --git a/src/assets/images/icon-delete.png b/src/assets/images/icon-delete.png new file mode 100644 index 0000000..3f7f2e2 Binary files /dev/null and b/src/assets/images/icon-delete.png differ diff --git a/src/assets/images/icon-export.png b/src/assets/images/icon-export.png new file mode 100644 index 0000000..cdd4a39 Binary files /dev/null and b/src/assets/images/icon-export.png differ diff --git a/src/assets/images/icon-import.png b/src/assets/images/icon-import.png new file mode 100644 index 0000000..5572d6a Binary files /dev/null and b/src/assets/images/icon-import.png differ diff --git a/src/assets/images/icon-logout.png b/src/assets/images/icon-logout.png new file mode 100644 index 0000000..3c7ab21 Binary files /dev/null and b/src/assets/images/icon-logout.png differ diff --git a/src/assets/images/icon-message.png b/src/assets/images/icon-message.png new file mode 100644 index 0000000..0ebad56 Binary files /dev/null and b/src/assets/images/icon-message.png differ diff --git a/src/assets/images/icon-search.png b/src/assets/images/icon-search.png new file mode 100644 index 0000000..0a21433 Binary files /dev/null and b/src/assets/images/icon-search.png differ diff --git a/src/assets/images/icon-step-complete.png b/src/assets/images/icon-step-complete.png new file mode 100644 index 0000000..0059e57 Binary files /dev/null and b/src/assets/images/icon-step-complete.png differ diff --git a/src/assets/images/light.svg b/src/assets/images/light.svg new file mode 100644 index 0000000..ab7cc08 --- /dev/null +++ b/src/assets/images/light.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/login/bg-login.png b/src/assets/images/login/bg-login.png new file mode 100644 index 0000000..4627fa4 Binary files /dev/null and b/src/assets/images/login/bg-login.png differ diff --git a/src/assets/images/login/bg.png b/src/assets/images/login/bg.png new file mode 100644 index 0000000..be43762 Binary files /dev/null and b/src/assets/images/login/bg.png differ diff --git a/src/assets/images/login/decoration-login.png b/src/assets/images/login/decoration-login.png new file mode 100644 index 0000000..6f5fd72 Binary files /dev/null and b/src/assets/images/login/decoration-login.png differ diff --git a/src/assets/images/login/icon-account.png b/src/assets/images/login/icon-account.png new file mode 100644 index 0000000..ec4b92e Binary files /dev/null and b/src/assets/images/login/icon-account.png differ diff --git a/src/assets/images/login/icon-dun.png b/src/assets/images/login/icon-dun.png new file mode 100644 index 0000000..449626b Binary files /dev/null and b/src/assets/images/login/icon-dun.png differ diff --git a/src/assets/images/login/icon-pwd.png b/src/assets/images/login/icon-pwd.png new file mode 100644 index 0000000..2a7049b Binary files /dev/null and b/src/assets/images/login/icon-pwd.png differ diff --git a/src/assets/images/login/login-title.png b/src/assets/images/login/login-title.png new file mode 100644 index 0000000..ac16f02 Binary files /dev/null and b/src/assets/images/login/login-title.png differ diff --git a/src/assets/images/login/main-title.png b/src/assets/images/login/main-title.png new file mode 100644 index 0000000..73e5025 Binary files /dev/null and b/src/assets/images/login/main-title.png differ diff --git a/src/assets/images/login/图层2.png b/src/assets/images/login/图层2.png new file mode 100644 index 0000000..d212ec8 Binary files /dev/null and b/src/assets/images/login/图层2.png differ diff --git a/src/assets/images/login/登录.jpg b/src/assets/images/login/登录.jpg new file mode 100644 index 0000000..afb2088 Binary files /dev/null and b/src/assets/images/login/登录.jpg differ diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000..90615b0 Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/images/nav-logo.png b/src/assets/images/nav-logo.png new file mode 100644 index 0000000..f8090f5 Binary files /dev/null and b/src/assets/images/nav-logo.png differ diff --git a/src/assets/images/p-tree/down-fill.png b/src/assets/images/p-tree/down-fill.png new file mode 100644 index 0000000..c9faefb Binary files /dev/null and b/src/assets/images/p-tree/down-fill.png differ diff --git a/src/assets/images/p-tree/icon-add-active.png b/src/assets/images/p-tree/icon-add-active.png new file mode 100644 index 0000000..ab2c927 Binary files /dev/null and b/src/assets/images/p-tree/icon-add-active.png differ diff --git a/src/assets/images/p-tree/icon-add.png b/src/assets/images/p-tree/icon-add.png new file mode 100644 index 0000000..fa1afc7 Binary files /dev/null and b/src/assets/images/p-tree/icon-add.png differ diff --git a/src/assets/images/p-tree/icon-delete-active.png b/src/assets/images/p-tree/icon-delete-active.png new file mode 100644 index 0000000..350bd7d Binary files /dev/null and b/src/assets/images/p-tree/icon-delete-active.png differ diff --git a/src/assets/images/p-tree/icon-delete.png b/src/assets/images/p-tree/icon-delete.png new file mode 100644 index 0000000..6aaa364 Binary files /dev/null and b/src/assets/images/p-tree/icon-delete.png differ diff --git a/src/assets/images/p-tree/icon-download-active.png b/src/assets/images/p-tree/icon-download-active.png new file mode 100644 index 0000000..906073f Binary files /dev/null and b/src/assets/images/p-tree/icon-download-active.png differ diff --git a/src/assets/images/p-tree/icon-download.png b/src/assets/images/p-tree/icon-download.png new file mode 100644 index 0000000..0340103 Binary files /dev/null and b/src/assets/images/p-tree/icon-download.png differ diff --git a/src/assets/images/p-tree/icon-edit-active.png b/src/assets/images/p-tree/icon-edit-active.png new file mode 100644 index 0000000..a68e93a Binary files /dev/null and b/src/assets/images/p-tree/icon-edit-active.png differ diff --git a/src/assets/images/p-tree/icon-edit.png b/src/assets/images/p-tree/icon-edit.png new file mode 100644 index 0000000..f765400 Binary files /dev/null and b/src/assets/images/p-tree/icon-edit.png differ diff --git a/src/assets/images/p-tree/icon-evaluate-active.png b/src/assets/images/p-tree/icon-evaluate-active.png new file mode 100644 index 0000000..ce94bde Binary files /dev/null and b/src/assets/images/p-tree/icon-evaluate-active.png differ diff --git a/src/assets/images/p-tree/icon-evaluate.png b/src/assets/images/p-tree/icon-evaluate.png new file mode 100644 index 0000000..0fbf2fc Binary files /dev/null and b/src/assets/images/p-tree/icon-evaluate.png differ diff --git a/src/assets/images/p-tree/icon-formmodel.png b/src/assets/images/p-tree/icon-formmodel.png new file mode 100644 index 0000000..39e4b4e Binary files /dev/null and b/src/assets/images/p-tree/icon-formmodel.png differ diff --git a/src/assets/images/p-tree/icon-result.png b/src/assets/images/p-tree/icon-result.png new file mode 100644 index 0000000..a1a686e Binary files /dev/null and b/src/assets/images/p-tree/icon-result.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-0.png b/src/assets/images/p-tree/icon-tree-level-0.png new file mode 100644 index 0000000..366bd38 Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-0.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-1.png b/src/assets/images/p-tree/icon-tree-level-1.png new file mode 100644 index 0000000..0733d9d Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-1.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-2.png b/src/assets/images/p-tree/icon-tree-level-2.png new file mode 100644 index 0000000..3a3deea Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-2.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-3-open.png b/src/assets/images/p-tree/icon-tree-level-3-open.png new file mode 100644 index 0000000..7adefa8 Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-3-open.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-3.png b/src/assets/images/p-tree/icon-tree-level-3.png new file mode 100644 index 0000000..f99351e Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-3.png differ diff --git a/src/assets/images/p-tree/icon-tree-level-4.png b/src/assets/images/p-tree/icon-tree-level-4.png new file mode 100644 index 0000000..b1a9f70 Binary files /dev/null and b/src/assets/images/p-tree/icon-tree-level-4.png differ diff --git a/src/assets/images/p-tree/icon-tree.png b/src/assets/images/p-tree/icon-tree.png new file mode 100644 index 0000000..e3c14c6 Binary files /dev/null and b/src/assets/images/p-tree/icon-tree.png differ diff --git a/src/assets/images/p-tree/icon-upload-active.png b/src/assets/images/p-tree/icon-upload-active.png new file mode 100644 index 0000000..d26da50 Binary files /dev/null and b/src/assets/images/p-tree/icon-upload-active.png differ diff --git a/src/assets/images/p-tree/icon-upload.png b/src/assets/images/p-tree/icon-upload.png new file mode 100644 index 0000000..3508116 Binary files /dev/null and b/src/assets/images/p-tree/icon-upload.png differ diff --git a/src/assets/images/p-tree/right-fill.png b/src/assets/images/p-tree/right-fill.png new file mode 100644 index 0000000..a7d4963 Binary files /dev/null and b/src/assets/images/p-tree/right-fill.png differ diff --git a/src/assets/images/par/gu(fang).png b/src/assets/images/par/gu(fang).png new file mode 100644 index 0000000..21f2406 Binary files /dev/null and b/src/assets/images/par/gu(fang).png differ diff --git a/src/assets/images/par/gu(yuan).png b/src/assets/images/par/gu(yuan).png new file mode 100644 index 0000000..edd08b4 Binary files /dev/null and b/src/assets/images/par/gu(yuan).png differ diff --git a/src/assets/images/par/j_gu.png b/src/assets/images/par/j_gu.png new file mode 100644 index 0000000..8fc6dae Binary files /dev/null and b/src/assets/images/par/j_gu.png differ diff --git a/src/assets/images/par/j_maan.png b/src/assets/images/par/j_maan.png new file mode 100644 index 0000000..9afe2f1 Binary files /dev/null and b/src/assets/images/par/j_maan.png differ diff --git a/src/assets/images/par/j_yuanzhu.png b/src/assets/images/par/j_yuanzhu.png new file mode 100644 index 0000000..1d875d3 Binary files /dev/null and b/src/assets/images/par/j_yuanzhu.png differ diff --git a/src/assets/images/par/j_zhui.png b/src/assets/images/par/j_zhui.png new file mode 100644 index 0000000..9c86787 Binary files /dev/null and b/src/assets/images/par/j_zhui.png differ diff --git a/src/assets/images/par/j_zhui2.png b/src/assets/images/par/j_zhui2.png new file mode 100644 index 0000000..f6e15e0 Binary files /dev/null and b/src/assets/images/par/j_zhui2.png differ diff --git a/src/assets/images/par/maan(fang).png b/src/assets/images/par/maan(fang).png new file mode 100644 index 0000000..5334073 Binary files /dev/null and b/src/assets/images/par/maan(fang).png differ diff --git a/src/assets/images/par/maan(no).png b/src/assets/images/par/maan(no).png new file mode 100644 index 0000000..c8521f7 Binary files /dev/null and b/src/assets/images/par/maan(no).png differ diff --git a/src/assets/images/par/maan(yuan).png b/src/assets/images/par/maan(yuan).png new file mode 100644 index 0000000..010e76a Binary files /dev/null and b/src/assets/images/par/maan(yuan).png differ diff --git a/src/assets/images/par/youzhui.png b/src/assets/images/par/youzhui.png new file mode 100644 index 0000000..97259c8 Binary files /dev/null and b/src/assets/images/par/youzhui.png differ diff --git a/src/assets/images/par/yuanzhu(fang).png b/src/assets/images/par/yuanzhu(fang).png new file mode 100644 index 0000000..ef1f931 Binary files /dev/null and b/src/assets/images/par/yuanzhu(fang).png differ diff --git a/src/assets/images/par/yuanzhu(yuan).png b/src/assets/images/par/yuanzhu(yuan).png new file mode 100644 index 0000000..cc843a0 Binary files /dev/null and b/src/assets/images/par/yuanzhu(yuan).png differ diff --git a/src/assets/images/par/zhui(fang).png b/src/assets/images/par/zhui(fang).png new file mode 100644 index 0000000..562ace7 Binary files /dev/null and b/src/assets/images/par/zhui(fang).png differ diff --git a/src/assets/images/par/zhui(yuan).png b/src/assets/images/par/zhui(yuan).png new file mode 100644 index 0000000..15053a2 Binary files /dev/null and b/src/assets/images/par/zhui(yuan).png differ diff --git a/src/assets/images/par/zuozhui.png b/src/assets/images/par/zuozhui.png new file mode 100644 index 0000000..1de8fd3 Binary files /dev/null and b/src/assets/images/par/zuozhui.png differ diff --git a/src/assets/images/par/两端锥形中间马鞍形.png b/src/assets/images/par/两端锥形中间马鞍形.png new file mode 100644 index 0000000..28fd671 Binary files /dev/null and b/src/assets/images/par/两端锥形中间马鞍形.png differ diff --git a/src/assets/images/par2/bj.jpg b/src/assets/images/par2/bj.jpg new file mode 100644 index 0000000..2f5142a Binary files /dev/null and b/src/assets/images/par2/bj.jpg differ diff --git a/src/assets/images/par2/gu1.png b/src/assets/images/par2/gu1.png new file mode 100644 index 0000000..60ac30c Binary files /dev/null and b/src/assets/images/par2/gu1.png differ diff --git a/src/assets/images/par2/gu2.png b/src/assets/images/par2/gu2.png new file mode 100644 index 0000000..7ab4e2c Binary files /dev/null and b/src/assets/images/par2/gu2.png differ diff --git a/src/assets/images/par2/gu3.png b/src/assets/images/par2/gu3.png new file mode 100644 index 0000000..0af607a Binary files /dev/null and b/src/assets/images/par2/gu3.png differ diff --git a/src/assets/images/par2/maan1.png b/src/assets/images/par2/maan1.png new file mode 100644 index 0000000..0d35690 Binary files /dev/null and b/src/assets/images/par2/maan1.png differ diff --git a/src/assets/images/par2/maan2.png b/src/assets/images/par2/maan2.png new file mode 100644 index 0000000..a8119f7 Binary files /dev/null and b/src/assets/images/par2/maan2.png differ diff --git a/src/assets/images/par2/maan3.png b/src/assets/images/par2/maan3.png new file mode 100644 index 0000000..d71d051 Binary files /dev/null and b/src/assets/images/par2/maan3.png differ diff --git a/src/assets/images/par2/yuanzhu1.png b/src/assets/images/par2/yuanzhu1.png new file mode 100644 index 0000000..90ad8f7 Binary files /dev/null and b/src/assets/images/par2/yuanzhu1.png differ diff --git a/src/assets/images/par2/yuanzhu2.png b/src/assets/images/par2/yuanzhu2.png new file mode 100644 index 0000000..53f3d88 Binary files /dev/null and b/src/assets/images/par2/yuanzhu2.png differ diff --git a/src/assets/images/par2/yuanzhu3.png b/src/assets/images/par2/yuanzhu3.png new file mode 100644 index 0000000..4b3f806 Binary files /dev/null and b/src/assets/images/par2/yuanzhu3.png differ diff --git a/src/assets/images/par2/zhui1.png b/src/assets/images/par2/zhui1.png new file mode 100644 index 0000000..d195461 Binary files /dev/null and b/src/assets/images/par2/zhui1.png differ diff --git a/src/assets/images/par2/zhui2.png b/src/assets/images/par2/zhui2.png new file mode 100644 index 0000000..166198d Binary files /dev/null and b/src/assets/images/par2/zhui2.png differ diff --git a/src/assets/images/par2/zhui3.png b/src/assets/images/par2/zhui3.png new file mode 100644 index 0000000..1679252 Binary files /dev/null and b/src/assets/images/par2/zhui3.png differ diff --git a/src/assets/images/par2/zhui4.png b/src/assets/images/par2/zhui4.png new file mode 100644 index 0000000..dbdaf4f Binary files /dev/null and b/src/assets/images/par2/zhui4.png differ diff --git a/src/assets/images/par2/zhui5.png b/src/assets/images/par2/zhui5.png new file mode 100644 index 0000000..cdf9bc5 Binary files /dev/null and b/src/assets/images/par2/zhui5.png differ diff --git a/src/assets/images/par2/zhui6.png b/src/assets/images/par2/zhui6.png new file mode 100644 index 0000000..8ab7d17 Binary files /dev/null and b/src/assets/images/par2/zhui6.png differ diff --git a/src/assets/images/plan/1.png b/src/assets/images/plan/1.png new file mode 100644 index 0000000..8a2b96e Binary files /dev/null and b/src/assets/images/plan/1.png differ diff --git a/src/assets/images/plan/2.png b/src/assets/images/plan/2.png new file mode 100644 index 0000000..1a11173 Binary files /dev/null and b/src/assets/images/plan/2.png differ diff --git a/src/assets/images/plan/3.png b/src/assets/images/plan/3.png new file mode 100644 index 0000000..ca4096c Binary files /dev/null and b/src/assets/images/plan/3.png differ diff --git a/src/assets/images/plan/4.png b/src/assets/images/plan/4.png new file mode 100644 index 0000000..c446bd2 Binary files /dev/null and b/src/assets/images/plan/4.png differ diff --git a/src/assets/images/plan/5.png b/src/assets/images/plan/5.png new file mode 100644 index 0000000..4095c91 Binary files /dev/null and b/src/assets/images/plan/5.png differ diff --git a/src/assets/images/plane/avatar.png b/src/assets/images/plane/avatar.png new file mode 100644 index 0000000..751c167 Binary files /dev/null and b/src/assets/images/plane/avatar.png differ diff --git a/src/assets/images/plane/close-red.png b/src/assets/images/plane/close-red.png new file mode 100644 index 0000000..d6ebf3b Binary files /dev/null and b/src/assets/images/plane/close-red.png differ diff --git a/src/assets/images/plane/close.png b/src/assets/images/plane/close.png new file mode 100644 index 0000000..be69d5e Binary files /dev/null and b/src/assets/images/plane/close.png differ diff --git a/src/assets/images/plane/damage-distribution-display.png b/src/assets/images/plane/damage-distribution-display.png new file mode 100644 index 0000000..829f7a3 Binary files /dev/null and b/src/assets/images/plane/damage-distribution-display.png differ diff --git a/src/assets/images/plane/fc-1.png b/src/assets/images/plane/fc-1.png new file mode 100644 index 0000000..90143dd Binary files /dev/null and b/src/assets/images/plane/fc-1.png differ diff --git a/src/assets/images/plane/folder-close.png b/src/assets/images/plane/folder-close.png new file mode 100644 index 0000000..bc227a1 Binary files /dev/null and b/src/assets/images/plane/folder-close.png differ diff --git a/src/assets/images/plane/folder-open.png b/src/assets/images/plane/folder-open.png new file mode 100644 index 0000000..551e6b7 Binary files /dev/null and b/src/assets/images/plane/folder-open.png differ diff --git a/src/assets/images/plane/icon-dropdown-active.png b/src/assets/images/plane/icon-dropdown-active.png new file mode 100644 index 0000000..a9511c5 Binary files /dev/null and b/src/assets/images/plane/icon-dropdown-active.png differ diff --git a/src/assets/images/plane/icon-dropdown.png b/src/assets/images/plane/icon-dropdown.png new file mode 100644 index 0000000..4080be7 Binary files /dev/null and b/src/assets/images/plane/icon-dropdown.png differ diff --git a/src/assets/images/plane/icon-pause-disabled.png b/src/assets/images/plane/icon-pause-disabled.png new file mode 100644 index 0000000..08f2944 Binary files /dev/null and b/src/assets/images/plane/icon-pause-disabled.png differ diff --git a/src/assets/images/plane/icon-pause.png b/src/assets/images/plane/icon-pause.png new file mode 100644 index 0000000..790f3c1 Binary files /dev/null and b/src/assets/images/plane/icon-pause.png differ diff --git a/src/assets/images/plane/icon-start-disabled.png b/src/assets/images/plane/icon-start-disabled.png new file mode 100644 index 0000000..f320754 Binary files /dev/null and b/src/assets/images/plane/icon-start-disabled.png differ diff --git a/src/assets/images/plane/icon-start.png b/src/assets/images/plane/icon-start.png new file mode 100644 index 0000000..a8b03bb Binary files /dev/null and b/src/assets/images/plane/icon-start.png differ diff --git a/src/assets/images/plane/j-10.png b/src/assets/images/plane/j-10.png new file mode 100644 index 0000000..1dfde17 Binary files /dev/null and b/src/assets/images/plane/j-10.png differ diff --git a/src/assets/images/plane/j-20.png b/src/assets/images/plane/j-20.png new file mode 100644 index 0000000..abe2e1b Binary files /dev/null and b/src/assets/images/plane/j-20.png differ diff --git a/src/assets/images/plane/j-7.png b/src/assets/images/plane/j-7.png new file mode 100644 index 0000000..247f6fb Binary files /dev/null and b/src/assets/images/plane/j-7.png differ diff --git a/src/assets/images/plane/killing-element-power-field-bg.png b/src/assets/images/plane/killing-element-power-field-bg.png new file mode 100644 index 0000000..a1a0a14 Binary files /dev/null and b/src/assets/images/plane/killing-element-power-field-bg.png differ diff --git a/src/assets/images/plane/killing-element-power-field.gif b/src/assets/images/plane/killing-element-power-field.gif new file mode 100644 index 0000000..c6ceaff Binary files /dev/null and b/src/assets/images/plane/killing-element-power-field.gif differ diff --git a/src/assets/images/plane/killing-element-power-field.png b/src/assets/images/plane/killing-element-power-field.png new file mode 100644 index 0000000..5f02176 Binary files /dev/null and b/src/assets/images/plane/killing-element-power-field.png differ diff --git a/src/assets/images/plane/logo.png b/src/assets/images/plane/logo.png new file mode 100644 index 0000000..d212ec8 Binary files /dev/null and b/src/assets/images/plane/logo.png differ diff --git a/src/assets/images/plane/missile-red.png b/src/assets/images/plane/missile-red.png new file mode 100644 index 0000000..7f61d92 Binary files /dev/null and b/src/assets/images/plane/missile-red.png differ diff --git a/src/assets/images/plane/pl-10.png b/src/assets/images/plane/pl-10.png new file mode 100644 index 0000000..4afc6ae Binary files /dev/null and b/src/assets/images/plane/pl-10.png differ diff --git a/src/assets/images/plane/pl-11.png b/src/assets/images/plane/pl-11.png new file mode 100644 index 0000000..a8252ac Binary files /dev/null and b/src/assets/images/plane/pl-11.png differ diff --git a/src/assets/images/plane/pl-12.png b/src/assets/images/plane/pl-12.png new file mode 100644 index 0000000..b26fdcd Binary files /dev/null and b/src/assets/images/plane/pl-12.png differ diff --git a/src/assets/images/plane/pl-13.png b/src/assets/images/plane/pl-13.png new file mode 100644 index 0000000..f2fb5b5 Binary files /dev/null and b/src/assets/images/plane/pl-13.png differ diff --git a/src/assets/images/plane/plane-red.png b/src/assets/images/plane/plane-red.png new file mode 100644 index 0000000..2a8deff Binary files /dev/null and b/src/assets/images/plane/plane-red.png differ diff --git a/src/assets/images/plane/plane-scan.png b/src/assets/images/plane/plane-scan.png new file mode 100644 index 0000000..b39dd63 Binary files /dev/null and b/src/assets/images/plane/plane-scan.png differ diff --git a/src/assets/images/plane/raycaster.gif b/src/assets/images/plane/raycaster.gif new file mode 100644 index 0000000..dfcedbd Binary files /dev/null and b/src/assets/images/plane/raycaster.gif differ diff --git a/src/assets/images/plane/raycaster.png b/src/assets/images/plane/raycaster.png new file mode 100644 index 0000000..7d49b0c Binary files /dev/null and b/src/assets/images/plane/raycaster.png differ diff --git a/src/assets/images/plane/real-img-j20.png b/src/assets/images/plane/real-img-j20.png new file mode 100644 index 0000000..bb4e377 Binary files /dev/null and b/src/assets/images/plane/real-img-j20.png differ diff --git a/src/assets/images/plane/simulation-destroy.png b/src/assets/images/plane/simulation-destroy.png new file mode 100644 index 0000000..9c92647 Binary files /dev/null and b/src/assets/images/plane/simulation-destroy.png differ diff --git a/src/assets/images/plane/simulation-light.png b/src/assets/images/plane/simulation-light.png new file mode 100644 index 0000000..5866504 Binary files /dev/null and b/src/assets/images/plane/simulation-light.png differ diff --git a/src/assets/images/plane/simulation-plane.png b/src/assets/images/plane/simulation-plane.png new file mode 100644 index 0000000..14c27d8 Binary files /dev/null and b/src/assets/images/plane/simulation-plane.png differ diff --git a/src/assets/images/plane/simulation-sun.png b/src/assets/images/plane/simulation-sun.png new file mode 100644 index 0000000..44563c3 Binary files /dev/null and b/src/assets/images/plane/simulation-sun.png differ diff --git a/src/assets/images/plane/triangle-active.png b/src/assets/images/plane/triangle-active.png new file mode 100644 index 0000000..614f64c Binary files /dev/null and b/src/assets/images/plane/triangle-active.png differ diff --git a/src/assets/images/plane/triangle.png b/src/assets/images/plane/triangle.png new file mode 100644 index 0000000..c19e087 Binary files /dev/null and b/src/assets/images/plane/triangle.png differ diff --git a/src/assets/images/plane/tuceng135.png b/src/assets/images/plane/tuceng135.png new file mode 100644 index 0000000..49ca36a Binary files /dev/null and b/src/assets/images/plane/tuceng135.png differ diff --git a/src/assets/images/plane/tuceng2.png b/src/assets/images/plane/tuceng2.png new file mode 100644 index 0000000..c711bb3 Binary files /dev/null and b/src/assets/images/plane/tuceng2.png differ diff --git a/src/assets/images/plane/tuceng4.png b/src/assets/images/plane/tuceng4.png new file mode 100644 index 0000000..bb4e377 Binary files /dev/null and b/src/assets/images/plane/tuceng4.png differ diff --git a/src/assets/images/plane/tuceng5.png b/src/assets/images/plane/tuceng5.png new file mode 100644 index 0000000..c099b72 Binary files /dev/null and b/src/assets/images/plane/tuceng5.png differ diff --git a/src/assets/images/plane/tuceng6.png b/src/assets/images/plane/tuceng6.png new file mode 100644 index 0000000..420e6b0 Binary files /dev/null and b/src/assets/images/plane/tuceng6.png differ diff --git a/src/assets/images/profile.jpg b/src/assets/images/profile.jpg new file mode 100644 index 0000000..f4fde57 Binary files /dev/null and b/src/assets/images/profile.jpg differ diff --git a/src/assets/images/tab-active.svg b/src/assets/images/tab-active.svg new file mode 100644 index 0000000..290ceba --- /dev/null +++ b/src/assets/images/tab-active.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/tab.svg b/src/assets/images/tab.svg new file mode 100644 index 0000000..c26c19b --- /dev/null +++ b/src/assets/images/tab.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/threejs/back.jpg b/src/assets/images/threejs/back.jpg new file mode 100644 index 0000000..e0057f3 Binary files /dev/null and b/src/assets/images/threejs/back.jpg differ diff --git a/src/assets/images/threejs/boom.png b/src/assets/images/threejs/boom.png new file mode 100644 index 0000000..8b8df16 Binary files /dev/null and b/src/assets/images/threejs/boom.png differ diff --git a/src/assets/images/threejs/down.jpg b/src/assets/images/threejs/down.jpg new file mode 100644 index 0000000..c025b60 Binary files /dev/null and b/src/assets/images/threejs/down.jpg differ diff --git a/src/assets/images/threejs/front.jpg b/src/assets/images/threejs/front.jpg new file mode 100644 index 0000000..bd1d20b Binary files /dev/null and b/src/assets/images/threejs/front.jpg differ diff --git a/src/assets/images/threejs/left.jpg b/src/assets/images/threejs/left.jpg new file mode 100644 index 0000000..1d7e3c4 Binary files /dev/null and b/src/assets/images/threejs/left.jpg differ diff --git a/src/assets/images/threejs/right.jpg b/src/assets/images/threejs/right.jpg new file mode 100644 index 0000000..356a09e Binary files /dev/null and b/src/assets/images/threejs/right.jpg differ diff --git a/src/assets/images/threejs/top.jpg b/src/assets/images/threejs/top.jpg new file mode 100644 index 0000000..76c3dab Binary files /dev/null and b/src/assets/images/threejs/top.jpg differ diff --git a/src/assets/images/u32.svg b/src/assets/images/u32.svg new file mode 100644 index 0000000..d94a7ea --- /dev/null +++ b/src/assets/images/u32.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/u3909.png b/src/assets/images/u3909.png new file mode 100644 index 0000000..c04f694 Binary files /dev/null and b/src/assets/images/u3909.png differ diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png new file mode 100644 index 0000000..3f919d8 Binary files /dev/null and b/src/assets/logo/logo.png differ diff --git a/src/assets/styles/btn.scss b/src/assets/styles/btn.scss new file mode 100644 index 0000000..e6ba1a8 --- /dev/null +++ b/src/assets/styles/btn.scss @@ -0,0 +1,99 @@ +@import './variables.scss'; + +@mixin colorBtn($color) { + background: $color; + + &:hover { + color: $color; + + &:before, + &:after { + background: $color; + } + } +} + +.blue-btn { + @include colorBtn($blue) +} + +.light-blue-btn { + @include colorBtn($light-blue) +} + +.red-btn { + @include colorBtn($red) +} + +.pink-btn { + @include colorBtn($pink) +} + +.green-btn { + @include colorBtn($green) +} + +.tiffany-btn { + @include colorBtn($tiffany) +} + +.yellow-btn { + @include colorBtn($yellow) +} + +.pan-btn { + font-size: 14px; + color: #fff; + padding: 14px 36px; + border-radius: 8px; + border: none; + outline: none; + transition: 600ms ease all; + position: relative; + display: inline-block; + + &:hover { + background: #fff; + + &:before, + &:after { + width: 100%; + transition: 600ms ease all; + } + } + + &:before, + &:after { + content: ''; + position: absolute; + top: 0; + right: 0; + height: 2px; + width: 0; + transition: 400ms ease all; + } + + &::after { + right: inherit; + top: inherit; + left: 0; + bottom: 0; + } +} + +.custom-button { + display: inline-block; + line-height: 1; + white-space: nowrap; + cursor: pointer; + background: #fff; + color: #fff; + -webkit-appearance: none; + text-align: center; + box-sizing: border-box; + outline: 0; + margin: 0; + padding: 10px 15px; + font-size: 14px; + border-radius: 4px; +} diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss new file mode 100644 index 0000000..52671af --- /dev/null +++ b/src/assets/styles/element-ui.scss @@ -0,0 +1,141 @@ +// cover some element-ui styles + +.el-breadcrumb__inner, +.el-breadcrumb__inner a { + font-weight: 400 !important; +} + +.el-upload { + input[type="file"] { + display: none !important; + } +} + +.el-upload__input { + display: none; +} + +.cell { + .el-tag { + margin-right: 0px; + } +} + +.small-padding { + .cell { + padding-left: 5px; + padding-right: 5px; + } +} + +.fixed-width { + .el-button--mini { + padding: 7px 10px; + width: 60px; + } +} + +.status-col { + .cell { + padding: 0 10px; + text-align: center; + + .el-tag { + margin-right: 0px; + } + } +} + +// to fixed https://github.com/ElemeFE/element/issues/2461 +.el-dialog { + transform: none; + left: 0; + position: relative; + margin: 0 auto; + border-radius: 4px; + + &__title { + color: #1f76cb; + font-size: 14px; + font-weight: bold; + } +} + +// refine element ui upload +.upload-container { + .el-upload { + width: 100%; + + .el-upload-dragger { + width: 100%; + height: 200px; + } + } +} + +// dropdown +.el-dropdown-menu { + a { + display: block; + } +} + +// fix date-picker ui bug in filter-item +.el-range-editor.el-input__inner { + display: inline-flex !important; +} + +// to fix el-date-picker css style +.el-range-separator { + box-sizing: content-box; +} + +.el-menu--collapse + > div + > .el-submenu + > .el-submenu__title + .el-submenu__icon-arrow { + display: none; +} + +.el-button { + height: 34px; + line-height: 34px; + font-size: 16px; + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.el-form { + &-item { + &__label { + flex-shrink: 0; + font-size: 14px; + color: #1d2129; + font-weight: normal; + line-height: 34px !important; + } + } +} + +.el-form-item--medium .el-form-item__content { + line-height: 34px; +} + +.el-input-number { + width: auto; + line-height: 32px; + + &__decrease, + &__increase { + width: 40px; + background-color: #fff; + } +} + +.el-tabs { + &__active-bar { + transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), + width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + } +} diff --git a/src/assets/styles/element-variables.scss b/src/assets/styles/element-variables.scss new file mode 100644 index 0000000..817cfbe --- /dev/null +++ b/src/assets/styles/element-variables.scss @@ -0,0 +1,38 @@ +/** +* I think element-ui's default theme color is too light for long-term use. +* So I modified the default color and you can modify it to your liking. +**/ + +/* theme color */ +$--color-primary: #1f76cb; +$--color-success: #13ce66; +$--color-warning: #ffba00; +$--color-danger: #ff4949; +// $--color-info: #1E1E1E; + +$--button-font-weight: 400; + +// $--color-text-regular: #1f2d3d; + +$--border-color-light: #dfe4ed; +$--border-color-lighter: #e6ebf5; + +$--table-border: 1px solid #ebeef3; + +$--input-medium-height: 34px; +$--input-border-radius: 0; + +$--form-label-font-size: 14px; + +$--select-input-color: #606266; + +/* icon font path, required */ +$--font-path: "~element-ui/lib/theme-chalk/fonts"; + +@import "~element-ui/packages/theme-chalk/src/index"; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + theme: $--color-primary; +} diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss new file mode 100644 index 0000000..afaab72 --- /dev/null +++ b/src/assets/styles/index.scss @@ -0,0 +1,307 @@ +@import "./variables.scss"; +@import "./mixin.scss"; +@import "./transition.scss"; +@import "./element-ui.scss"; +@import "./sidebar.scss"; +@import "./btn.scss"; + +body { + height: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-family: siyuan-reg, Microsoft YaHei, Arial, sans-serif; +} + +label { + font-weight: 700; +} + +html { + height: 100%; + box-sizing: border-box; +} + +#app { + height: 100%; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +.no-padding { + padding: 0px !important; +} + +.padding-content { + padding: 4px 0; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.fr { + float: right; +} + +.fl { + float: left; +} + +.pr-5 { + padding-right: 5px; +} + +.pl-5 { + padding-left: 5px; +} + +.block { + display: block; +} + +.pointer { + cursor: pointer; +} + +.inlineBlock { + display: block; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } +} + +aside { + background: #eef1f6; + padding: 8px 24px; + margin-bottom: 20px; + border-radius: 2px; + display: block; + line-height: 32px; + font-size: 16px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + color: #2c3e50; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + a { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } + } +} + +//main-container全局样式 +.app-container { + padding: 20px; + background: #fff; + height: 100%; +} + +.components-container { + margin: 30px 50px; + position: relative; +} + +.pagination-container { + margin-top: 30px; +} + +.text-center { + text-align: center; +} + +.sub-navbar { + height: 50px; + line-height: 50px; + position: relative; + width: 100%; + text-align: right; + padding-right: 20px; + transition: 600ms ease position; + background: linear-gradient( + 90deg, + rgba(32, 182, 249, 1) 0%, + rgba(32, 182, 249, 1) 0%, + rgba(33, 120, 241, 1) 100%, + rgba(33, 120, 241, 1) 100% + ); + + .subtitle { + font-size: 20px; + color: #fff; + } + + &.draft { + background: #d0d0d0; + } + + &.deleted { + background: #d0d0d0; + } +} + +.link-type, +.link-type:focus { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } +} + +.filter-container { + padding-bottom: 10px; + + .filter-item { + display: inline-block; + vertical-align: middle; + margin-bottom: 10px; + } +} + +.h-space { + display: flex; +} + +.el-dialog__header { + border-bottom: 1px solid #ddd; + padding-top: 12px; +} + +.el-dialog__footer { + border-top: 1px solid #ddd; + padding-bottom: 12px; +} + +.btn-text-danger { + color: $red !important; +} + +:root { + --variant-panel-background: #fff; +} +.el-table__row.hover-row td { + background-color: #fbfbfb !important; +} +.el-menu.el-menu--horizontal { + border-bottom: 1px solid #1f76cb !important; +} + +.mt-10 { + margin-top: 10px; +} + +.mt-20 { + margin-top: 20px; +} + +@font-face { + font-family: 'siyuan-nor'; + src: url('../font/SourceHanSansCN-Normal.otf'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'siyuan-med'; + src: url('../font/SourceHanSansCN-Medium.otf'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'siyuan-reg'; + src: url('../font/SourceHanSansCN-Regular.otf'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'puhui-bold'; + src: url('../font/Alibaba-PuHuiTi-Bold.otf'); + font-weight: normal; + font-style: normal; +} + +.siyuan-nor { + font-family: siyuan-nor; +} + +.siyuan-med { + font-family: siyuan-med; +} + +.siyuan-reg { + font-family: siyuan-reg; +} + +.puhui-bold { + font-family: puhui-bold; +} + +.el-collapse-item__header { + font-family: 'siyuan-reg'; + font-size: 14px; + letter-spacing: 0px; + color: #1f76cb; +} +.ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.el-dialog__header { + background-color: #2076cb; +} + +.el-dialog__title { + font-family: MicrosoftYaHei; + font-size: 14px; + font-weight: bold; + letter-spacing: 1px; + color: #ffffff; +} + +.el-dialog__body { + padding: 20px; +} + +.el-dialog__headerbtn .el-dialog__close { + color: #ffffff; +} + +.el-table .custom-table-header th { + background-color: #ECF4FF !important; +} 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/ruoyi.scss b/src/assets/styles/ruoyi.scss new file mode 100644 index 0000000..161c0e4 --- /dev/null +++ b/src/assets/styles/ruoyi.scss @@ -0,0 +1,361 @@ +/** +* 通用css样式布局处理 +* Copyright (c) 2019 ruoyi +*/ + +/** 基础通用 **/ +.pt5 { + padding-top: 5px; +} + +.pr5 { + padding-right: 5px; +} + +.pb5 { + padding-bottom: 5px; +} + +.mt5 { + margin-top: 5px; +} + +.mr5 { + margin-right: 5px; +} + +.mb5 { + margin-bottom: 5px; +} + +.mb8 { + margin-bottom: 8px; +} + +.ml5 { + margin-left: 5px; +} + +.mt10 { + margin-top: 10px; +} + +.mr10 { + margin-right: 10px; +} + +.mb10 { + margin-bottom: 10px; +} +.ml10 { + margin-left: 10px; +} + +.mt20 { + margin-top: 20px; +} + +.mr20 { + margin-right: 20px; +} + +.mb20 { + margin-bottom: 20px; +} +.ml20 { + margin-left: 20px; +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + +.el-message-box__status + .el-message-box__message { + word-break: break-word; +} + +.el-dialog:not(.is-fullscreen) { + margin-top: 6vh !important; +} + +.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body { + overflow: auto; + overflow-x: hidden; + max-height: 70vh; + padding: 10px 20px 0; +} + +.el-table { + color: #002242; + + .el-table__header-wrapper, + .el-table__fixed-header-wrapper { + th { + word-break: break-word; + background-color: #f8f8f9; + color: #000; + } + } + + .el-table__body-wrapper { + .el-button [class*="el-icon-"] + span { + margin-left: 1px; + } + } + + .el-table__body { + .el-table__row { + &:nth-child(2n) { + background-color: #fbfbfb; + } + + &.el-table__row_checked { + background-color: #fbfbfb; + } + } + } + + .custom-table-header { + th { + background-color: #f5f5f5; + } + } + + .el-table__cell { + padding: 8px 0; + } + + .cell { + line-height: 22px; + } +} + +/** 表单布局 **/ +.form-header { + font-size: 15px; + color: #6379bb; + border-bottom: 1px solid #ddd; + margin: 8px 10px 25px 10px; + padding-bottom: 5px; +} + +/** 表格布局 **/ +.pagination-container { + position: relative; + height: 25px; + margin-bottom: 10px; + margin-top: 15px; + padding: 10px 20px !important; +} + +/* tree border */ +.tree-border { + margin-top: 5px; + border: 1px solid #e5e6e7; + background: #ffffff none; + border-radius: 4px; +} + +.pagination-container .el-pagination { + right: 0; + position: absolute; +} + +@media (max-width: 768px) { + .pagination-container .el-pagination > .el-pagination__jump { + display: none !important; + } + .pagination-container .el-pagination > .el-pagination__sizes { + display: none !important; + } +} + +.el-table .fixed-width .el-button--mini { + padding-left: 0; + padding-right: 0; + width: inherit; +} + +/** 表格更多操作下拉样式 */ +.el-table .el-dropdown-link, +.el-table .el-dropdown-selfdefine { + cursor: pointer; + margin-left: 5px; +} + +.el-table .el-dropdown, +.el-icon-arrow-down { + font-size: 12px; +} + +.el-tree-node__content > .el-checkbox { + margin-right: 8px; +} + +.list-group-striped > .list-group-item { + border-left: 0; + border-right: 0; + border-radius: 0; + padding-left: 0; + padding-right: 0; +} + +.list-group { + padding-left: 0px; + list-style: none; +} + +.list-group-item { + border-bottom: 1px solid #e7eaec; + border-top: 1px solid #e7eaec; + margin-bottom: -1px; + padding: 11px 0px; + font-size: 13px; +} + +.pull-right { + float: right !important; +} + +.el-card { + display: flex; + flex-direction: column; + border-radius: 0; +} + +.el-card__header { + min-height: 30px; + padding: 0; + padding-right: 10px; + display: flex; + align-items: center; + gap: 15px; + font-size: 14px; + color: #1d2129; + letter-spacing: 1px; + + &::before { + content: ""; + width: 4px; + height: 14px; + background: #1e89ff; + } +} + +.el-card__body { + padding: 10px; + flex: 1; + overflow: auto; +} + +.card-box { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 10px; +} + +/* button color */ +.el-button--cyan.is-active, +.el-button--cyan:active { + background: #20b2aa; + border-color: #20b2aa; + color: #ffffff; +} + +.el-button--cyan:focus, +.el-button--cyan:hover { + background: #48d1cc; + border-color: #48d1cc; + color: #ffffff; +} + +.el-button--cyan { + background-color: #20b2aa; + border-color: #20b2aa; + color: #ffffff; +} + +/* text color */ +.text-navy { + color: #1ab394; +} + +.text-primary { + color: inherit; +} + +.text-success { + color: #1c84c6; +} + +.text-info { + color: #23c6c8; +} + +.text-warning { + color: #f8ac59; +} + +.text-danger { + color: #ed5565; +} + +.text-muted { + color: #888888; +} + +/* image */ +.img-circle { + border-radius: 50%; +} + +.img-lg { + width: 120px; + height: 120px; +} + +.avatar-upload-preview { + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 200px; + height: 200px; + border-radius: 50%; + box-shadow: 0 0 4px #ccc; + overflow: hidden; +} + +/* 拖拽列样式 */ +.sortable-ghost { + opacity: 0.8; + color: #fff !important; + background: #42b983 !important; +} + +.top-right-btn { + position: relative; + float: right; +} + +.el-button.is-disabled, +.el-button.is-disabled:hover, +.el-button.is-disabled:focus { + background-color: #ebebeb; + border-color: #d9d9d9; + color: rgba(0, 0, 0, 0.25); +} diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss new file mode 100644 index 0000000..abe5b63 --- /dev/null +++ b/src/assets/styles/sidebar.scss @@ -0,0 +1,227 @@ +#app { + + .main-container { + height: 100%; + transition: margin-left .28s; + margin-left: $base-sidebar-width; + position: relative; + } + + .sidebarHide { + margin-left: 0!important; + } + + .sidebar-container { + -webkit-transition: width .28s; + transition: width 0.28s; + width: $base-sidebar-width !important; + background-color: $base-menu-background; + height: 100%; + position: fixed; + font-size: 0px; + top: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: hidden; + -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); + box-shadow: 2px 0 6px rgba(0,21,41,.35); + + // reset element-ui css + .horizontal-collapse-transition { + transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; + } + + .scrollbar-wrapper { + overflow-x: hidden !important; + } + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + + .el-scrollbar { + height: 100%; + } + + &.has-logo { + .el-scrollbar { + height: calc(100% - 50px); + } + } + + .is-horizontal { + display: none; + } + + a { + display: inline-block; + width: 100%; + overflow: hidden; + } + + .svg-icon { + margin-right: 16px; + } + + .el-menu { + border: none; + height: 100%; + width: 100% !important; + } + + .el-menu-item, .el-submenu__title { + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + // menu hover + .submenu-title-noDropdown, + .el-submenu__title { + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .is-active > .el-submenu__title { + color: $base-menu-color-active !important; + } + + & .nest-menu .el-submenu>.el-submenu__title, + & .el-submenu .el-menu-item { + min-width: $base-sidebar-width !important; + + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .nest-menu .el-submenu>.el-submenu__title, + & .theme-dark .el-submenu .el-menu-item { + background-color: $base-sub-menu-background !important; + + &:hover { + background-color: $base-sub-menu-hover !important; + } + } + } + + .hideSidebar { + .sidebar-container { + width: 54px !important; + } + + .main-container { + margin-left: 54px; + } + + .submenu-title-noDropdown { + padding: 0 !important; + position: relative; + + .el-tooltip { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + } + } + + .el-submenu { + overflow: hidden; + + &>.el-submenu__title { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + + } + } + + .el-menu--collapse { + .el-submenu { + &>.el-submenu__title { + &>span { + height: 0; + width: 0; + overflow: hidden; + visibility: hidden; + display: inline-block; + } + } + } + } + } + + .el-menu--collapse .el-menu .el-submenu { + min-width: $base-sidebar-width !important; + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar-container { + transition: transform .28s; + width: $base-sidebar-width !important; + } + + &.hideSidebar { + .sidebar-container { + pointer-events: none; + transition-duration: 0.3s; + transform: translate3d(-$base-sidebar-width, 0, 0); + } + } + } + + .withoutAnimation { + + .main-container, + .sidebar-container { + transition: none; + } + } +} + +// when menu collapsed +.el-menu--vertical { + &>.el-menu { + .svg-icon { + margin-right: 16px; + } + } + + .nest-menu .el-submenu>.el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + // the scroll bar appears when the subMenu is too long + >.el-menu--popup { + max-height: 100vh; + overflow-y: auto; + + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } + } +} diff --git a/src/assets/styles/transition.scss b/src/assets/styles/transition.scss new file mode 100644 index 0000000..073f8c6 --- /dev/null +++ b/src/assets/styles/transition.scss @@ -0,0 +1,49 @@ +// global transition css + +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/* fade-transform */ +.fade-transform--move, +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all .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.scss b/src/assets/styles/variables.scss new file mode 100644 index 0000000..95720fa --- /dev/null +++ b/src/assets/styles/variables.scss @@ -0,0 +1,54 @@ +// base color +$blue:#324157; +$light-blue:#3A71A8; +$red:#C03639; +$pink: #E65D6E; +$green: #30B08F; +$tiffany: #4AB7BD; +$yellow:#FEC171; +$panGreen: #30B08F; + +// 默认菜单主题风格 +$base-menu-color:#bfcbd9; +$base-menu-color-active:#f4f4f5; +$base-menu-background:#304156; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#1f2d3d; +$base-sub-menu-hover:#001528; + +// 自定义暗色菜单风格 +/** +$base-menu-color:hsla(0,0%,100%,.65); +$base-menu-color-active:#fff; +$base-menu-background:#001529; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#000c17; +$base-sub-menu-hover:#001528; +*/ + +$base-sidebar-width: 0; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + menuColor: $base-menu-color; + menuLightColor: $base-menu-light-color; + menuColorActive: $base-menu-color-active; + menuBackground: $base-menu-background; + menuLightBackground: $base-menu-light-background; + subMenuBackground: $base-sub-menu-background; + subMenuHover: $base-sub-menu-hover; + sideBarWidth: $base-sidebar-width; + logoTitleColor: $base-logo-title-color; + logoLightTitleColor: $base-logo-light-title-color +} diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue new file mode 100644 index 0000000..98e4e30 --- /dev/null +++ b/src/components/Breadcrumb/index.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/src/components/Crontab/day.vue b/src/components/Crontab/day.vue new file mode 100644 index 0000000..fe3eaf0 --- /dev/null +++ b/src/components/Crontab/day.vue @@ -0,0 +1,161 @@ + + + diff --git a/src/components/Crontab/hour.vue b/src/components/Crontab/hour.vue new file mode 100644 index 0000000..4b1f1fc --- /dev/null +++ b/src/components/Crontab/hour.vue @@ -0,0 +1,114 @@ + + + diff --git a/src/components/Crontab/index.vue b/src/components/Crontab/index.vue new file mode 100644 index 0000000..3963df2 --- /dev/null +++ b/src/components/Crontab/index.vue @@ -0,0 +1,430 @@ + + + + diff --git a/src/components/Crontab/min.vue b/src/components/Crontab/min.vue new file mode 100644 index 0000000..43cab90 --- /dev/null +++ b/src/components/Crontab/min.vue @@ -0,0 +1,116 @@ + + + \ No newline at end of file diff --git a/src/components/Crontab/month.vue b/src/components/Crontab/month.vue new file mode 100644 index 0000000..fd0ac38 --- /dev/null +++ b/src/components/Crontab/month.vue @@ -0,0 +1,114 @@ + + + diff --git a/src/components/Crontab/result.vue b/src/components/Crontab/result.vue new file mode 100644 index 0000000..aea6e0e --- /dev/null +++ b/src/components/Crontab/result.vue @@ -0,0 +1,559 @@ + + + diff --git a/src/components/Crontab/second.vue b/src/components/Crontab/second.vue new file mode 100644 index 0000000..e7b7761 --- /dev/null +++ b/src/components/Crontab/second.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/components/Crontab/week.vue b/src/components/Crontab/week.vue new file mode 100644 index 0000000..1cec700 --- /dev/null +++ b/src/components/Crontab/week.vue @@ -0,0 +1,202 @@ + + + diff --git a/src/components/Crontab/year.vue b/src/components/Crontab/year.vue new file mode 100644 index 0000000..5487a6c --- /dev/null +++ b/src/components/Crontab/year.vue @@ -0,0 +1,131 @@ + + + diff --git a/src/components/DictData/index.js b/src/components/DictData/index.js new file mode 100644 index 0000000..7b85d4a --- /dev/null +++ b/src/components/DictData/index.js @@ -0,0 +1,49 @@ +import Vue from 'vue' +import store from '@/store' +import DataDict from '@/utils/dict' +import { getDicts as getDicts } from '@/api/system/dict/data' + +function searchDictByKey(dict, key) { + if (key == null && key == "") { + return null + } + try { + for (let i = 0; i < dict.length; i++) { + if (dict[i].key == key) { + return dict[i].value + } + } + } catch (e) { + return null + } +} + +function install() { + Vue.use(DataDict, { + metas: { + '*': { + labelField: 'dictLabel', + valueField: 'dictValue', + request(dictMeta) { + const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) + if (storeDict) { + return new Promise(resolve => { resolve(storeDict) }) + } else { + return new Promise((resolve, reject) => { + getDicts(dictMeta.type).then(res => { + store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) + resolve(res.data) + }).catch(error => { + reject(error) + }) + }) + } + }, + }, + }, + }) +} + +export default { + install, +} \ No newline at end of file diff --git a/src/components/DictTag/index.vue b/src/components/DictTag/index.vue new file mode 100644 index 0000000..279b613 --- /dev/null +++ b/src/components/DictTag/index.vue @@ -0,0 +1,92 @@ + + + + diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue new file mode 100644 index 0000000..1f2e15e --- /dev/null +++ b/src/components/Editor/index.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/src/components/FJ/ContentCard/index.vue b/src/components/FJ/ContentCard/index.vue new file mode 100644 index 0000000..a3a5cdf --- /dev/null +++ b/src/components/FJ/ContentCard/index.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/src/components/FJ/LeftCard/index.vue b/src/components/FJ/LeftCard/index.vue new file mode 100644 index 0000000..2ff850e --- /dev/null +++ b/src/components/FJ/LeftCard/index.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/components/FJ/PageCard/index.vue b/src/components/FJ/PageCard/index.vue new file mode 100644 index 0000000..2d717a0 --- /dev/null +++ b/src/components/FJ/PageCard/index.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/components/FJ/RightCard/index.vue b/src/components/FJ/RightCard/index.vue new file mode 100644 index 0000000..581af9c --- /dev/null +++ b/src/components/FJ/RightCard/index.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue new file mode 100644 index 0000000..08cc711 --- /dev/null +++ b/src/components/FileUpload/index.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/src/components/HButton/index.vue b/src/components/HButton/index.vue new file mode 100644 index 0000000..da96977 --- /dev/null +++ b/src/components/HButton/index.vue @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/src/components/HCard/index.vue b/src/components/HCard/index.vue new file mode 100644 index 0000000..e5bf2ac --- /dev/null +++ b/src/components/HCard/index.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/components/HCommonTable/index.vue b/src/components/HCommonTable/index.vue new file mode 100644 index 0000000..4d97fca --- /dev/null +++ b/src/components/HCommonTable/index.vue @@ -0,0 +1,192 @@ + + + + + \ No newline at end of file diff --git a/src/components/HDict/index.vue b/src/components/HDict/index.vue new file mode 100644 index 0000000..90bebb2 --- /dev/null +++ b/src/components/HDict/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/components/HEditTable/index.vue b/src/components/HEditTable/index.vue new file mode 100644 index 0000000..ddb89ef --- /dev/null +++ b/src/components/HEditTable/index.vue @@ -0,0 +1,570 @@ + + + diff --git a/src/components/HEmpty/index.vue b/src/components/HEmpty/index.vue new file mode 100644 index 0000000..ece2337 --- /dev/null +++ b/src/components/HEmpty/index.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/src/components/HExport/index.vue b/src/components/HExport/index.vue new file mode 100644 index 0000000..89d551b --- /dev/null +++ b/src/components/HExport/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/components/HForm/enum.js b/src/components/HForm/enum.js new file mode 100644 index 0000000..0f26211 --- /dev/null +++ b/src/components/HForm/enum.js @@ -0,0 +1,12 @@ +export const FormItemType = { + dateTimeRange: "datetimerange", + datePicker: "datepicker", + textArea: "textarea", + number: "number", + radioGroup: "radiogroup", + dict: "dict", + title: "title", + checkboxGroup: "checkboxGroup", + select: "select", + richText: "richText", +}; diff --git a/src/components/HForm/index.vue b/src/components/HForm/index.vue new file mode 100644 index 0000000..c92614a --- /dev/null +++ b/src/components/HForm/index.vue @@ -0,0 +1,195 @@ + + + diff --git a/src/components/HFormula/index.vue b/src/components/HFormula/index.vue new file mode 100644 index 0000000..9341ed3 --- /dev/null +++ b/src/components/HFormula/index.vue @@ -0,0 +1,69 @@ + + + diff --git a/src/components/HImport/index.vue b/src/components/HImport/index.vue new file mode 100644 index 0000000..8108e8b --- /dev/null +++ b/src/components/HImport/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/src/components/HInputGroup/index.vue b/src/components/HInputGroup/index.vue new file mode 100644 index 0000000..48571a9 --- /dev/null +++ b/src/components/HInputGroup/index.vue @@ -0,0 +1,60 @@ + + + + + \ No newline at end of file diff --git a/src/components/HLoading/index.vue b/src/components/HLoading/index.vue new file mode 100644 index 0000000..78b7231 --- /dev/null +++ b/src/components/HLoading/index.vue @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/src/components/HModal/index.vue b/src/components/HModal/index.vue new file mode 100644 index 0000000..95d84a4 --- /dev/null +++ b/src/components/HModal/index.vue @@ -0,0 +1,77 @@ + + diff --git a/src/components/HPageContainer/CardTitle.vue b/src/components/HPageContainer/CardTitle.vue new file mode 100644 index 0000000..7cce168 --- /dev/null +++ b/src/components/HPageContainer/CardTitle.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/components/HPageContainer/index.vue b/src/components/HPageContainer/index.vue new file mode 100644 index 0000000..02006b5 --- /dev/null +++ b/src/components/HPageContainer/index.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/components/HPopupTableSelect/index.vue b/src/components/HPopupTableSelect/index.vue new file mode 100644 index 0000000..1cf4d19 --- /dev/null +++ b/src/components/HPopupTableSelect/index.vue @@ -0,0 +1,210 @@ + + + + + \ No newline at end of file diff --git a/src/components/HSpace/index.jsx b/src/components/HSpace/index.jsx new file mode 100644 index 0000000..4cace5b --- /dev/null +++ b/src/components/HSpace/index.jsx @@ -0,0 +1,23 @@ +export default { + name: 'HSpace', + props: { + size: { + type: Number, + default: 10 + }, + align: { + type: String, + default: 'left' + } + }, + render() { + const items = this.$slots.default + const style = { + gap: this.size + 'px', + justifyContent: this.align + } + return
+ { items.map((child, i) =>
{ child }
) } +
+ } +} diff --git a/src/components/HTable/index.vue b/src/components/HTable/index.vue new file mode 100644 index 0000000..f337eba --- /dev/null +++ b/src/components/HTable/index.vue @@ -0,0 +1,736 @@ + + + diff --git a/src/components/HTitle/index.vue b/src/components/HTitle/index.vue new file mode 100644 index 0000000..e6159dc --- /dev/null +++ b/src/components/HTitle/index.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/components/HVirtualTable/index.vue b/src/components/HVirtualTable/index.vue new file mode 100644 index 0000000..03b9ae7 --- /dev/null +++ b/src/components/HVirtualTable/index.vue @@ -0,0 +1,359 @@ + + + diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue new file mode 100644 index 0000000..368b002 --- /dev/null +++ b/src/components/Hamburger/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue new file mode 100644 index 0000000..c4d76bb --- /dev/null +++ b/src/components/HeaderSearch/index.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/src/components/IconSelect/index.vue b/src/components/IconSelect/index.vue new file mode 100644 index 0000000..8dadc02 --- /dev/null +++ b/src/components/IconSelect/index.vue @@ -0,0 +1,104 @@ + + + + + + diff --git a/src/components/IconSelect/requireIcons.js b/src/components/IconSelect/requireIcons.js new file mode 100644 index 0000000..99e5c54 --- /dev/null +++ b/src/components/IconSelect/requireIcons.js @@ -0,0 +1,11 @@ + +const req = require.context('../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const icons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default icons diff --git a/src/components/ImagePreview/index.vue b/src/components/ImagePreview/index.vue new file mode 100644 index 0000000..cd99626 --- /dev/null +++ b/src/components/ImagePreview/index.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue new file mode 100644 index 0000000..fa44e1b --- /dev/null +++ b/src/components/ImageUpload/index.vue @@ -0,0 +1,228 @@ + + + + diff --git a/src/components/Page/assessment-instrument-container.vue b/src/components/Page/assessment-instrument-container.vue new file mode 100644 index 0000000..b038cb7 --- /dev/null +++ b/src/components/Page/assessment-instrument-container.vue @@ -0,0 +1,133 @@ + + + + + \ No newline at end of file diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue new file mode 100644 index 0000000..56f5a6b --- /dev/null +++ b/src/components/Pagination/index.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/src/components/PanThumb/index.vue b/src/components/PanThumb/index.vue new file mode 100644 index 0000000..1bcf417 --- /dev/null +++ b/src/components/PanThumb/index.vue @@ -0,0 +1,142 @@ + + + + + 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/ProductTree/index.vue b/src/components/ProductTree/index.vue new file mode 100644 index 0000000..d1653e1 --- /dev/null +++ b/src/components/ProductTree/index.vue @@ -0,0 +1,330 @@ + + + + + \ No newline at end of file diff --git a/src/components/RightPanel/index.vue b/src/components/RightPanel/index.vue new file mode 100644 index 0000000..5abeecb --- /dev/null +++ b/src/components/RightPanel/index.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/components/RightToolbar/index.vue b/src/components/RightToolbar/index.vue new file mode 100644 index 0000000..527e07c --- /dev/null +++ b/src/components/RightToolbar/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/src/components/RuoYi/Doc/index.vue b/src/components/RuoYi/Doc/index.vue new file mode 100644 index 0000000..257e397 --- /dev/null +++ b/src/components/RuoYi/Doc/index.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/components/RuoYi/Git/index.vue b/src/components/RuoYi/Git/index.vue new file mode 100644 index 0000000..43b23e9 --- /dev/null +++ b/src/components/RuoYi/Git/index.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue new file mode 100644 index 0000000..d4e539c --- /dev/null +++ b/src/components/Screenfull/index.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/SizeSelect/index.vue b/src/components/SizeSelect/index.vue new file mode 100644 index 0000000..069b5de --- /dev/null +++ b/src/components/SizeSelect/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..e4bf5ad --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/components/ThemePicker/index.vue b/src/components/ThemePicker/index.vue new file mode 100644 index 0000000..7a70bb8 --- /dev/null +++ b/src/components/ThemePicker/index.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue new file mode 100644 index 0000000..9fb8dd8 --- /dev/null +++ b/src/components/TopNav/index.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/components/iFrame/index.vue b/src/components/iFrame/index.vue new file mode 100644 index 0000000..426857f --- /dev/null +++ b/src/components/iFrame/index.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue new file mode 100644 index 0000000..f797ccb --- /dev/null +++ b/src/layout/components/Navbar.vue @@ -0,0 +1,197 @@ + + + + + diff --git a/src/layout/components/Settings/index.vue b/src/layout/components/Settings/index.vue new file mode 100644 index 0000000..3f9991d --- /dev/null +++ b/src/layout/components/Settings/index.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..f92d99b --- /dev/null +++ b/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue new file mode 100644 index 0000000..96585a5 --- /dev/null +++ b/src/layout/components/TagsView/index.vue @@ -0,0 +1,332 @@ + + + + + + + diff --git a/src/layout/components/TopBar/TopBar.vue b/src/layout/components/TopBar/TopBar.vue new file mode 100644 index 0000000..6fffc5e --- /dev/null +++ b/src/layout/components/TopBar/TopBar.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/src/layout/components/TopNav/FixiOSBug.js b/src/layout/components/TopNav/FixiOSBug.js new file mode 100644 index 0000000..6823726 --- /dev/null +++ b/src/layout/components/TopNav/FixiOSBug.js @@ -0,0 +1,25 @@ +export default { + computed: { + device() { + return this.$store.state.app.device + } + }, + mounted() { + // In order to fix the click on menu on the ios device will trigger the mouseleave bug + this.fixBugIniOS() + }, + methods: { + fixBugIniOS() { + const $subMenu = this.$refs.subMenu + if ($subMenu) { + const handleMouseleave = $subMenu.handleMouseleave + $subMenu.handleMouseleave = (e) => { + if (this.device === 'mobile') { + return + } + handleMouseleave(e) + } + } + } + } +} diff --git a/src/layout/components/TopNav/Item.vue b/src/layout/components/TopNav/Item.vue new file mode 100644 index 0000000..1ff4700 --- /dev/null +++ b/src/layout/components/TopNav/Item.vue @@ -0,0 +1,33 @@ + diff --git a/src/layout/components/TopNav/Link.vue b/src/layout/components/TopNav/Link.vue new file mode 100644 index 0000000..8b0bc93 --- /dev/null +++ b/src/layout/components/TopNav/Link.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/layout/components/TopNav/Logo.vue b/src/layout/components/TopNav/Logo.vue new file mode 100644 index 0000000..b8d9d6b --- /dev/null +++ b/src/layout/components/TopNav/Logo.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/src/layout/components/TopNav/SidebarItem.vue b/src/layout/components/TopNav/SidebarItem.vue new file mode 100644 index 0000000..0797a4a --- /dev/null +++ b/src/layout/components/TopNav/SidebarItem.vue @@ -0,0 +1,159 @@ + + + + diff --git a/src/layout/components/TopNav/index.vue b/src/layout/components/TopNav/index.vue new file mode 100644 index 0000000..6c27f35 --- /dev/null +++ b/src/layout/components/TopNav/index.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/src/layout/components/index.js b/src/layout/components/index.js new file mode 100644 index 0000000..078eafd --- /dev/null +++ b/src/layout/components/index.js @@ -0,0 +1,6 @@ +export { default as AppMain } from './AppMain' +export { default as Navbar } from './Navbar' +export { default as Settings } from './Settings' +export { default as TopNav } from './TopNav/index.vue' +export { default as TagsView } from './TagsView/index.vue' +export { default as TopBar } from './TopBar/TopBar.vue' diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..f9e9336 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/layout/mixin/ResizeHandler.js b/src/layout/mixin/ResizeHandler.js new file mode 100644 index 0000000..e8d0df8 --- /dev/null +++ b/src/layout/mixin/ResizeHandler.js @@ -0,0 +1,45 @@ +import store from '@/store' + +const { body } = document +const WIDTH = 992 // refer to Bootstrap's responsive design + +export default { + watch: { + $route(route) { + if (this.device === 'mobile' && this.sidebar.opened) { + store.dispatch('app/closeSideBar', { withoutAnimation: false }) + } + } + }, + beforeMount() { + window.addEventListener('resize', this.$_resizeHandler) + }, + beforeDestroy() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + mounted() { + const isMobile = this.$_isMobile() + if (isMobile) { + store.dispatch('app/toggleDevice', 'mobile') + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_isMobile() { + const rect = body.getBoundingClientRect() + return rect.width - 1 < WIDTH + }, + $_resizeHandler() { + if (!document.hidden) { + const isMobile = this.$_isMobile() + store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') + + if (isMobile) { + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + } + } + } +} diff --git a/src/lib/echarts.js b/src/lib/echarts.js new file mode 100644 index 0000000..35bd5d6 --- /dev/null +++ b/src/lib/echarts.js @@ -0,0 +1,28 @@ +import { use } from "echarts/core"; +import { LineChart, PieChart, BarChart } from "echarts/charts"; +import { + TitleComponent, + TooltipComponent, + LegendComponent, + GridComponent, +} from "echarts/components"; +import { CanvasRenderer } from "echarts/renderers"; + +import ECharts from "vue-echarts"; + +use([ + TitleComponent, + TooltipComponent, + LegendComponent, + LineChart, + PieChart, + CanvasRenderer, + GridComponent, + BarChart, +]); + +export default { + install(Vue) { + Vue.component("v-chart", ECharts); + }, +}; diff --git a/src/lib/wordcloud/WordCloudSeries.js b/src/lib/wordcloud/WordCloudSeries.js new file mode 100644 index 0000000..a561a1c --- /dev/null +++ b/src/lib/wordcloud/WordCloudSeries.js @@ -0,0 +1,59 @@ +import * as echarts from 'echarts/lib/echarts'; + +echarts.extendSeriesModel({ + type: 'series.wordCloud', + + visualStyleAccessPath: 'textStyle', + visualStyleMapper: function (model) { + return { + fill: model.get('color') + }; + }, + visualDrawType: 'fill', + + optionUpdated: function () { + var option = this.option; + option.gridSize = Math.max(Math.floor(option.gridSize), 4); + }, + + getInitialData: function (option, ecModel) { + var dimensions = echarts.helper.createDimensions(option.data, { + coordDimensions: ['value'] + }); + var list = new echarts.List(dimensions, this); + list.initData(option.data); + return list; + }, + + // Most of options are from https://github.com/timdream/wordcloud2.js/blob/gh-pages/API.md + defaultOption: { + maskImage: null, + + // Shape can be 'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star' + shape: 'circle', + keepAspect: false, + + left: 'center', + + top: 'center', + + width: '70%', + + height: '80%', + + sizeRange: [12, 60], + + rotationRange: [-90, 90], + + rotationStep: 45, + + gridSize: 8, + + drawOutOfBound: false, + shrinkToFit: false, + + textStyle: { + fontWeight: 'normal' + } + } +}); diff --git a/src/lib/wordcloud/WordCloudView.js b/src/lib/wordcloud/WordCloudView.js new file mode 100644 index 0000000..78806ff --- /dev/null +++ b/src/lib/wordcloud/WordCloudView.js @@ -0,0 +1,99 @@ +import * as echarts from "echarts"; + +echarts.extendChartView({ + type: "wordCloud", + + render: function (seriesModel, ecModel, api) { + const group = this.group; + group.removeAll(); + + const data = seriesModel.getData(); + + const gridSize = seriesModel.get("gridSize"); + + seriesModel.layoutInstance.ondraw = function (text, size, dataIdx, drawn) { + const itemModel = data.getItemModel(dataIdx); + const textStyleModel = itemModel.getModel("textStyle"); + const { option: label } = itemModel.getModel("label"); + const labelStyle = itemModel.getModel("labelStyle"); + + const textEl = new echarts.graphic.Text({ + style: echarts.helper.createTextStyle(textStyleModel), + scaleX: 1 / drawn.info.mu, + scaleY: 1 / drawn.info.mu, + x: (drawn.gx + drawn.info.gw / 2) * gridSize, + y: (drawn.gy + drawn.info.gh / 2) * gridSize, + rotation: drawn.rot, + }); + textEl.setStyle({ + x: drawn.info.fillTextOffsetX, + y: drawn.info.fillTextOffsetY + size * 0.5, + text: text, + verticalAlign: "middle", + fill: data.getItemVisual(dataIdx, "style").fill, + fontSize: size, + }); + const textLabel = new echarts.graphic.Text({ + style: echarts.helper.createTextStyle(labelStyle), + scaleX: 1 / drawn.info.mu, + scaleY: 1 / drawn.info.mu, + x: (drawn.gx + drawn.info.gw / 2) * gridSize, + y: (drawn.gy + drawn.info.gh / 2) * gridSize, + rotation: drawn.rot, + }); + textLabel.setStyle({ + x: drawn.info.fillTextOffsetX + size * 0.45, + y: drawn.info.fillTextOffsetY + size * 0.45, + // text: label.length > 5 ? label.slice(0, 5) + '...' : label, + text: label, + align: "center", + verticalAlign: "middle", + }); + + group.add(textEl); + group.add(textLabel); + + data.setItemGraphicEl(dataIdx, textEl); + + textEl.ensureState("emphasis").style = echarts.helper.createTextStyle( + itemModel.getModel(["emphasis", "textStyle"]), + { + state: "emphasis", + } + ); + textEl.ensureState("blur").style = echarts.helper.createTextStyle( + itemModel.getModel(["blur", "textStyle"]), + { + state: "blur", + } + ); + + echarts.helper.enableHoverEmphasis( + textEl, + itemModel.get(["emphasis", "focus"]), + itemModel.get(["emphasis", "blurScope"]) + ); + + textEl.stateTransition = { + duration: seriesModel.get("animation") + ? seriesModel.get(["stateAnimation", "duration"]) + : 0, + easing: seriesModel.get(["stateAnimation", "easing"]), + }; + // TODO + textEl.__highDownDispatcher = true; + }; + + this._model = seriesModel; + }, + + remove: function () { + this.group.removeAll(); + + this._model.layoutInstance.dispose(); + }, + + dispose: function () { + this._model.layoutInstance.dispose(); + }, +}); diff --git a/src/lib/wordcloud/layout.js b/src/lib/wordcloud/layout.js new file mode 100644 index 0000000..e4ee4cf --- /dev/null +++ b/src/lib/wordcloud/layout.js @@ -0,0 +1,1339 @@ +/*! + * wordcloud2.js + * http://timdream.org/wordcloud2.js/ + * + * Copyright 2011 - 2019 Tim Guan-tin Chien and contributors. + * Released under the MIT license + */ + +'use strict'; + +// setImmediate +if (!window.setImmediate) { + window.setImmediate = (function setupSetImmediate() { + return ( + window.msSetImmediate || + window.webkitSetImmediate || + window.mozSetImmediate || + window.oSetImmediate || + (function setupSetZeroTimeout() { + if (!window.postMessage || !window.addEventListener) { + return null; + } + + var callbacks = [undefined]; + var message = 'zero-timeout-message'; + + // Like setTimeout, but only takes a function argument. There's + // no time argument (always zero) and no arguments (you have to + // use a closure). + var setZeroTimeout = function setZeroTimeout(callback) { + var id = callbacks.length; + callbacks.push(callback); + window.postMessage(message + id.toString(36), '*'); + + return id; + }; + + window.addEventListener( + 'message', + function setZeroTimeoutMessage(evt) { + // Skipping checking event source, retarded IE confused this window + // object with another in the presence of iframe + if ( + typeof evt.data !== 'string' || + evt.data.substr(0, message.length) !== message /* || + evt.source !== window */ + ) { + return; + } + + evt.stopImmediatePropagation(); + + var id = parseInt(evt.data.substr(message.length), 36); + if (!callbacks[id]) { + return; + } + + callbacks[id](); + callbacks[id] = undefined; + }, + true + ); + + /* specify clearImmediate() here since we need the scope */ + window.clearImmediate = function clearZeroTimeout(id) { + if (!callbacks[id]) { + return; + } + + callbacks[id] = undefined; + }; + + return setZeroTimeout; + })() || + // fallback + function setImmediateFallback(fn) { + window.setTimeout(fn, 0); + } + ); + })(); +} + +if (!window.clearImmediate) { + window.clearImmediate = (function setupClearImmediate() { + return ( + window.msClearImmediate || + window.webkitClearImmediate || + window.mozClearImmediate || + window.oClearImmediate || + // "clearZeroTimeout" is implement on the previous block || + // fallback + function clearImmediateFallback(timer) { + window.clearTimeout(timer); + } + ); + })(); +} + +// Check if WordCloud can run on this browser +var isSupported = (function isSupported() { + var canvas = document.createElement('canvas'); + if (!canvas || !canvas.getContext) { + return false; + } + + var ctx = canvas.getContext('2d'); + if (!ctx) { + return false; + } + if (!ctx.getImageData) { + return false; + } + if (!ctx.fillText) { + return false; + } + + if (!Array.prototype.some) { + return false; + } + if (!Array.prototype.push) { + return false; + } + + return true; +})(); + +// Find out if the browser impose minium font size by +// drawing small texts on a canvas and measure it's width. +var minFontSize = (function getMinFontSize() { + if (!isSupported) { + return; + } + + var ctx = document.createElement('canvas').getContext('2d'); + + // start from 20 + var size = 20; + + // two sizes to measure + var hanWidth, mWidth; + + while (size) { + ctx.font = size.toString(10) + 'px sans-serif'; + if ( + ctx.measureText('\uFF37').width === hanWidth && + ctx.measureText('m').width === mWidth + ) { + return size + 1; + } + + hanWidth = ctx.measureText('\uFF37').width; + mWidth = ctx.measureText('m').width; + + size--; + } + + return 0; +})(); + +var getItemExtraData = function (item) { + if (Array.isArray(item)) { + var itemCopy = item.slice(); + // remove data we already have (word and weight) + itemCopy.splice(0, 2); + return itemCopy; + } else { + return []; + } +}; + +// Based on http://jsfromhell.com/array/shuffle +var shuffleArray = function shuffleArray(arr) { + for (var j, x, i = arr.length; i; ) { + j = Math.floor(Math.random() * i); + x = arr[--i]; + arr[i] = arr[j]; + arr[j] = x; + } + return arr; +}; + +var timer = {}; +var WordCloud = function WordCloud(elements, options) { + if (!isSupported) { + return; + } + + var timerId = Math.floor(Math.random() * Date.now()); + + if (!Array.isArray(elements)) { + elements = [elements]; + } + + elements.forEach(function (el, i) { + if (typeof el === 'string') { + elements[i] = document.getElementById(el); + if (!elements[i]) { + throw new Error('The element id specified is not found.'); + } + } else if (!el.tagName && !el.appendChild) { + throw new Error( + 'You must pass valid HTML elements, or ID of the element.' + ); + } + }); + + /* Default values to be overwritten by options object */ + var settings = { + list: [], + fontFamily: + '"Trebuchet MS", "Heiti TC", "微軟正黑體", ' + + '"Arial Unicode MS", "Droid Fallback Sans", sans-serif', + fontWeight: 'normal', + color: 'random-dark', + minSize: 0, // 0 to disable + weightFactor: 1, + clearCanvas: true, + backgroundColor: '#fff', // opaque white = rgba(255, 255, 255, 1) + + gridSize: 8, + drawOutOfBound: false, + shrinkToFit: false, + origin: null, + + drawMask: false, + maskColor: 'rgba(255,0,0,0.3)', + maskGapWidth: 0.3, + + layoutAnimation: true, + + wait: 0, + abortThreshold: 0, // disabled + abort: function noop() {}, + + minRotation: -Math.PI / 2, + maxRotation: Math.PI / 2, + rotationStep: 0.1, + + shuffle: true, + rotateRatio: 0.1, + + shape: 'circle', + ellipticity: 0.65, + + classes: null, + + hover: null, + click: null + }; + + if (options) { + for (var key in options) { + if (key in settings) { + settings[key] = options[key]; + } + } + } + + /* Convert weightFactor into a function */ + if (typeof settings.weightFactor !== 'function') { + var factor = settings.weightFactor; + settings.weightFactor = function weightFactor(pt) { + return pt * factor; // in px + }; + } + + /* Convert shape into a function */ + if (typeof settings.shape !== 'function') { + switch (settings.shape) { + case 'circle': + /* falls through */ + default: + // 'circle' is the default and a shortcut in the code loop. + settings.shape = 'circle'; + break; + + case 'cardioid': + settings.shape = function shapeCardioid(theta) { + return 1 - Math.sin(theta); + }; + break; + + /* + To work out an X-gon, one has to calculate "m", + where 1/(cos(2*PI/X)+m*sin(2*PI/X)) = 1/(cos(0)+m*sin(0)) + http://www.wolframalpha.com/input/?i=1%2F%28cos%282*PI%2FX%29%2Bm*sin%28 + 2*PI%2FX%29%29+%3D+1%2F%28cos%280%29%2Bm*sin%280%29%29 + Copy the solution into polar equation r = 1/(cos(t') + m*sin(t')) + where t' equals to mod(t, 2PI/X); + */ + + case 'diamond': + // http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+ + // %28t%2C+PI%2F2%29%29%2Bsin%28mod+%28t%2C+PI%2F2%29%29%29%2C+t+%3D + // +0+..+2*PI + settings.shape = function shapeSquare(theta) { + var thetaPrime = theta % ((2 * Math.PI) / 4); + return 1 / (Math.cos(thetaPrime) + Math.sin(thetaPrime)); + }; + break; + + case 'square': + // http://www.wolframalpha.com/input/?i=plot+r+%3D+min(1%2Fabs(cos(t + // )),1%2Fabs(sin(t)))),+t+%3D+0+..+2*PI + settings.shape = function shapeSquare(theta) { + return Math.min( + 1 / Math.abs(Math.cos(theta)), + 1 / Math.abs(Math.sin(theta)) + ); + }; + break; + + case 'triangle-forward': + // http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+ + // %28t%2C+2*PI%2F3%29%29%2Bsqrt%283%29sin%28mod+%28t%2C+2*PI%2F3%29 + // %29%29%2C+t+%3D+0+..+2*PI + settings.shape = function shapeTriangle(theta) { + var thetaPrime = theta % ((2 * Math.PI) / 3); + return ( + 1 / (Math.cos(thetaPrime) + Math.sqrt(3) * Math.sin(thetaPrime)) + ); + }; + break; + + case 'triangle': + case 'triangle-upright': + settings.shape = function shapeTriangle(theta) { + var thetaPrime = (theta + (Math.PI * 3) / 2) % ((2 * Math.PI) / 3); + return ( + 1 / (Math.cos(thetaPrime) + Math.sqrt(3) * Math.sin(thetaPrime)) + ); + }; + break; + + case 'pentagon': + settings.shape = function shapePentagon(theta) { + var thetaPrime = (theta + 0.955) % ((2 * Math.PI) / 5); + return 1 / (Math.cos(thetaPrime) + 0.726543 * Math.sin(thetaPrime)); + }; + break; + + case 'star': + settings.shape = function shapeStar(theta) { + var thetaPrime = (theta + 0.955) % ((2 * Math.PI) / 10); + if ( + ((theta + 0.955) % ((2 * Math.PI) / 5)) - (2 * Math.PI) / 10 >= + 0 + ) { + return ( + 1 / + (Math.cos((2 * Math.PI) / 10 - thetaPrime) + + 3.07768 * Math.sin((2 * Math.PI) / 10 - thetaPrime)) + ); + } else { + return 1 / (Math.cos(thetaPrime) + 3.07768 * Math.sin(thetaPrime)); + } + }; + break; + } + } + + /* Make sure gridSize is a whole number and is not smaller than 4px */ + settings.gridSize = Math.max(Math.floor(settings.gridSize), 4); + + /* shorthand */ + var g = settings.gridSize; + var maskRectWidth = g - settings.maskGapWidth; + + /* normalize rotation settings */ + var rotationRange = Math.abs(settings.maxRotation - settings.minRotation); + var minRotation = Math.min(settings.maxRotation, settings.minRotation); + var rotationStep = settings.rotationStep; + + /* information/object available to all functions, set when start() */ + var grid, // 2d array containing filling information + ngx, + ngy, // width and height of the grid + center, // position of the center of the cloud + maxRadius; + + /* timestamp for measuring each putWord() action */ + var escapeTime; + + /* function for getting the color of the text */ + var getTextColor; + function randomHslColor(min, max) { + return ( + 'hsl(' + + (Math.random() * 360).toFixed() + + ',' + + (Math.random() * 30 + 70).toFixed() + + '%,' + + (Math.random() * (max - min) + min).toFixed() + + '%)' + ); + } + switch (settings.color) { + case 'random-dark': + getTextColor = function getRandomDarkColor() { + return randomHslColor(10, 50); + }; + break; + + case 'random-light': + getTextColor = function getRandomLightColor() { + return randomHslColor(50, 90); + }; + break; + + default: + if (typeof settings.color === 'function') { + getTextColor = settings.color; + } + break; + } + + /* function for getting the font-weight of the text */ + var getTextFontWeight; + if (typeof settings.fontWeight === 'function') { + getTextFontWeight = settings.fontWeight; + } + + /* function for getting the classes of the text */ + var getTextClasses = null; + if (typeof settings.classes === 'function') { + getTextClasses = settings.classes; + } + + /* Interactive */ + var interactive = false; + var infoGrid = []; + var hovered; + + var getInfoGridFromMouseTouchEvent = function getInfoGridFromMouseTouchEvent( + evt + ) { + var canvas = evt.currentTarget; + var rect = canvas.getBoundingClientRect(); + var clientX; + var clientY; + /** Detect if touches are available */ + if (evt.touches) { + clientX = evt.touches[0].clientX; + clientY = evt.touches[0].clientY; + } else { + clientX = evt.clientX; + clientY = evt.clientY; + } + var eventX = clientX - rect.left; + var eventY = clientY - rect.top; + + var x = Math.floor((eventX * (canvas.width / rect.width || 1)) / g); + var y = Math.floor((eventY * (canvas.height / rect.height || 1)) / g); + + if (!infoGrid[x]) { + return null + } + + return infoGrid[x][y]; + }; + + var wordcloudhover = function wordcloudhover(evt) { + var info = getInfoGridFromMouseTouchEvent(evt); + + if (hovered === info) { + return; + } + + hovered = info; + if (!info) { + settings.hover(undefined, undefined, evt); + + return; + } + + settings.hover(info.item, info.dimension, evt); + }; + + var wordcloudclick = function wordcloudclick(evt) { + var info = getInfoGridFromMouseTouchEvent(evt); + if (!info) { + return; + } + + settings.click(info.item, info.dimension, evt); + evt.preventDefault(); + }; + + /* Get points on the grid for a given radius away from the center */ + var pointsAtRadius = []; + var getPointsAtRadius = function getPointsAtRadius(radius) { + if (pointsAtRadius[radius]) { + return pointsAtRadius[radius]; + } + + // Look for these number of points on each radius + var T = radius * 8; + + // Getting all the points at this radius + var t = T; + var points = []; + + if (radius === 0) { + points.push([center[0], center[1], 0]); + } + + while (t--) { + // distort the radius to put the cloud in shape + var rx = 1; + if (settings.shape !== 'circle') { + rx = settings.shape((t / T) * 2 * Math.PI); // 0 to 1 + } + + // Push [x, y, t]; t is used solely for getTextColor() + points.push([ + center[0] + radius * rx * Math.cos((-t / T) * 2 * Math.PI), + center[1] + + radius * rx * Math.sin((-t / T) * 2 * Math.PI) * settings.ellipticity, + (t / T) * 2 * Math.PI + ]); + } + + pointsAtRadius[radius] = points; + return points; + }; + + /* Return true if we had spent too much time */ + var exceedTime = function exceedTime() { + return ( + settings.abortThreshold > 0 && + new Date().getTime() - escapeTime > settings.abortThreshold + ); + }; + + /* Get the deg of rotation according to settings, and luck. */ + var getRotateDeg = function getRotateDeg() { + if (settings.rotateRatio === 0) { + return 0; + } + + if (Math.random() > settings.rotateRatio) { + return 0; + } + + if (rotationRange === 0) { + return minRotation; + } + + return minRotation + Math.round(Math.random() * rotationRange / rotationStep) * rotationStep; + }; + + var getTextInfo = function getTextInfo( + word, + weight, + rotateDeg, + extraDataArray + ) { + // calculate the acutal font size + // fontSize === 0 means weightFactor function wants the text skipped, + // and size < minSize means we cannot draw the text. + var debug = false; + var fontSize = settings.weightFactor(weight); + if (fontSize <= settings.minSize) { + return false; + } + + // Scale factor here is to make sure fillText is not limited by + // the minium font size set by browser. + // It will always be 1 or 2n. + var mu = 1; + if (fontSize < minFontSize) { + mu = (function calculateScaleFactor() { + var mu = 2; + while (mu * fontSize < minFontSize) { + mu += 2; + } + return mu; + })(); + } + + // Get fontWeight that will be used to set fctx.font + var fontWeight; + if (getTextFontWeight) { + fontWeight = getTextFontWeight(word, weight, fontSize, extraDataArray); + } else { + fontWeight = settings.fontWeight; + } + + var fcanvas = document.createElement('canvas'); + var fctx = fcanvas.getContext('2d', { willReadFrequently: true }); + + fctx.font = + fontWeight + + ' ' + + (fontSize * mu).toString(10) + + 'px ' + + settings.fontFamily; + + // Estimate the dimension of the text with measureText(). + var fw = fctx.measureText(word).width / mu; + var fh = + Math.max( + fontSize * mu, + fctx.measureText('m').width, + fctx.measureText('\uFF37').width + ) / mu; + + // Create a boundary box that is larger than our estimates, + // so text don't get cut of (it sill might) + var boxWidth = fw + fh * 2; + var boxHeight = fh * 3; + var fgw = Math.ceil(boxWidth / g); + var fgh = Math.ceil(boxHeight / g); + boxWidth = fgw * g; + boxHeight = fgh * g; + + // Calculate the proper offsets to make the text centered at + // the preferred position. + + // This is simply half of the width. + var fillTextOffsetX = -fw / 2; + // Instead of moving the box to the exact middle of the preferred + // position, for Y-offset we move 0.4 instead, so Latin alphabets look + // vertical centered. + var fillTextOffsetY = -fh * 0.4; + + // Calculate the actual dimension of the canvas, considering the rotation. + var cgh = Math.ceil( + (boxWidth * Math.abs(Math.sin(rotateDeg)) + + boxHeight * Math.abs(Math.cos(rotateDeg))) / + g + ); + var cgw = Math.ceil( + (boxWidth * Math.abs(Math.cos(rotateDeg)) + + boxHeight * Math.abs(Math.sin(rotateDeg))) / + g + ); + var width = cgw * g; + var height = cgh * g; + + fcanvas.setAttribute('width', width); + fcanvas.setAttribute('height', height); + + if (debug) { + // Attach fcanvas to the DOM + document.body.appendChild(fcanvas); + // Save it's state so that we could restore and draw the grid correctly. + fctx.save(); + } + + // Scale the canvas with |mu|. + fctx.scale(1 / mu, 1 / mu); + fctx.translate((width * mu) / 2, (height * mu) / 2); + fctx.rotate(-rotateDeg); + + // Once the width/height is set, ctx info will be reset. + // Set it again here. + fctx.font = + fontWeight + + ' ' + + (fontSize * mu).toString(10) + + 'px ' + + settings.fontFamily; + + // Fill the text into the fcanvas. + // XXX: We cannot because textBaseline = 'top' here because + // Firefox and Chrome uses different default line-height for canvas. + // Please read https://bugzil.la/737852#c6. + // Here, we use textBaseline = 'middle' and draw the text at exactly + // 0.5 * fontSize lower. + fctx.fillStyle = '#000'; + fctx.textBaseline = 'middle'; + fctx.fillText( + word, + fillTextOffsetX * mu, + (fillTextOffsetY + fontSize * 0.5) * mu + ); + + // Get the pixels of the text + var imageData = fctx.getImageData(0, 0, width, height).data; + + if (exceedTime()) { + return false; + } + + if (debug) { + // Draw the box of the original estimation + fctx.strokeRect(fillTextOffsetX * mu, fillTextOffsetY, fw * mu, fh * mu); + fctx.restore(); + } + + // Read the pixels and save the information to the occupied array + var occupied = []; + var gx = cgw; + var gy, x, y; + var bounds = [cgh / 2, cgw / 2, cgh / 2, cgw / 2]; + while (gx--) { + gy = cgh; + while (gy--) { + y = g; + /* eslint no-labels: ['error', { 'allowLoop': true }] */ + singleGridLoop: while (y--) { + x = g; + while (x--) { + if (imageData[((gy * g + y) * width + (gx * g + x)) * 4 + 3]) { + occupied.push([gx, gy]); + + if (gx < bounds[3]) { + bounds[3] = gx; + } + if (gx > bounds[1]) { + bounds[1] = gx; + } + if (gy < bounds[0]) { + bounds[0] = gy; + } + if (gy > bounds[2]) { + bounds[2] = gy; + } + + if (debug) { + fctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; + fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5); + } + break singleGridLoop; + } + } + } + if (debug) { + fctx.fillStyle = 'rgba(0, 0, 255, 0.5)'; + fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5); + } + } + } + + if (debug) { + fctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; + fctx.fillRect( + bounds[3] * g, + bounds[0] * g, + (bounds[1] - bounds[3] + 1) * g, + (bounds[2] - bounds[0] + 1) * g + ); + } + + // Return information needed to create the text on the real canvas + return { + mu: mu, + occupied: occupied, + bounds: bounds, + gw: cgw, + gh: cgh, + fillTextOffsetX: fillTextOffsetX, + fillTextOffsetY: fillTextOffsetY, + fillTextWidth: fw, + fillTextHeight: fh, + fontSize: fontSize + }; + }; + + /* Determine if there is room available in the given dimension */ + var canFitText = function canFitText(gx, gy, gw, gh, occupied) { + // Go through the occupied points, + // return false if the space is not available. + var i = occupied.length; + while (i--) { + var px = gx + occupied[i][0]; + var py = gy + occupied[i][1]; + + if (px >= ngx || py >= ngy || px < 0 || py < 0) { + if (!settings.drawOutOfBound) { + return false; + } + continue; + } + + if (!grid[px][py]) { + return false; + } + } + return true; + }; + + /* Actually draw the text on the grid */ + var drawText = function drawText( + gx, + gy, + info, + word, + weight, + distance, + theta, + rotateDeg, + attributes, + extraDataArray + ) { + var fontSize = info.fontSize; + var color; + if (getTextColor) { + color = getTextColor( + word, + weight, + fontSize, + distance, + theta, + extraDataArray + ); + } else { + color = settings.color; + } + + // get fontWeight that will be used to set ctx.font and font style rule + var fontWeight; + if (getTextFontWeight) { + fontWeight = getTextFontWeight(word, weight, fontSize, extraDataArray); + } else { + fontWeight = settings.fontWeight; + } + + var classes; + if (getTextClasses) { + classes = getTextClasses(word, weight, fontSize, extraDataArray); + } else { + classes = settings.classes; + } + + elements.forEach(function (el) { + if (el.getContext) { + var ctx = el.getContext('2d'); + var mu = info.mu; + + // Save the current state before messing it + ctx.save(); + ctx.scale(1 / mu, 1 / mu); + + ctx.font = + fontWeight + + ' ' + + (fontSize * mu).toString(10) + + 'px ' + + settings.fontFamily; + ctx.fillStyle = color; + + // Translate the canvas position to the origin coordinate of where + // the text should be put. + ctx.translate((gx + info.gw / 2) * g * mu, (gy + info.gh / 2) * g * mu); + + if (rotateDeg !== 0) { + ctx.rotate(-rotateDeg); + } + + // Finally, fill the text. + + // XXX: We cannot because textBaseline = 'top' here because + // Firefox and Chrome uses different default line-height for canvas. + // Please read https://bugzil.la/737852#c6. + // Here, we use textBaseline = 'middle' and draw the text at exactly + // 0.5 * fontSize lower. + ctx.textBaseline = 'middle'; + ctx.fillText( + word, + info.fillTextOffsetX * mu, + (info.fillTextOffsetY + fontSize * 0.5) * mu + ); + + // The below box is always matches how s are positioned + /* ctx.strokeRect(info.fillTextOffsetX, info.fillTextOffsetY, + info.fillTextWidth, info.fillTextHeight); */ + + // Restore the state. + ctx.restore(); + } else { + // drawText on DIV element + var span = document.createElement('span'); + var transformRule = ''; + transformRule = 'rotate(' + (-rotateDeg / Math.PI) * 180 + 'deg) '; + if (info.mu !== 1) { + transformRule += + 'translateX(-' + + info.fillTextWidth / 4 + + 'px) ' + + 'scale(' + + 1 / info.mu + + ')'; + } + var styleRules = { + position: 'absolute', + display: 'block', + font: + fontWeight + ' ' + fontSize * info.mu + 'px ' + settings.fontFamily, + left: (gx + info.gw / 2) * g + info.fillTextOffsetX + 'px', + top: (gy + info.gh / 2) * g + info.fillTextOffsetY + 'px', + width: info.fillTextWidth + 'px', + height: info.fillTextHeight + 'px', + lineHeight: fontSize + 'px', + whiteSpace: 'nowrap', + transform: transformRule, + webkitTransform: transformRule, + msTransform: transformRule, + transformOrigin: '50% 40%', + webkitTransformOrigin: '50% 40%', + msTransformOrigin: '50% 40%' + }; + if (color) { + styleRules.color = color; + } + span.textContent = word; + for (var cssProp in styleRules) { + span.style[cssProp] = styleRules[cssProp]; + } + if (attributes) { + for (var attribute in attributes) { + span.setAttribute(attribute, attributes[attribute]); + } + } + if (classes) { + span.className += classes; + } + el.appendChild(span); + } + }); + }; + + /* Help function to updateGrid */ + var fillGridAt = function fillGridAt(x, y, drawMask, dimension, item) { + if (x >= ngx || y >= ngy || x < 0 || y < 0) { + return; + } + + grid[x][y] = false; + + if (drawMask) { + var ctx = elements[0].getContext('2d'); + ctx.fillRect(x * g, y * g, maskRectWidth, maskRectWidth); + } + + if (interactive) { + infoGrid[x][y] = { item: item, dimension: dimension }; + } + }; + + /* Update the filling information of the given space with occupied points. + Draw the mask on the canvas if necessary. */ + var updateGrid = function updateGrid(gx, gy, gw, gh, info, item) { + var occupied = info.occupied; + var drawMask = settings.drawMask; + var ctx; + if (drawMask) { + ctx = elements[0].getContext('2d'); + ctx.save(); + ctx.fillStyle = settings.maskColor; + } + + var dimension; + if (interactive) { + var bounds = info.bounds; + dimension = { + x: (gx + bounds[3]) * g, + y: (gy + bounds[0]) * g, + w: (bounds[1] - bounds[3] + 1) * g, + h: (bounds[2] - bounds[0] + 1) * g + }; + } + + var i = occupied.length; + while (i--) { + var px = gx + occupied[i][0]; + var py = gy + occupied[i][1]; + + if (px >= ngx || py >= ngy || px < 0 || py < 0) { + continue; + } + + fillGridAt(px, py, drawMask, dimension, item); + } + + if (drawMask) { + ctx.restore(); + } + }; + + /* putWord() processes each item on the list, + calculate it's size and determine it's position, and actually + put it on the canvas. */ + var putWord = function putWord(item, loopIndex) { + if (loopIndex > 20) { + return null; + } + + var word, weight, attributes; + if (Array.isArray(item)) { + word = item[0]; + weight = item[1]; + } else { + word = item.word; + weight = item.weight; + attributes = item.attributes; + } + var rotateDeg = getRotateDeg(); + + var extraDataArray = getItemExtraData(item); + + // get info needed to put the text onto the canvas + var info = getTextInfo(word, weight, rotateDeg, extraDataArray); + + // not getting the info means we shouldn't be drawing this one. + if (!info) { + return false; + } + + if (exceedTime()) { + return false; + } + + // If drawOutOfBound is set to false, + // skip the loop if we have already know the bounding box of + // word is larger than the canvas. + if (!settings.drawOutOfBound && !settings.shrinkToFit) { + var bounds = info.bounds; + if (bounds[1] - bounds[3] + 1 > ngx || bounds[2] - bounds[0] + 1 > ngy) { + return false; + } + } + + // Determine the position to put the text by + // start looking for the nearest points + var r = maxRadius + 1; + + var tryToPutWordAtPoint = function (gxy) { + var gx = Math.floor(gxy[0] - info.gw / 2); + var gy = Math.floor(gxy[1] - info.gh / 2); + var gw = info.gw; + var gh = info.gh; + + // If we cannot fit the text at this position, return false + // and go to the next position. + if (!canFitText(gx, gy, gw, gh, info.occupied)) { + return false; + } + + // Actually put the text on the canvas + drawText( + gx, + gy, + info, + word, + weight, + maxRadius - r, + gxy[2], + rotateDeg, + attributes, + extraDataArray + ); + + // Mark the spaces on the grid as filled + updateGrid(gx, gy, gw, gh, info, item); + + return { + gx: gx, + gy: gy, + rot: rotateDeg, + info: info + }; + }; + + while (r--) { + var points = getPointsAtRadius(maxRadius - r); + + if (settings.shuffle) { + points = [].concat(points); + shuffleArray(points); + } + + // Try to fit the words by looking at each point. + // array.some() will stop and return true + // when putWordAtPoint() returns true. + for (var i = 0; i < points.length; i++) { + var res = tryToPutWordAtPoint(points[i]); + if (res) { + return res; + } + } + + // var drawn = points.some(tryToPutWordAtPoint); + // if (drawn) { + // // leave putWord() and return true + // return true; + // } + } + + if (settings.shrinkToFit) { + if (Array.isArray(item)) { + item[1] = (item[1] * 3) / 4; + } else { + item.weight = (item.weight * 3) / 4; + } + return putWord(item, loopIndex + 1); + } + + // we tried all distances but text won't fit, return null + return null; + }; + + /* Send DOM event to all elements. Will stop sending event and return + if the previous one is canceled (for cancelable events). */ + var sendEvent = function sendEvent(type, cancelable, details) { + if (cancelable) { + return !elements.some(function (el) { + var event = new CustomEvent(type, { + detail: details || {} + }); + return !el.dispatchEvent(event); + }, this); + } else { + elements.forEach(function (el) { + var event = new CustomEvent(type, { + detail: details || {} + }); + el.dispatchEvent(event); + }, this); + } + }; + + /* Start drawing on a canvas */ + var start = function start() { + // For dimensions, clearCanvas etc., + // we only care about the first element. + var canvas = elements[0]; + + if (canvas.getContext) { + ngx = Math.ceil(canvas.width / g); + ngy = Math.ceil(canvas.height / g); + } else { + var rect = canvas.getBoundingClientRect(); + ngx = Math.ceil(rect.width / g); + ngy = Math.ceil(rect.height / g); + } + + // Sending a wordcloudstart event which cause the previous loop to stop. + // Do nothing if the event is canceled. + if (!sendEvent('wordcloudstart', true)) { + return; + } + + // Determine the center of the word cloud + center = settings.origin + ? [settings.origin[0] / g, settings.origin[1] / g] + : [ngx / 2, ngy / 2]; + + // Maxium radius to look for space + maxRadius = Math.floor(Math.sqrt(ngx * ngx + ngy * ngy)); + + /* Clear the canvas only if the clearCanvas is set, + if not, update the grid to the current canvas state */ + grid = []; + + var gx, gy, i; + if (!canvas.getContext || settings.clearCanvas) { + elements.forEach(function (el) { + if (el.getContext) { + var ctx = el.getContext('2d'); + ctx.fillStyle = settings.backgroundColor; + ctx.clearRect(0, 0, ngx * (g + 1), ngy * (g + 1)); + ctx.fillRect(0, 0, ngx * (g + 1), ngy * (g + 1)); + } else { + el.textContent = ''; + el.style.backgroundColor = settings.backgroundColor; + el.style.position = 'relative'; + } + }); + + /* fill the grid with empty state */ + gx = ngx; + while (gx--) { + grid[gx] = []; + gy = ngy; + while (gy--) { + grid[gx][gy] = true; + } + } + } else { + /* Determine bgPixel by creating + another canvas and fill the specified background color. */ + var bctx = document.createElement('canvas').getContext('2d'); + + bctx.fillStyle = settings.backgroundColor; + bctx.fillRect(0, 0, 1, 1); + var bgPixel = bctx.getImageData(0, 0, 1, 1).data; + + /* Read back the pixels of the canvas we got to tell which part of the + canvas is empty. + (no clearCanvas only works with a canvas, not divs) */ + var imageData = canvas + .getContext('2d') + .getImageData(0, 0, ngx * g, ngy * g).data; + + gx = ngx; + var x, y; + while (gx--) { + grid[gx] = []; + gy = ngy; + while (gy--) { + y = g; + /* eslint no-labels: ['error', { 'allowLoop': true }] */ + singleGridLoop: while (y--) { + x = g; + while (x--) { + i = 4; + while (i--) { + if ( + imageData[((gy * g + y) * ngx * g + (gx * g + x)) * 4 + i] !== + bgPixel[i] + ) { + grid[gx][gy] = false; + break singleGridLoop; + } + } + } + } + if (grid[gx][gy] !== false) { + grid[gx][gy] = true; + } + } + } + + imageData = bctx = bgPixel = undefined; + } + + // fill the infoGrid with empty state if we need it + if (settings.hover || settings.click) { + interactive = true; + + /* fill the grid with empty state */ + gx = ngx + 1; + while (gx--) { + infoGrid[gx] = []; + } + + if (settings.hover) { + canvas.addEventListener('mousemove', wordcloudhover); + } + + if (settings.click) { + canvas.addEventListener('click', wordcloudclick); + canvas.addEventListener('touchstart', wordcloudclick); + canvas.addEventListener('touchend', function (e) { + e.preventDefault(); + }); + canvas.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)'; + } + + canvas.addEventListener('wordcloudstart', function stopInteraction() { + canvas.removeEventListener('wordcloudstart', stopInteraction); + + canvas.removeEventListener('mousemove', wordcloudhover); + canvas.removeEventListener('click', wordcloudclick); + hovered = undefined; + }); + } + + i = 0; + var loopingFunction, stoppingFunction; + var layouting = true; + if (!settings.layoutAnimation) { + loopingFunction = function (cb) { + cb(); + }; + stoppingFunction = function () { + layouting = false; + }; + } else if (settings.wait !== 0) { + loopingFunction = window.setTimeout; + stoppingFunction = window.clearTimeout; + } else { + loopingFunction = window.setImmediate; + stoppingFunction = window.clearImmediate; + } + + var addEventListener = function addEventListener(type, listener) { + elements.forEach(function (el) { + el.addEventListener(type, listener); + }, this); + }; + + var removeEventListener = function removeEventListener(type, listener) { + elements.forEach(function (el) { + el.removeEventListener(type, listener); + }, this); + }; + + var anotherWordCloudStart = function anotherWordCloudStart() { + removeEventListener('wordcloudstart', anotherWordCloudStart); + stoppingFunction(timer[timerId]); + }; + + addEventListener('wordcloudstart', anotherWordCloudStart); + + // At least wait the following code before call the first iteration. + timer[timerId] = (settings.layoutAnimation ? loopingFunction : setTimeout)( + function loop() { + if (!layouting) { + return; + } + if (i >= settings.list.length) { + stoppingFunction(timer[timerId]); + sendEvent('wordcloudstop', false); + removeEventListener('wordcloudstart', anotherWordCloudStart); + delete timer[timerId]; + return; + } + escapeTime = new Date().getTime(); + var drawn = putWord(settings.list[i], 0); + var canceled = !sendEvent('wordclouddrawn', true, { + item: settings.list[i], + drawn: drawn + }); + if (exceedTime() || canceled) { + stoppingFunction(timer[timerId]); + settings.abort(); + sendEvent('wordcloudabort', false); + sendEvent('wordcloudstop', false); + removeEventListener('wordcloudstart', anotherWordCloudStart); + return; + } + i++; + timer[timerId] = loopingFunction(loop, settings.wait); + }, + settings.wait + ); + }; + + // All set, start the drawing + start(); +}; + +WordCloud.isSupported = isSupported; +WordCloud.minFontSize = minFontSize; + +export default WordCloud; diff --git a/src/lib/wordcloud/wordCloud.js b/src/lib/wordcloud/wordCloud.js new file mode 100644 index 0000000..fbdf574 --- /dev/null +++ b/src/lib/wordcloud/wordCloud.js @@ -0,0 +1,213 @@ +import * as echarts from 'echarts/lib/echarts'; + +import './WordCloudSeries'; +import './WordCloudView'; + +import wordCloudLayoutHelper from './layout'; + +if (!wordCloudLayoutHelper.isSupported) { + throw new Error('Sorry your browser not support wordCloud'); +} + +// https://github.com/timdream/wordcloud2.js/blob/c236bee60436e048949f9becc4f0f67bd832dc5c/index.js#L233 +function updateCanvasMask(maskCanvas) { + var ctx = maskCanvas.getContext('2d'); + var imageData = ctx.getImageData(0, 0, maskCanvas.width, maskCanvas.height); + var newImageData = ctx.createImageData(imageData); + + var toneSum = 0; + var toneCnt = 0; + for (var i = 0; i < imageData.data.length; i += 4) { + var alpha = imageData.data[i + 3]; + if (alpha > 128) { + var tone = + imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]; + toneSum += tone; + ++toneCnt; + } + } + var threshold = toneSum / toneCnt; + + for (var i = 0; i < imageData.data.length; i += 4) { + var tone = + imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2]; + var alpha = imageData.data[i + 3]; + + if (alpha < 128 || tone > threshold) { + // Area not to draw + newImageData.data[i] = 0; + newImageData.data[i + 1] = 0; + newImageData.data[i + 2] = 0; + newImageData.data[i + 3] = 0; + } else { + // Area to draw + // The color must be same with backgroundColor + newImageData.data[i] = 255; + newImageData.data[i + 1] = 255; + newImageData.data[i + 2] = 255; + newImageData.data[i + 3] = 255; + } + } + + ctx.putImageData(newImageData, 0, 0); +} + +echarts.registerLayout(function (ecModel, api) { + ecModel.eachSeriesByType('wordCloud', function (seriesModel) { + var gridRect = echarts.helper.getLayoutRect( + seriesModel.getBoxLayoutParams(), + { + width: api.getWidth(), + height: api.getHeight() + } + ); + + var keepAspect = seriesModel.get('keepAspect'); + var maskImage = seriesModel.get('maskImage'); + var ratio = maskImage ? maskImage.width / maskImage.height : 1; + keepAspect && adjustRectAspect(gridRect, ratio); + + var data = seriesModel.getData(); + + var canvas = document.createElement('canvas'); + canvas.width = gridRect.width; + canvas.height = gridRect.height; + + var ctx = canvas.getContext('2d'); + if (maskImage) { + try { + ctx.drawImage(maskImage, 0, 0, canvas.width, canvas.height); + updateCanvasMask(canvas); + } catch (e) { + console.error('Invalid mask image'); + console.error(e.toString()); + } + } + + var sizeRange = seriesModel.get('sizeRange'); + var rotationRange = seriesModel.get('rotationRange'); + var valueExtent = data.getDataExtent('value'); + + var DEGREE_TO_RAD = Math.PI / 180; + var gridSize = seriesModel.get('gridSize'); + wordCloudLayoutHelper(canvas, { + list: data + .mapArray('value', function (value, idx) { + var itemModel = data.getItemModel(idx); + return [ + data.getName(idx), + itemModel.get('textStyle.fontSize', true) || + echarts.number.linearMap(value, valueExtent, sizeRange), + idx + ]; + }) + .sort(function (a, b) { + // Sort from large to small in case there is no more room for more words + return b[1] - a[1]; + }), + fontFamily: + seriesModel.get('textStyle.fontFamily') || + seriesModel.get('emphasis.textStyle.fontFamily') || + ecModel.get('textStyle.fontFamily'), + fontWeight: + seriesModel.get('textStyle.fontWeight') || + seriesModel.get('emphasis.textStyle.fontWeight') || + ecModel.get('textStyle.fontWeight'), + + gridSize: gridSize, + + ellipticity: gridRect.height / gridRect.width, + + minRotation: rotationRange[0] * DEGREE_TO_RAD, + maxRotation: rotationRange[1] * DEGREE_TO_RAD, + + clearCanvas: !maskImage, + + rotateRatio: 1, + + rotationStep: seriesModel.get('rotationStep') * DEGREE_TO_RAD, + + drawOutOfBound: seriesModel.get('drawOutOfBound'), + shrinkToFit: seriesModel.get('shrinkToFit'), + + layoutAnimation: seriesModel.get('layoutAnimation'), + + shuffle: false, + + shape: seriesModel.get('shape') + }); + + function onWordCloudDrawn(e) { + var item = e.detail.item; + if (e.detail.drawn && seriesModel.layoutInstance.ondraw) { + e.detail.drawn.gx += gridRect.x / gridSize; + e.detail.drawn.gy += gridRect.y / gridSize; + seriesModel.layoutInstance.ondraw( + item[0], + item[1], + item[2], + e.detail.drawn + ); + } + } + + canvas.addEventListener('wordclouddrawn', onWordCloudDrawn); + + if (seriesModel.layoutInstance) { + // Dispose previous + seriesModel.layoutInstance.dispose(); + } + + seriesModel.layoutInstance = { + ondraw: null, + + dispose: function () { + canvas.removeEventListener('wordclouddrawn', onWordCloudDrawn); + // Abort + canvas.addEventListener('wordclouddrawn', function (e) { + // Prevent default to cancle the event and stop the loop + e.preventDefault(); + }); + } + }; + }); +}); + +echarts.registerPreprocessor(function (option) { + var series = (option || {}).series; + !echarts.util.isArray(series) && (series = series ? [series] : []); + + var compats = ['shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; + + echarts.util.each(series, function (seriesItem) { + if (seriesItem && seriesItem.type === 'wordCloud') { + var textStyle = seriesItem.textStyle || {}; + + compatTextStyle(textStyle.normal); + compatTextStyle(textStyle.emphasis); + } + }); + + function compatTextStyle(textStyle) { + textStyle && + echarts.util.each(compats, function (key) { + if (textStyle.hasOwnProperty(key)) { + textStyle['text' + echarts.format.capitalFirst(key)] = textStyle[key]; + } + }); + } +}); + +function adjustRectAspect(gridRect, aspect) { + // var outerWidth = gridRect.width + gridRect.x * 2; + // var outerHeight = gridRect.height + gridRect.y * 2; + var width = gridRect.width; + var height = gridRect.height; + if (width > height * aspect) { + gridRect.x += (width - height * aspect) / 2; + gridRect.width = height * aspect; + } else { + gridRect.y += (height - width / aspect) / 2; + gridRect.height = width / aspect; + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..7b00857 --- /dev/null +++ b/src/main.js @@ -0,0 +1,131 @@ +import Vue from "vue"; + +import Cookies from "js-cookie"; + +import Element from "element-ui"; +import "./assets/styles/element-variables.scss"; + +import "@/assets/styles/index.scss"; // global css +import "@/assets/styles/ruoyi.scss"; // ruoyi css +import App from "./App"; +import store from "./store"; +import router from "./router"; +import directive from "./directive"; // directive +import plugins from "./plugins"; // plugins +import { download } from "@/utils/request"; + +import "./assets/icons"; // icon +import "./permission"; // permission control +import { getDicts } from "@/api/system/dict/data"; +import { getConfigKey, updateConfigByKey } from "@/api/system/config"; +import { + parseTime, + resetForm, + addDateRange, + selectDictLabel, + selectDictLabels, + handleTree, +} from "@/utils/ruoyi"; +// 分页组件 +import Pagination from "@/components/Pagination"; +// 自定义表格工具组件 +import RightToolbar from "@/components/RightToolbar"; +// 富文本组件 +import Editor from "@/components/Editor"; +// 文件上传组件 +import FileUpload from "@/components/FileUpload"; +// 图片上传组件 +import ImageUpload from "@/components/ImageUpload"; +// 图片预览组件 +import ImagePreview from "@/components/ImagePreview"; +// 字典标签组件 +import DictTag from "@/components/DictTag"; +// 头部标签组件 +import VueMeta from "vue-meta"; +// 字典数据组件 +import DictData from "@/components/DictData"; + +import HTable from "@/components/HTable"; +import HSpace from "@/components/HSpace/index.jsx"; +import HForm from "@/components/HForm"; +import HModal from "@/components/HModal"; +import HCommonTable from "@/components/HCommonTable"; +import HButton from "@/components/HButton"; +import HLoading from "@/components/HLoading"; + +import "mathlive-chinese"; +MathfieldElement.fontsDirectory = "/fonts"; +MathfieldElement.soundsDirectory = "/sounds"; + +import VChart from "@/lib/echarts"; + +import "@/lib/wordcloud/wordCloud"; +import vueBus from "@/utils/vueBus"; + +import "vue-resize/dist/vue-resize.css"; +import VueResize from "vue-resize"; +import { getLabelByValue } from "./utils/dict/DefaultOption"; +Vue.use(VueResize); + +// 全局方法挂载 +Vue.prototype.getDicts = getDicts; +Vue.prototype.getConfigKey = getConfigKey; +Vue.prototype.updateConfigByKey = updateConfigByKey; +Vue.prototype.parseTime = parseTime; +Vue.prototype.resetForm = resetForm; +Vue.prototype.addDateRange = addDateRange; +Vue.prototype.selectDictLabel = selectDictLabel; +Vue.prototype.selectDictLabels = selectDictLabels; +Vue.prototype.download = download; +Vue.prototype.handleTree = handleTree; + +// 全局组件挂载 +Vue.component("DictTag", DictTag); +Vue.component("Pagination", Pagination); +Vue.component("RightToolbar", RightToolbar); +Vue.component("Editor", Editor); +Vue.component("FileUpload", FileUpload); +Vue.component("ImageUpload", ImageUpload); +Vue.component("ImagePreview", ImagePreview); +Vue.component("HTable", HTable); +Vue.component("HSpace", HSpace); +Vue.component("HForm", HForm); +Vue.component("HModal", HModal); +Vue.component("HCommonTable", HCommonTable); +Vue.component("HButton", HButton); +Vue.component("HLoading", HLoading); + +Vue.filter("getLabelByValue", getLabelByValue); + +Vue.use(directive); +Vue.use(plugins); +Vue.use(VueMeta); +Vue.use(VChart); +Vue.use(vueBus); +DictData.install(); +MathfieldElement.locale = "zh-cn"; + +/** + * If you don't want to use mock-server + * you want to use MockJs for mock api + * you can execute: mockXHR() + * + * Currently MockJs will be used in the production environment, + * please remove it before going online! ! ! + */ + +// 修改 el-dialog 默认点击遮照为不关闭 +Element.Dialog.props.closeOnClickModal.default = false; + +Vue.use(Element, { + size: Cookies.get("size") || "medium", // set element-ui default size +}); + +Vue.config.productionTip = false; + +new Vue({ + el: "#app", + router, + store, + render: (h) => h(App), +}); diff --git a/src/permission.js b/src/permission.js new file mode 100644 index 0000000..55cd168 --- /dev/null +++ b/src/permission.js @@ -0,0 +1,75 @@ +import router from "./router"; +import store from "./store"; +import { Message } from "element-ui"; +import NProgress from "nprogress"; +import "nprogress/nprogress.css"; +import { getToken } from "@/utils/auth"; +import { isRelogin } from "@/utils/request"; + +NProgress.configure({ showSpinner: false }); + +const whiteList = ["/login", "/register"]; + +router.beforeEach((to, from, next) => { + NProgress.start(); + if (getToken()) { + to.meta.title && store.dispatch("settings/setTitle", to.meta.title); + /* has token*/ + if (to.path === "/login") { + next({ path: "/" }); + NProgress.done(); + } else { + if (store.getters.roles.length === 0) { + isRelogin.show = true; + // 判断当前用户是否已拉取完user_info信息 + store + .dispatch("GetInfo") + .then(async () => { + isRelogin.show = false; + const accessRoutes = await store.dispatch("GenerateRoutes"); + // 根据roles权限生成可访问的路由表 + router.addRoutes(accessRoutes); // 动态添加可访问路由表 + next({ ...to, replace: true }); // hack方法 确保addRoutes已完成 + }) + .catch((err) => { + store.dispatch("LogOut").then(() => { + Message.error(err); + next({ path: "/" }); + }); + }); + } else { + // 如果要跳转毁伤结果列表 + if ( + to.path == + "/SimulationAndEvaluation/StructuralPatternSimulation/ListOfDamageResults" + ) { + if ( + from.path == + "/SimulationAndEvaluation/StructuralPatternSimulation/SceneSimulation" + ) { + store.commit("app/SET_DESTOY_MODAL_STATE", true); + } else { + next({ + path: "/SimulationAndEvaluation/StructuralPatternSimulation/SceneSimulation", + }); + } + } else { + next(); + } + } + } + } else { + // 没有token + if (whiteList.indexOf(to.path) !== -1) { + // 在免登录白名单,直接进入 + next(); + } else { + next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页 + NProgress.done(); + } + } +}); + +router.afterEach(() => { + NProgress.done(); +}); diff --git a/src/plugins/auth.js b/src/plugins/auth.js new file mode 100644 index 0000000..6c6bc24 --- /dev/null +++ b/src/plugins/auth.js @@ -0,0 +1,60 @@ +import store from '@/store' + +function authPermission(permission) { + const all_permission = "*:*:*"; + const permissions = store.getters && store.getters.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 = store.getters && store.getters.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) + }) + } +} diff --git a/src/plugins/cache.js b/src/plugins/cache.js new file mode 100644 index 0000000..6b5c00b --- /dev/null +++ b/src/plugins/cache.js @@ -0,0 +1,77 @@ +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); + } +} + +export default { + /** + * 会话级缓存 + */ + session: sessionCache, + /** + * 本地缓存 + */ + local: localCache +} diff --git a/src/plugins/download.js b/src/plugins/download.js new file mode 100644 index 0000000..b27702f --- /dev/null +++ b/src/plugins/download.js @@ -0,0 +1,65 @@ +import axios from 'axios' +import {Loading, Message} from 'element-ui' +import { saveAs } from 'file-saver' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { blobValidate } from "@/utils/ruoyi"; + +const baseURL = process.env.VUE_APP_BASE_API +let downloadLoadingInstance; + +export default { + oss(ossId) { + var url = baseURL + '/system/oss/download/' + ossId + downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + const blob = new Blob([res.data], { type: 'application/octet-stream' }) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + downloadLoadingInstance.close(); + }).catch((r) => { + console.error(r) + Message.error('下载文件出现错误,请联系管理员!') + downloadLoadingInstance.close(); + }) + }, + zip(url, name) { + var url = baseURL + url + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { + 'Authorization': 'Bearer ' + getToken(), + 'datasource': localStorage.getItem("dataName") + } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + 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'] + Message.error(errMsg); + } +} + diff --git a/src/plugins/index.js b/src/plugins/index.js new file mode 100644 index 0000000..d000f2d --- /dev/null +++ b/src/plugins/index.js @@ -0,0 +1,20 @@ +import tab from './tab' +import auth from './auth' +import cache from './cache' +import modal from './modal' +import download from './download' + +export default { + install(Vue) { + // 页签操作 + Vue.prototype.$tab = tab + // 认证对象 + Vue.prototype.$auth = auth + // 缓存对象 + Vue.prototype.$cache = cache + // 模态框对象 + Vue.prototype.$modal = modal + // 下载文件 + Vue.prototype.$download = download + } +} diff --git a/src/plugins/modal.js b/src/plugins/modal.js new file mode 100644 index 0000000..b37ca14 --- /dev/null +++ b/src/plugins/modal.js @@ -0,0 +1,83 @@ +import { Message, MessageBox, Notification, Loading } from 'element-ui' + +let loadingInstance; + +export default { + // 消息提示 + msg(content) { + Message.info(content) + }, + // 错误消息 + msgError(content) { + Message.error(content) + }, + // 成功消息 + msgSuccess(content) { + Message.success(content) + }, + // 警告消息 + msgWarning(content) { + Message.warning(content) + }, + // 弹出提示 + alert(content) { + MessageBox.alert(content, "系统提示") + }, + // 错误提示 + alertError(content) { + MessageBox.alert(content, "系统提示", { type: 'error' }) + }, + // 成功提示 + alertSuccess(content) { + MessageBox.alert(content, "系统提示", { type: 'success' }) + }, + // 警告提示 + alertWarning(content) { + MessageBox.alert(content, "系统提示", { type: 'warning' }) + }, + // 通知提示 + notify(content) { + Notification.info(content) + }, + // 错误通知 + notifyError(content) { + Notification.error(content); + }, + // 成功通知 + notifySuccess(content) { + Notification.success(content) + }, + // 警告通知 + notifyWarning(content) { + Notification.warning(content) + }, + // 确认窗体 + confirm(content) { + return MessageBox.confirm(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 提交内容 + prompt(content) { + return MessageBox.prompt(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 打开遮罩层 + loading(content) { + loadingInstance = Loading.service({ + lock: true, + text: content, + spinner: "el-icon-loading", + background: "rgba(0, 0, 0, 0.7)", + }) + }, + // 关闭遮罩层 + closeLoading() { + loadingInstance.close(); + } +} diff --git a/src/plugins/tab.js b/src/plugins/tab.js new file mode 100644 index 0000000..3d757a3 --- /dev/null +++ b/src/plugins/tab.js @@ -0,0 +1,71 @@ +import store from '@/store' +import router from '@/router'; + +export default { + // 刷新当前tab页签 + refreshPage(obj) { + const { path, query, matched } = router.currentRoute; + 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 store.dispatch('tagsView/delCachedView', obj).then(() => { + const { path, query } = obj + router.replace({ + path: '/redirect' + path, + query: query + }) + }) + }, + // 关闭当前tab页签,打开新页签 + closeOpenPage(obj) { + store.dispatch("tagsView/delView", router.currentRoute); + if (obj !== undefined) { + return router.push(obj); + } + }, + // 关闭指定tab页签 + closePage(obj) { + if (obj === undefined) { + return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => { + const latestView = visitedViews.slice(-1)[0] + if (latestView) { + return router.push(latestView.fullPath) + } + return router.push('/'); + }); + } + return store.dispatch('tagsView/delView', obj); + }, + // 关闭所有tab页签 + closeAllPage() { + return store.dispatch('tagsView/delAllViews'); + }, + // 关闭左侧tab页签 + closeLeftPage(obj) { + return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute); + }, + // 关闭右侧tab页签 + closeRightPage(obj) { + return store.dispatch('tagsView/delRightTags', obj || router.currentRoute); + }, + // 关闭其他tab页签 + closeOtherPage(obj) { + return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute); + }, + // 添加tab页签 + openPage(title, url, params) { + var obj = { path: url, meta: { title: title } } + store.dispatch('tagsView/addView', obj); + return router.push({ path: url, query: params }); + }, + // 修改tab页签 + updatePage(obj) { + return store.dispatch('tagsView/updateVisitedView', obj); + } +} diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..61531eb --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,187 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +/* Layout */ +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"}' // 访问路由的默认传递参数 + * roles: ['admin', 'common'] // 访问路由的角色权限 + * permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限 + * meta : { + noCache: true // 如果设置为true,则不会被 缓存(默认 false) + title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 + icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg + breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 + activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 + } + */ + +// 公共路由 +export const constantRoutes = [ + { + path: "/redirect", + component: Layout, + hidden: true, + children: [ + { + path: "/redirect/:path(.*)", + component: () => import("@/views/redirect"), + }, + ], + }, + { + path: "/login", + component: () => import("@/views/login"), + hidden: true, + }, + { + path: "/register", + component: () => import("@/views/register"), + hidden: true, + }, + { + path: "/404", + component: () => import("@/views/error/404"), + hidden: true, + }, + { + path: "/401", + component: () => import("@/views/error/401"), + hidden: true, + }, + { + path: "", + component: Layout, + redirect: "/HighDimensionalData/index", + children: [ + // { + // path: "home", + // component: () => import("@/views/home"), + // name: "Index", + // meta: { + // title: "首页", + // icon: "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" }, + }, + ], + }, +]; + +// 动态路由,基于用户权限动态去加载 +export const dynamicRoutes = [ + { + path: '/system/user-auth', + component: Layout, + hidden: true, + permissions: ['system:user:edit'], + children: [ + { + path: 'role/:userId(\\d+)', + component: () => import('@/views/system/user/authRole'), + name: 'AuthRole', + meta: { title: '分配角色', activeMenu: '/system/user' } + } + ] + }, + { + path: '/system/role-auth', + component: Layout, + hidden: true, + permissions: ['system:role:edit'], + children: [ + { + path: 'user/:roleId(\\d+)', + component: () => import('@/views/system/role/authUser'), + name: 'AuthUser', + meta: { title: '分配用户', activeMenu: '/system/role' } + } + ] + }, + { + path: '/system/dict-data', + component: Layout, + hidden: true, + permissions: ['system:dict:list'], + children: [ + { + path: 'index/:dictId(\\d+)', + component: () => import('@/views/system/dict/data'), + name: 'Data', + meta: { title: '字典数据', activeMenu: '/system/dict' } + } + ] + }, + { + path: '/system/oss-config', + component: Layout, + hidden: true, + permissions: ['system:oss:list'], + children: [ + { + path: 'index', + component: () => import('@/views/system/oss/config'), + name: 'OssConfig', + meta: { title: '配置管理', activeMenu: '/system/oss' } + } + ] + }, + { + path: '/tool/gen-edit', + component: Layout, + hidden: true, + permissions: ['tool:gen:edit'], + children: [ + { + path: 'index/:tableId(\\d+)', + component: () => import('@/views/tool/gen/editTable'), + name: 'GenEdit', + meta: { title: '修改生成配置', activeMenu: '/tool/gen' } + } + ] + } +] + +// 防止连续点击多次路由报错 +let routerPush = Router.prototype.push; +let routerReplace = Router.prototype.replace; +// push +Router.prototype.push = function push(location) { + return routerPush.call(this, location).catch(err => err) +} +// replace +Router.prototype.replace = function push(location) { + return routerReplace.call(this, location).catch(err => err) +} + +export default new Router({ + base: process.env.VUE_APP_CONTEXT_PATH, + mode: 'history', // 去掉url中的# + scrollBehavior: () => ({ y: 0 }), + routes: constantRoutes +}) diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..6a0b09f --- /dev/null +++ b/src/settings.js @@ -0,0 +1,44 @@ +module.exports = { + /** + * 侧边栏主题 深色主题theme-dark,浅色主题theme-light + */ + sideTheme: 'theme-dark', + + /** + * 是否系统布局配置 + */ + 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' +} diff --git a/src/store/getters.js b/src/store/getters.js new file mode 100644 index 0000000..8b1f220 --- /dev/null +++ b/src/store/getters.js @@ -0,0 +1,22 @@ +const getters = { + sidebar: (state) => state.app.sidebar, + size: (state) => state.app.size, + device: (state) => state.app.device, + dict: (state) => state.dict.dict, + visitedViews: (state) => state.tagsView.visitedViews, + cachedViews: (state) => state.tagsView.cachedViews, + token: (state) => state.user.token, + avatar: (state) => state.user.avatar, + name: (state) => state.user.name, + introduction: (state) => state.user.introduction, + roles: (state) => state.user.roles, + permissions: (state) => state.user.permissions, + permission_routes: (state) => state.permission.routes, + topbarRouters: (state) => state.permission.topbarRouters, + defaultRoutes: (state) => state.permission.defaultRoutes, + sidebarRouters: (state) => state.permission.sidebarRouters, + treeData: (state) => state.productTree.treeData, + originalRoutes: (state) => state.permission.originalRoutes, + destroyModalVisible: (state) => state.app.destroyModalVisible, +}; +export default getters; diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..28f78ad --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,30 @@ +import Vue from "vue"; +import Vuex from "vuex"; +import app from "./modules/app"; +import dict from "./modules/dict"; +import user from "./modules/user"; +import tagsView from "./modules/tagsView"; +import permission from "./modules/permission"; +import settings from "./modules/settings"; +// import productTree from "./modules/productTree"; +import getters from "./getters"; + +Vue.use(Vuex); + +const store = new Vuex.Store({ + modules: { + app, + dict, + user, + tagsView, + permission, + settings, + // productTree, + }, + getters, + state: { + VUE_APP_PROVIEW_API: "http://192.168.1.15:8080", + }, +}); + +export default store; diff --git a/src/store/modules/app.js b/src/store/modules/app.js new file mode 100644 index 0000000..da6b2f7 --- /dev/null +++ b/src/store/modules/app.js @@ -0,0 +1,72 @@ +import Cookies from "js-cookie"; + +const state = { + sidebar: { + opened: Cookies.get("sidebarStatus") + ? !!+Cookies.get("sidebarStatus") + : true, + withoutAnimation: false, + hide: false, + }, + device: "desktop", + size: Cookies.get("size") || "medium", + destroyModalVisible: false, +}; + +const mutations = { + TOGGLE_SIDEBAR: (state) => { + if (state.sidebar.hide) { + return false; + } + state.sidebar.opened = !state.sidebar.opened; + state.sidebar.withoutAnimation = false; + if (state.sidebar.opened) { + Cookies.set("sidebarStatus", 1); + } else { + Cookies.set("sidebarStatus", 0); + } + }, + CLOSE_SIDEBAR: (state, withoutAnimation) => { + Cookies.set("sidebarStatus", 0); + state.sidebar.opened = false; + state.sidebar.withoutAnimation = withoutAnimation; + }, + TOGGLE_DEVICE: (state, device) => { + state.device = device; + }, + SET_SIZE: (state, size) => { + state.size = size; + Cookies.set("size", size); + }, + SET_SIDEBAR_HIDE: (state, status) => { + state.sidebar.hide = status; + }, + SET_DESTOY_MODAL_STATE: (state, visible) => { + state.destroyModalVisible = visible; + }, +}; + +const actions = { + toggleSideBar({ commit }) { + commit("TOGGLE_SIDEBAR"); + }, + closeSideBar({ commit }, { withoutAnimation }) { + commit("CLOSE_SIDEBAR", withoutAnimation); + }, + toggleDevice({ commit }, device) { + commit("TOGGLE_DEVICE", device); + }, + setSize({ commit }, size) { + commit("SET_SIZE", size); + }, + toggleSideBarHide({ commit }, status) { + commit("SET_SIDEBAR_HIDE", status); + }, +}; + +export default { + namespaced: true, + state, + mutations, + actions, +}; diff --git a/src/store/modules/dict.js b/src/store/modules/dict.js new file mode 100644 index 0000000..f95bead --- /dev/null +++ b/src/store/modules/dict.js @@ -0,0 +1,50 @@ +const state = { + dict: new Array() +} +const mutations = { + SET_DICT: (state, { key, value }) => { + if (key !== null && key !== "") { + state.dict.push({ + key: key, + value: value + }) + } + }, + REMOVE_DICT: (state, key) => { + try { + for (let i = 0; i < state.dict.length; i++) { + if (state.dict[i].key == key) { + state.dict.splice(i, i) + return true + } + } + } catch (e) { + } + }, + CLEAN_DICT: (state) => { + state.dict = new Array() + } +} + +const actions = { + // 设置字典 + setDict({ commit }, data) { + commit('SET_DICT', data) + }, + // 删除字典 + removeDict({ commit }, key) { + commit('REMOVE_DICT', key) + }, + // 清空字典 + cleanDict({ commit }) { + commit('CLEAN_DICT') + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js new file mode 100644 index 0000000..19f159f --- /dev/null +++ b/src/store/modules/permission.js @@ -0,0 +1,144 @@ +import auth from "@/plugins/auth"; +import router, { constantRoutes, dynamicRoutes } from "@/router"; +import { getRouters } from "@/api/menu"; +import Layout from "@/layout/index"; +import ParentView from "@/components/ParentView"; +import InnerLink from "@/layout/components/InnerLink"; + +const permission = { + state: { + routes: [], + addRoutes: [], + defaultRoutes: [], + topbarRouters: [], + sidebarRouters: [], + originalRoutes: [], + }, + mutations: { + SET_ROUTES: (state, routes) => { + state.addRoutes = routes; + state.routes = constantRoutes.concat(routes); + }, + SET_DEFAULT_ROUTES: (state, routes) => { + state.defaultRoutes = constantRoutes.concat(routes); + }, + SET_TOPBAR_ROUTES: (state, routes) => { + state.topbarRouters = routes; + }, + SET_SIDEBAR_ROUTERS: (state, routes) => { + state.sidebarRouters = routes; + }, + SET_ORIGINAL_ROUTES: (state, routes) => { + state.originalRoutes = routes; + }, + }, + actions: { + // 生成路由 + async GenerateRoutes({ commit }) { + // 向后端请求路由数据 + const res = await getRouters(); + const sdata = JSON.parse(JSON.stringify(res.data)); + const rdata = JSON.parse(JSON.stringify(res.data)); + const sidebarRoutes = filterAsyncRouter(sdata); + const rewriteRoutes = filterAsyncRouter(rdata, false, true); + const asyncRoutes = filterDynamicRoutes(dynamicRoutes); + rewriteRoutes.push({ path: "*", redirect: "/404", hidden: true }); + router.addRoutes(asyncRoutes); + commit("SET_ORIGINAL_ROUTES", res); + commit("SET_ROUTES", rewriteRoutes); + commit("SET_SIDEBAR_ROUTERS", constantRoutes.concat(sidebarRoutes)); + commit("SET_DEFAULT_ROUTES", sidebarRoutes); + commit("SET_TOPBAR_ROUTES", sidebarRoutes); + + rewriteRoutes.push({ + path: "", + component: Layout, + redirect: + "/SimulationAndEvaluation/StructuralPatternSimulation/SceneSimulation", + }); + + return rewriteRoutes; + }, + }, +}; + +// 遍历后台传来的路由字符串,转换为组件对象 +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); + route.redirect = `./${route.children[0].path}`; + } else { + delete route["children"]; + delete route["redirect"]; + } + return true; + }); +} + +function filterChildren(childrenMap, lastRouter = false) { + var children = []; + childrenMap.forEach((el, index) => { + if (el.children && el.children.length) { + if (el.component === "ParentView" && !lastRouter) { + el.children.forEach((c) => { + c.path = el.path + "/" + c.path; + if (c.children && c.children.length) { + children = children.concat(filterChildren(c.children, c)); + return; + } + children.push(c); + }); + return; + } + } + if (lastRouter) { + el.path = lastRouter.path + "/" + el.path; + } + children = children.concat(el); + }); + return children; +} + +// 动态路由遍历,验证是否具备权限 +export function filterDynamicRoutes(routes) { + const res = []; + routes.forEach((route) => { + if (route.permissions) { + if (auth.hasPermiOr(route.permissions)) { + res.push(route); + } + } else if (route.roles) { + if (auth.hasRoleOr(route.roles)) { + res.push(route); + } + } + }); + return res; +} + +export const loadView = (view) => { + if (process.env.NODE_ENV === "development") { + return (resolve) => require([`@/views/${view}`], resolve); + } else { + // 使用 import 实现生产环境的路由懒加载 + return () => import(`@/views/${view}`); + } +}; + +export default permission; diff --git a/src/store/modules/productTree.js b/src/store/modules/productTree.js new file mode 100644 index 0000000..6376757 --- /dev/null +++ b/src/store/modules/productTree.js @@ -0,0 +1,97 @@ +import Vue from "vue"; +import { + getNodeById, + getNodeByIdAndType, + getParentNodeByIdFake, +} from "@/utils/productTreeHelper"; +import { getAction } from "@/api/common"; + +const state = { + treeData: [], +}; + +const mutations = { + // 设置树数据 + SET_TREE_DATA(state, treeData) { + state.treeData = treeData; + }, + + // 根据父节点id增加子节点 + ADD_NODE(state, { parentIdFake, idFake, id, type, name, senStressArray }) { + const parentNode = getNodeById(state.treeData, parentIdFake); + if (!parentNode) { + console.error("未找到目标节点"); + return; + } + + if (!parentNode.children) { + Vue.set(parentNode, "children", []); + } + + parentNode.children.push({ + id, + idFake, + type, + name, + senStressArray, + children: [], + }); + }, + + // 根据id更新数据 + UPDATE_NODE(state, { id, type, name, senStressArray }) { + const targetNode = getNodeByIdAndType(state.treeData, id, type); + if (!targetNode) { + console.error("未找到目标节点"); + return; + } + + targetNode.name = name; + targetNode.senStressArray = senStressArray; + }, + + // 根据id移除节点 + REMOVE_NODE(state, { id, type }) { + const find = getNodeByIdAndType(state.treeData, id, type); + if (!find) { + console.log("未找到要移除的节点"); + return; + } + + const findParent = getParentNodeByIdFake(state.treeData, find.idFake); + if (!findParent) { + console.log("未找到要移除的节点的父节点"); + return; + } + + const { parentNode, index } = findParent; + if (parentNode) { + parentNode.children.splice(index, 1); + } + }, +}; + +const actions = { + // 获取树列表 + async getData({ commit }) { + try { + const { code, data, msg } = await getAction( + "/project/datama/treeMaterialAccele" + ); + if (code == 200) { + commit("SET_TREE_DATA", data); + } else { + this.$message.error(msg); + } + } catch (error) { + console.log(error); + } + }, +}; + +export default { + namespaced: true, + state, + mutations, + actions, +}; diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js new file mode 100644 index 0000000..3f60e9a --- /dev/null +++ b/src/store/modules/settings.js @@ -0,0 +1,42 @@ +import defaultSettings from '@/settings' + +const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' +const state = { + title: '', + theme: storageSetting.theme || '#409EFF', + 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, +} +const mutations = { + CHANGE_SETTING: (state, { key, value }) => { + if (state.hasOwnProperty(key)) { + state[key] = value + } + }, +} + +const actions = { + // 修改布局设置 + changeSetting({ commit }, data) { + commit('CHANGE_SETTING', data) + }, + // 设置网页标题 + setTitle({ commit }, title) { + state.title = title + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..f2c649f --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,228 @@ +const state = { + visitedViews: [], + cachedViews: ['CreateAssessment'], + iframeViews: [] +} + +const mutations = { + ADD_IFRAME_VIEW: (state, view) => { + if (state.iframeViews.some(v => v.path === view.path)) return + state.iframeViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (view.meta && !view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_IFRAME_VIEW: (state, view) => { + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_CACHED_VIEW: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + index > -1 && state.cachedViews.splice(index, 1) + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + state.iframeViews = state.iframeViews.filter(item => item.path === view.path) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + if (index > -1) { + state.cachedViews = state.cachedViews.slice(index, index + 1) + } else { + state.cachedViews = [] + } + }, + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + state.iframeViews = [] + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + DEL_RIGHT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx <= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + }, + DEL_LEFT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx >= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addIframeView({ commit }, view) { + commit('ADD_IFRAME_VIEW', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delIframeView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_IFRAME_VIEW', view) + resolve([...state.iframeViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + }, + delRightTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_RIGHT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delLeftTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_LEFT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/store/modules/user.js b/src/store/modules/user.js new file mode 100644 index 0000000..d67c9a4 --- /dev/null +++ b/src/store/modules/user.js @@ -0,0 +1,96 @@ +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/utils/auth' + +const user = { + state: { + token: getToken(), + name: '', + avatar: '', + roles: [], + permissions: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + } + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + setToken(res.data.token) + commit('SET_TOKEN', res.data.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.data.user + const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : user.avatar; + if (res.data.roles && res.data.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + commit('SET_ROLES', res.data.roles) + commit('SET_PERMISSIONS', res.data.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', user.userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 前端 登出 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/src/utils/auth.js b/src/utils/auth.js new file mode 100644 index 0000000..08a43d6 --- /dev/null +++ b/src/utils/auth.js @@ -0,0 +1,15 @@ +import Cookies from 'js-cookie' + +const TokenKey = 'Admin-Token' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} diff --git a/src/utils/chart-helper.js b/src/utils/chart-helper.js new file mode 100644 index 0000000..eecf811 --- /dev/null +++ b/src/utils/chart-helper.js @@ -0,0 +1,8 @@ +export const downloadChart = (url, filename) => { + const link = document.createElement("a"); // 创建一个a标签 + link.href = url; // 设置a标签的href属性为给定的url + link.download = filename; // 把a标签的download属性设置为filename + link.target = "_blank"; // 在新的浏览器窗口或标签页中打开链接 + link.click(); // 模拟点击a标签,触发浏览器的下载功能 + link.remove(); // 从DOM中删除a标签 +}; diff --git a/src/utils/datetime.js b/src/utils/datetime.js new file mode 100644 index 0000000..e3904ea --- /dev/null +++ b/src/utils/datetime.js @@ -0,0 +1,10 @@ +import dayjs from "dayjs"; + +/** + * 获取年月日 + * @param {string | Date | Number} dateTime + * @returns + */ +export const getDate = (dateTime, format = "YYYY-MM-DD") => { + return dayjs(dateTime).format(format); +}; diff --git a/src/utils/dict/DefaultOption.js b/src/utils/dict/DefaultOption.js new file mode 100644 index 0000000..3cb7a53 --- /dev/null +++ b/src/utils/dict/DefaultOption.js @@ -0,0 +1,53 @@ +/** + * @typedef Option + * @property {string} label + * @property {string|number} value + */ + +// 类型示例 +// export const STRESS_TYPE = [ +// { label: "标题1", value: 0 }, +// { label: "标题2", value: 1 }, +// ]; + +/** + * 根据值在下拉列表配置中找到label + * @param {string|number} value + * @param {Option[]} list + * @returns + */ +export const getLabelByValue = (value, list) => { + if (value === null || value === undefined || value === "") { + return "—"; + } + const find = list.find((option) => option.value == value); + return find ? find.label : "—"; +}; + +// 起爆模式 +export const BOOM_TYPE = [ + { + label: "中心起爆", + value: 0, + }, + { + label: "一端起爆", + value: 1, + }, + { + label: "双端起爆", + value: 2, + }, +]; + +// 弹目交会 模型类型 +export const MISSILE_TARGET_RENDEZVOUS_MODEL_TYPE = [ + { + label: "系统内置模型", + value: 0, + }, + { + label: "ANSYS模型", + value: 1, + }, +]; diff --git a/src/utils/dict/Dict.js b/src/utils/dict/Dict.js new file mode 100644 index 0000000..104bd6e --- /dev/null +++ b/src/utils/dict/Dict.js @@ -0,0 +1,82 @@ +import Vue from 'vue' +import { mergeRecursive } from "@/utils/ruoyi"; +import DictMeta from './DictMeta' +import DictData from './DictData' + +const DEFAULT_DICT_OPTIONS = { + types: [], +} + +/** + * @classdesc 字典 + * @property {Object} label 标签对象,内部属性名为字典类型名称 + * @property {Object} dict 字段数组,内部属性名为字典类型名称 + * @property {Array.} _dictMetas 字典元数据数组 + */ +export default class Dict { + constructor() { + this.owner = null + this.label = {} + this.type = {} + } + + init(options) { + if (options instanceof Array) { + options = { types: options } + } + const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options) + if (opts.types === undefined) { + throw new Error('need dict types') + } + const ps = [] + this._dictMetas = opts.types.map(t => DictMeta.parse(t)) + this._dictMetas.forEach(dictMeta => { + const type = dictMeta.type + Vue.set(this.label, type, {}) + Vue.set(this.type, type, []) + if (dictMeta.lazy) { + return + } + ps.push(loadDict(this, dictMeta)) + }) + return Promise.all(ps) + } + + /** + * 重新加载字典 + * @param {String} type 字典类型 + */ + reloadDict(type) { + const dictMeta = this._dictMetas.find(e => e.type === type) + if (dictMeta === undefined) { + return Promise.reject(`the dict meta of ${type} was not found`) + } + return loadDict(this, dictMeta) + } +} + +/** + * 加载字典 + * @param {Dict} dict 字典 + * @param {DictMeta} dictMeta 字典元数据 + * @returns {Promise} + */ +function loadDict(dict, dictMeta) { + return dictMeta.request(dictMeta) + .then(response => { + const type = dictMeta.type + let dicts = dictMeta.responseConverter(response, dictMeta) + if (!(dicts instanceof Array)) { + console.error('the return of responseConverter must be Array.') + dicts = [] + } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) { + console.error('the type of elements in dicts must be DictData') + dicts = [] + } + dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts) + dicts.forEach(d => { + Vue.set(dict.label[type], d.value, d.label) + }) + return dicts + }) +} diff --git a/src/utils/dict/DictConverter.js b/src/utils/dict/DictConverter.js new file mode 100644 index 0000000..0cf5df8 --- /dev/null +++ b/src/utils/dict/DictConverter.js @@ -0,0 +1,17 @@ +import DictOptions from './DictOptions' +import DictData from './DictData' + +export default function(dict, dictMeta) { + const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS) + const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS) + return new DictData(dict[label], dict[value], dict) +} + +/** + * 确定字典字段 + * @param {DictData} dict + * @param {...String} fields + */ +function determineDictField(dict, ...fields) { + return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) +} diff --git a/src/utils/dict/DictData.js b/src/utils/dict/DictData.js new file mode 100644 index 0000000..afc763e --- /dev/null +++ b/src/utils/dict/DictData.js @@ -0,0 +1,13 @@ +/** + * @classdesc 字典数据 + * @property {String} label 标签 + * @property {*} value 标签 + * @property {Object} raw 原始数据 + */ +export default class DictData { + constructor(label, value, raw) { + this.label = label + this.value = value + this.raw = raw + } +} diff --git a/src/utils/dict/DictMeta.js b/src/utils/dict/DictMeta.js new file mode 100644 index 0000000..9779daa --- /dev/null +++ b/src/utils/dict/DictMeta.js @@ -0,0 +1,38 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import DictOptions from './DictOptions' + +/** + * @classdesc 字典元数据 + * @property {String} type 类型 + * @property {Function} request 请求 + * @property {String} label 标签字段 + * @property {String} value 值字段 + */ +export default class DictMeta { + constructor(options) { + this.type = options.type + this.request = options.request + this.responseConverter = options.responseConverter + this.labelField = options.labelField + this.valueField = options.valueField + this.lazy = options.lazy === true + } +} + + +/** + * 解析字典元数据 + * @param {Object} options + * @returns {DictMeta} + */ +DictMeta.parse= function(options) { + let opts = null + if (typeof options === 'string') { + opts = DictOptions.metas[options] || {} + opts.type = options + } else if (typeof options === 'object') { + opts = options + } + opts = mergeRecursive(DictOptions.metas['*'], opts) + return new DictMeta(opts) +} diff --git a/src/utils/dict/DictOptions.js b/src/utils/dict/DictOptions.js new file mode 100644 index 0000000..338a94e --- /dev/null +++ b/src/utils/dict/DictOptions.js @@ -0,0 +1,51 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import dictConverter from './DictConverter' + +export const options = { + metas: { + '*': { + /** + * 字典请求,方法签名为function(dictMeta: DictMeta): Promise + */ + request: (dictMeta) => { + console.log(`load dict ${dictMeta.type}`) + return Promise.resolve([]) + }, + /** + * 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData + */ + responseConverter, + labelField: 'label', + valueField: 'value', + }, + }, + /** + * 默认标签字段 + */ + DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'], + /** + * 默认值字段 + */ + DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'], +} + +/** + * 映射字典 + * @param {Object} response 字典数据 + * @param {DictMeta} dictMeta 字典元数据 + * @returns {DictData} + */ +function responseConverter(response, dictMeta) { + const dicts = response.content instanceof Array ? response.content : response + if (dicts === undefined) { + console.warn(`no dict data of "${dictMeta.type}" found in the response`) + return [] + } + return dicts.map(d => dictConverter(d, dictMeta)) +} + +export function mergeOptions(src) { + mergeRecursive(options, src) +} + +export default options diff --git a/src/utils/dict/index.js b/src/utils/dict/index.js new file mode 100644 index 0000000..215eb9e --- /dev/null +++ b/src/utils/dict/index.js @@ -0,0 +1,33 @@ +import Dict from './Dict' +import { mergeOptions } from './DictOptions' + +export default function(Vue, options) { + mergeOptions(options) + Vue.mixin({ + data() { + if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) { + return {} + } + const dict = new Dict() + dict.owner = this + return { + dict + } + }, + created() { + if (!(this.dict instanceof Dict)) { + return + } + options.onCreated && options.onCreated(this.dict) + this.dict.init(this.$options.dicts).then(() => { + options.onReady && options.onReady(this.dict) + this.$nextTick(() => { + this.$emit('dictReady', this.dict) + if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { + this.$options.methods.onDictReady.call(this, this.dict) + } + }) + }) + }, + }) +} 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/generator/config.js b/src/utils/generator/config.js new file mode 100644 index 0000000..7abf227 --- /dev/null +++ b/src/utils/generator/config.js @@ -0,0 +1,438 @@ +export const formConf = { + formRef: 'elForm', + formModel: 'formData', + size: 'medium', + labelPosition: 'right', + labelWidth: 100, + formRules: 'rules', + gutter: 15, + disabled: false, + span: 24, + formBtns: true +} + +export const inputComponents = [ + { + label: '单行文本', + tag: 'el-input', + tagIcon: 'input', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '多行文本', + tag: 'el-input', + tagIcon: 'textarea', + type: 'textarea', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + labelWidth: null, + autosize: { + minRows: 4, + maxRows: 4 + }, + style: { width: '100%' }, + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '密码', + tag: 'el-input', + tagIcon: 'password', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + 'show-password': true, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '计数器', + tag: 'el-input-number', + tagIcon: 'number', + placeholder: '', + defaultValue: undefined, + span: 24, + labelWidth: null, + min: undefined, + max: undefined, + step: undefined, + 'step-strictly': false, + precision: undefined, + 'controls-position': '', + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input-number' + } +] + +export const selectComponents = [ + { + label: '下拉选择', + tag: 'el-select', + tagIcon: 'select', + placeholder: '请选择', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + disabled: false, + required: true, + filterable: false, + multiple: false, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/select' + }, + { + label: '级联选择', + tag: 'el-cascader', + tagIcon: 'cascader', + placeholder: '请选择', + defaultValue: [], + span: 24, + labelWidth: null, + style: { width: '100%' }, + props: { + props: { + multiple: false + } + }, + 'show-all-levels': true, + disabled: false, + clearable: true, + filterable: false, + required: true, + options: [{ + id: 1, + value: 1, + label: '选项1', + children: [{ + id: 2, + value: 2, + label: '选项1-1' + }] + }], + dataType: 'dynamic', + labelKey: 'label', + valueKey: 'value', + childrenKey: 'children', + separator: '/', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/cascader' + }, + { + label: '单选框组', + tag: 'el-radio-group', + tagIcon: 'radio', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/radio' + }, + { + label: '多选框组', + tag: 'el-checkbox-group', + tagIcon: 'checkbox', + defaultValue: [], + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/checkbox' + }, + { + label: '开关', + tag: 'el-switch', + tagIcon: 'switch', + defaultValue: false, + span: 24, + labelWidth: null, + style: {}, + disabled: false, + required: true, + 'active-text': '', + 'inactive-text': '', + 'active-color': null, + 'inactive-color': null, + 'active-value': true, + 'inactive-value': false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/switch' + }, + { + label: '滑块', + tag: 'el-slider', + tagIcon: 'slider', + defaultValue: null, + span: 24, + labelWidth: null, + disabled: false, + required: true, + min: 0, + max: 100, + step: 1, + 'show-stops': false, + range: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/slider' + }, + { + label: '时间选择', + tag: 'el-time-picker', + tagIcon: 'time', + placeholder: '请选择', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'picker-options': { + selectableRange: '00:00:00-23:59:59' + }, + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '时间范围', + tag: 'el-time-picker', + tagIcon: 'time-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'is-range': true, + 'range-separator': '至', + 'start-placeholder': '开始时间', + 'end-placeholder': '结束时间', + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '日期选择', + tag: 'el-date-picker', + tagIcon: 'date', + placeholder: '请选择', + defaultValue: null, + type: 'date', + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '日期范围', + tag: 'el-date-picker', + tagIcon: 'date-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + type: 'daterange', + 'range-separator': '至', + 'start-placeholder': '开始日期', + 'end-placeholder': '结束日期', + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '评分', + tag: 'el-rate', + tagIcon: 'rate', + defaultValue: 0, + span: 24, + labelWidth: null, + style: {}, + max: 5, + 'allow-half': false, + 'show-text': false, + 'show-score': false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/rate' + }, + { + label: '颜色选择', + tag: 'el-color-picker', + tagIcon: 'color', + defaultValue: null, + labelWidth: null, + 'show-alpha': false, + 'color-format': '', + disabled: false, + required: true, + size: 'medium', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/color-picker' + }, + { + label: '上传', + tag: 'el-upload', + tagIcon: 'upload', + action: 'https://jsonplaceholder.typicode.com/posts/', + defaultValue: null, + labelWidth: null, + disabled: false, + required: true, + accept: '', + name: 'file', + 'auto-upload': true, + showTip: false, + buttonText: '点击上传', + fileSize: 2, + sizeUnit: 'MB', + 'list-type': 'text', + multiple: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/upload' + } +] + +export const layoutComponents = [ + { + layout: 'rowFormItem', + tagIcon: 'row', + type: 'default', + justify: 'start', + align: 'top', + label: '行容器', + layoutTree: true, + children: [], + document: 'https://element.eleme.cn/#/zh-CN/component/layout' + }, + { + layout: 'colFormItem', + label: '按钮', + changeTag: true, + labelWidth: null, + tag: 'el-button', + tagIcon: 'button', + span: 24, + default: '主要按钮', + type: 'primary', + icon: 'el-icon-search', + size: 'medium', + disabled: false, + document: 'https://element.eleme.cn/#/zh-CN/component/button' + } +] + +// 组件rule的触发方式,无触发方式的组件不生成rule +export const trigger = { + 'el-input': 'blur', + 'el-input-number': 'blur', + 'el-select': 'change', + 'el-radio-group': 'change', + 'el-checkbox-group': 'change', + 'el-cascader': 'change', + 'el-time-picker': 'change', + 'el-date-picker': 'change', + 'el-rate': 'change' +} diff --git a/src/utils/generator/css.js b/src/utils/generator/css.js new file mode 100644 index 0000000..c1c62e6 --- /dev/null +++ b/src/utils/generator/css.js @@ -0,0 +1,18 @@ +const styles = { + 'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}', + 'el-upload': '.el-upload__tip{line-height: 1.2;}' +} + +function addCss(cssList, el) { + const css = styles[el.tag] + css && cssList.indexOf(css) === -1 && cssList.push(css) + if (el.children) { + el.children.forEach(el2 => addCss(cssList, el2)) + } +} + +export function makeUpCss(conf) { + const cssList = [] + conf.fields.forEach(el => addCss(cssList, el)) + return cssList.join('\n') +} diff --git a/src/utils/generator/drawingDefault.js b/src/utils/generator/drawingDefault.js new file mode 100644 index 0000000..09f133c --- /dev/null +++ b/src/utils/generator/drawingDefault.js @@ -0,0 +1,29 @@ +export default [ + { + layout: 'colFormItem', + tagIcon: 'input', + label: '手机号', + vModel: 'mobile', + formId: 6, + tag: 'el-input', + placeholder: '请输入手机号', + defaultValue: '', + span: 24, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': 'el-icon-mobile', + 'suffix-icon': '', + maxlength: 11, + 'show-word-limit': true, + readonly: false, + disabled: false, + required: true, + changeTag: true, + regList: [{ + pattern: '/^1(3|4|5|7|8|9)\\d{9}$/', + message: '手机号格式错误' + }] + } +] diff --git a/src/utils/generator/html.js b/src/utils/generator/html.js new file mode 100644 index 0000000..9bcc536 --- /dev/null +++ b/src/utils/generator/html.js @@ -0,0 +1,359 @@ +/* eslint-disable max-len */ +import { trigger } from './config' + +let confGlobal +let someSpanIsNot24 + +export function dialogWrapper(str) { + return ` + ${str} +
+ 取消 + 确定 +
+
` +} + +export function vueTemplate(str) { + return `` +} + +export function vueScript(str) { + return `` +} + +export function cssStyle(cssStr) { + return `` +} + +function buildFormTemplate(conf, child, type) { + let labelPosition = '' + if (conf.labelPosition !== 'right') { + labelPosition = `label-position="${conf.labelPosition}"` + } + const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' + let str = ` + ${child} + ${buildFromBtns(conf, type)} + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + return str +} + +function buildFromBtns(conf, type) { + let str = '' + if (conf.formBtns && type === 'file') { + str = ` + 提交 + 重置 + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + } + return str +} + +// span不为24的用el-col包裹 +function colWrapper(element, str) { + if (someSpanIsNot24 || element.span !== 24) { + return ` + ${str} + ` + } + return str +} + +const layouts = { + colFormItem(element) { + let labelWidth = '' + if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) { + labelWidth = `label-width="${element.labelWidth}px"` + } + const required = !trigger[element.tag] && element.required ? 'required' : '' + const tagDom = tags[element.tag] ? tags[element.tag](element) : null + let str = ` + ${tagDom} + ` + str = colWrapper(element, str) + return str + }, + rowFormItem(element) { + const type = element.type === 'default' ? '' : `type="${element.type}"` + const justify = element.type === 'default' ? '' : `justify="${element.justify}"` + const align = element.type === 'default' ? '' : `align="${element.align}"` + const gutter = element.gutter ? `gutter="${element.gutter}"` : '' + const children = element.children.map(el => layouts[el.layout](el)) + let str = ` + ${children.join('\n')} + ` + str = colWrapper(element, str) + return str + } +} + +const tags = { + 'el-button': el => { + const { + tag, disabled + } = attrBuilder(el) + const type = el.type ? `type="${el.type}"` : '' + const icon = el.icon ? `icon="${el.icon}"` : '' + const size = el.size ? `size="${el.size}"` : '' + let child = buildElButtonChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}` + }, + 'el-input': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' + const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' + const readonly = el.readonly ? 'readonly' : '' + const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : '' + const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' + const showPassword = el['show-password'] ? 'show-password' : '' + const type = el.type ? `type="${el.type}"` : '' + const autosize = el.autosize && el.autosize.minRows + ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` + : '' + let child = buildElInputChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}` + }, + 'el-input-number': el => { + const { disabled, vModel, placeholder } = attrBuilder(el) + const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' + const precision = el.precision ? `:precision='${el.precision}'` : '' + + return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}>` + }, + 'el-select': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const filterable = el.filterable ? 'filterable' : '' + const multiple = el.multiple ? 'multiple' : '' + let child = buildElSelectChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}` + }, + 'el-radio-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + let child = buildElRadioGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${size} ${disabled}>${child}` + }, + 'el-checkbox-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const min = el.min ? `:min="${el.min}"` : '' + const max = el.max ? `:max="${el.max}"` : '' + let child = buildElCheckboxGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}` + }, + 'el-switch': el => { + const { disabled, vModel } = attrBuilder(el) + const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : '' + const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' + const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' + const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' + const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' + const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' + + return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}>` + }, + 'el-cascader': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const options = el.options ? `:options="${el.vModel}Options"` : '' + const props = el.props ? `:props="${el.vModel}Props"` : '' + const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' + const filterable = el.filterable ? 'filterable' : '' + const separator = el.separator === '/' ? '' : `separator="${el.separator}"` + + return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}>` + }, + 'el-slider': el => { + const { disabled, vModel } = attrBuilder(el) + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const range = el.range ? 'range' : '' + const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : '' + + return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}>` + }, + 'el-time-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const isRange = el['is-range'] ? 'is-range' : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' + + return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}>` + }, + 'el-date-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const type = el.type === 'date' ? '' : `type="${el.type}"` + const readonly = el.readonly ? 'readonly' : '' + + return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}>` + }, + 'el-rate': el => { + const { disabled, vModel } = attrBuilder(el) + const max = el.max ? `:max='${el.max}'` : '' + const allowHalf = el['allow-half'] ? 'allow-half' : '' + const showText = el['show-text'] ? 'show-text' : '' + const showScore = el['show-score'] ? 'show-score' : '' + + return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}>` + }, + 'el-color-picker': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const showAlpha = el['show-alpha'] ? 'show-alpha' : '' + const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : '' + + return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}>` + }, + 'el-upload': el => { + const disabled = el.disabled ? ':disabled=\'true\'' : '' + const action = el.action ? `:action="${el.vModel}Action"` : '' + const multiple = el.multiple ? 'multiple' : '' + const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' + const accept = el.accept ? `accept="${el.accept}"` : '' + const name = el.name !== 'file' ? `name="${el.name}"` : '' + const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : '' + const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"` + const fileList = `:file-list="${el.vModel}fileList"` + const ref = `ref="${el.vModel}"` + let child = buildElUploadChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}` + } +} + +function attrBuilder(el) { + return { + vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`, + clearable: el.clearable ? 'clearable' : '', + placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', + width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', + disabled: el.disabled ? ':disabled=\'true\'' : '' + } +} + +// el-buttin 子级 +function buildElButtonChild(conf) { + const children = [] + if (conf.default) { + children.push(conf.default) + } + return children.join('\n') +} + +// el-input innerHTML +function buildElInputChild(conf) { + const children = [] + if (conf.prepend) { + children.push(``) + } + if (conf.append) { + children.push(``) + } + return children.join('\n') +} + +function buildElSelectChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + children.push(``) + } + return children.join('\n') +} + +function buildElRadioGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}`) + } + return children.join('\n') +} + +function buildElCheckboxGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}`) + } + return children.join('\n') +} + +function buildElUploadChild(conf) { + const list = [] + if (conf['list-type'] === 'picture-card') list.push('') + else list.push(`${conf.buttonText}`) + if (conf.showTip) list.push(`
只能上传不超过 ${conf.fileSize}${conf.sizeUnit} 的${conf.accept}文件
`) + return list.join('\n') +} + +export function makeUpHtml(conf, type) { + const htmlList = [] + confGlobal = conf + someSpanIsNot24 = conf.fields.some(item => item.span !== 24) + conf.fields.forEach(el => { + htmlList.push(layouts[el.layout](el)) + }) + const htmlStr = htmlList.join('\n') + + let temp = buildFormTemplate(conf, htmlStr, type) + if (type === 'dialog') { + temp = dialogWrapper(temp) + } + confGlobal = null + return temp +} diff --git a/src/utils/generator/icon.json b/src/utils/generator/icon.json new file mode 100644 index 0000000..2d9999a --- /dev/null +++ b/src/utils/generator/icon.json @@ -0,0 +1 @@ +["platform-eleme","eleme","delete-solid","delete","s-tools","setting","user-solid","user","phone","phone-outline","more","more-outline","star-on","star-off","s-goods","goods","warning","warning-outline","question","info","remove","circle-plus","success","error","zoom-in","zoom-out","remove-outline","circle-plus-outline","circle-check","circle-close","s-help","help","minus","plus","check","close","picture","picture-outline","picture-outline-round","upload","upload2","download","camera-solid","camera","video-camera-solid","video-camera","message-solid","bell","s-cooperation","s-order","s-platform","s-fold","s-unfold","s-operation","s-promotion","s-home","s-release","s-ticket","s-management","s-open","s-shop","s-marketing","s-flag","s-comment","s-finance","s-claim","s-custom","s-opportunity","s-data","s-check","s-grid","menu","share","d-caret","caret-left","caret-right","caret-bottom","caret-top","bottom-left","bottom-right","back","right","bottom","top","top-left","top-right","arrow-left","arrow-right","arrow-down","arrow-up","d-arrow-left","d-arrow-right","video-pause","video-play","refresh","refresh-right","refresh-left","finished","sort","sort-up","sort-down","rank","loading","view","c-scale-to-original","date","edit","edit-outline","folder","folder-opened","folder-add","folder-remove","folder-delete","folder-checked","tickets","document-remove","document-delete","document-copy","document-checked","document","document-add","printer","paperclip","takeaway-box","search","monitor","attract","mobile","scissors","umbrella","headset","brush","mouse","coordinate","magic-stick","reading","data-line","data-board","pie-chart","data-analysis","collection-tag","film","suitcase","suitcase-1","receiving","collection","files","notebook-1","notebook-2","toilet-paper","office-building","school","table-lamp","house","no-smoking","smoking","shopping-cart-full","shopping-cart-1","shopping-cart-2","shopping-bag-1","shopping-bag-2","sold-out","sell","present","box","bank-card","money","coin","wallet","discount","price-tag","news","guide","male","female","thumb","cpu","link","connection","open","turn-off","set-up","chat-round","chat-line-round","chat-square","chat-dot-round","chat-dot-square","chat-line-square","message","postcard","position","turn-off-microphone","microphone","close-notification","bangzhu","time","odometer","crop","aim","switch-button","full-screen","copy-document","mic","stopwatch","medal-1","medal","trophy","trophy-1","first-aid-kit","discover","place","location","location-outline","location-information","add-location","delete-location","map-location","alarm-clock","timer","watch-1","watch","lock","unlock","key","service","mobile-phone","bicycle","truck","ship","basketball","football","soccer","baseball","wind-power","light-rain","lightning","heavy-rain","sunrise","sunrise-1","sunset","sunny","cloudy","partly-cloudy","cloudy-and-sunny","moon","moon-night","dish","dish-1","food","chicken","fork-spoon","knife-fork","burger","tableware","sugar","dessert","ice-cream","hot-water","water-cup","coffee-cup","cold-drink","goblet","goblet-full","goblet-square","goblet-square-full","refrigerator","grape","watermelon","cherry","apple","pear","orange","coffee","ice-tea","ice-drink","milk-tea","potato-strips","lollipop","ice-cream-square","ice-cream-round"] \ No newline at end of file diff --git a/src/utils/generator/js.js b/src/utils/generator/js.js new file mode 100644 index 0000000..35e3e21 --- /dev/null +++ b/src/utils/generator/js.js @@ -0,0 +1,236 @@ +import { isArray } from 'util' +import { exportDefault, titleCase } from '@/utils/index' +import { trigger } from './config' + +const units = { + KB: '1024', + MB: '1024 / 1024', + GB: '1024 / 1024 / 1024' +} +let confGlobal +const inheritAttrs = { + file: '', + dialog: 'inheritAttrs: false,' +} + + +export function makeUpJs(conf, type) { + confGlobal = conf = JSON.parse(JSON.stringify(conf)) + const dataList = [] + const ruleList = [] + const optionsList = [] + const propsList = [] + const methodList = mixinMethod(type) + const uploadVarList = [] + + conf.fields.forEach(el => { + buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + + const script = buildexport( + conf, + type, + dataList.join('\n'), + ruleList.join('\n'), + optionsList.join('\n'), + uploadVarList.join('\n'), + propsList.join('\n'), + methodList.join('\n') + ) + confGlobal = null + return script +} + +function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) { + buildData(el, dataList) + buildRules(el, ruleList) + + if (el.options && el.options.length) { + buildOptions(el, optionsList) + if (el.dataType === 'dynamic') { + const model = `${el.vModel}Options` + const options = titleCase(model) + buildOptionMethod(`get${options}`, model, methodList) + } + } + + if (el.props && el.props.props) { + buildProps(el, propsList) + } + + if (el.action && el.tag === 'el-upload') { + uploadVarList.push( + `${el.vModel}Action: '${el.action}', + ${el.vModel}fileList: [],` + ) + methodList.push(buildBeforeUpload(el)) + if (!el['auto-upload']) { + methodList.push(buildSubmitUpload(el)) + } + } + + if (el.children) { + el.children.forEach(el2 => { + buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + } +} + +function mixinMethod(type) { + const list = []; const + minxins = { + file: confGlobal.formBtns ? { + submitForm: `submitForm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + // TODO 提交表单 + }) + },`, + resetForm: `resetForm() { + this.$refs['${confGlobal.formRef}'].resetFields() + },` + } : null, + dialog: { + onOpen: 'onOpen() {},', + onClose: `onClose() { + this.$refs['${confGlobal.formRef}'].resetFields() + },`, + close: `close() { + this.$emit('update:visible', false) + },`, + handleConfirm: `handleConfirm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + this.close() + }) + },` + } + } + + const methods = minxins[type] + if (methods) { + Object.keys(methods).forEach(key => { + list.push(methods[key]) + }) + } + + return list +} + +function buildData(conf, dataList) { + if (conf.vModel === undefined) return + let defaultValue + if (typeof (conf.defaultValue) === 'string' && !conf.multiple) { + defaultValue = `'${conf.defaultValue}'` + } else { + defaultValue = `${JSON.stringify(conf.defaultValue)}` + } + dataList.push(`${conf.vModel}: ${defaultValue},`) +} + +function buildRules(conf, ruleList) { + if (conf.vModel === undefined) return + const rules = [] + if (trigger[conf.tag]) { + if (conf.required) { + const type = isArray(conf.defaultValue) ? 'type: \'array\',' : '' + let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder + if (message === undefined) message = `${conf.label}不能为空` + rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`) + } + if (conf.regList && isArray(conf.regList)) { + conf.regList.forEach(item => { + if (item.pattern) { + rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`) + } + }) + } + ruleList.push(`${conf.vModel}: [${rules.join(',')}],`) + } +} + +function buildOptions(conf, optionsList) { + if (conf.vModel === undefined) return + if (conf.dataType === 'dynamic') { conf.options = [] } + const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},` + optionsList.push(str) +} + +function buildProps(conf, propsList) { + if (conf.dataType === 'dynamic') { + conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey) + conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey) + conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey) + } + const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},` + propsList.push(str) +} + +function buildBeforeUpload(conf) { + const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const + returnList = [] + if (conf.fileSize) { + rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize} + if(!isRightSize){ + this.$message.error('文件大小超过 ${conf.fileSize}${conf.sizeUnit}') + }` + returnList.push('isRightSize') + } + if (conf.accept) { + acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type) + if(!isAccept){ + this.$message.error('应该选择${conf.accept}类型的文件') + }` + returnList.push('isAccept') + } + const str = `${conf.vModel}BeforeUpload(file) { + ${rightSizeCode} + ${acceptCode} + return ${returnList.join('&&')} + },` + return returnList.length ? str : '' +} + +function buildSubmitUpload(conf) { + const str = `submitUpload() { + this.$refs['${conf.vModel}'].submit() + },` + return str +} + +function buildOptionMethod(methodName, model, methodList) { + const str = `${methodName}() { + // TODO 发起请求获取数据 + this.${model} + },` + methodList.push(str) +} + +function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) { + const str = `${exportDefault}{ + ${inheritAttrs[type]} + components: {}, + props: [], + data () { + return { + ${conf.formModel}: { + ${data} + }, + ${conf.formRules}: { + ${rules} + }, + ${uploadVar} + ${selectOptions} + ${props} + } + }, + computed: {}, + watch: {}, + created () {}, + mounted () {}, + methods: { + ${methods} + } +}` + return str +} diff --git a/src/utils/generator/render.js b/src/utils/generator/render.js new file mode 100644 index 0000000..e8640f0 --- /dev/null +++ b/src/utils/generator/render.js @@ -0,0 +1,126 @@ +import { makeMap } from '@/utils/index' + +// 参考https://github.com/vuejs/vue/blob/v2.6.10/src/platforms/web/server/util.js +const isAttr = makeMap( + 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' + + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' + + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' + + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' + + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + + 'target,title,type,usemap,value,width,wrap' +) + +function vModel(self, dataObject, defaultValue) { + dataObject.props.value = defaultValue + + dataObject.on.input = val => { + self.$emit('input', val) + } +} + +const componentChild = { + 'el-button': { + default(h, conf, key) { + return conf[key] + }, + }, + 'el-input': { + prepend(h, conf, key) { + return + }, + append(h, conf, key) { + return + } + }, + 'el-select': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + list.push() + }) + return list + } + }, + 'el-radio-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') list.push({item.label}) + else list.push({item.label}) + }) + return list + } + }, + 'el-checkbox-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') { + list.push({item.label}) + } else { + list.push({item.label}) + } + }) + return list + } + }, + 'el-upload': { + 'list-type': (h, conf, key) => { + const list = [] + if (conf['list-type'] === 'picture-card') { + list.push() + } else { + list.push({conf.buttonText}) + } + if (conf.showTip) { + list.push(
只能上传不超过 {conf.fileSize}{conf.sizeUnit} 的{conf.accept}文件
) + } + return list + } + } +} + +export default { + render(h) { + const dataObject = { + attrs: {}, + props: {}, + on: {}, + style: {} + } + const confClone = JSON.parse(JSON.stringify(this.conf)) + const children = [] + + const childObjs = componentChild[confClone.tag] + if (childObjs) { + Object.keys(childObjs).forEach(key => { + const childFunc = childObjs[key] + if (confClone[key]) { + children.push(childFunc(h, confClone, key)) + } + }) + } + + Object.keys(confClone).forEach(key => { + const val = confClone[key] + if (key === 'vModel') { + vModel(this, dataObject, confClone.defaultValue) + } else if (dataObject[key]) { + dataObject[key] = val + } else if (!isAttr(key)) { + dataObject.props[key] = val + } else { + dataObject.attrs[key] = val + } + }) + return h(this.conf.tag, dataObject, children) + }, + props: ['conf'] +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..1c6e9f0 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,436 @@ +import { parseTime } from "./ruoyi"; + +/** + * 表格时间格式化 + */ +export function formatDate(cellValue) { + if (cellValue == null || cellValue == "") return ""; + var date = new Date(cellValue); + var year = date.getFullYear(); + var month = + date.getMonth() + 1 < 10 + ? "0" + (date.getMonth() + 1) + : date.getMonth() + 1; + var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); + var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); + var minutes = + date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(); + var seconds = + date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); + return ( + year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + ); +} + +/** + * @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 {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 {string} input value + * @returns {number} output value + */ +export function byteLength(str) { + // returns the byte length of an utf8 string + let s = str.length; + for (var i = str.length - 1; i >= 0; i--) { + const code = str.charCodeAt(i); + if (code > 0x7f && code <= 0x7ff) s++; + else if (code > 0x7ff && code <= 0xffff) s += 2; + if (code >= 0xdc00 && code <= 0xdfff) i--; + } + return s; +} + +/** + * @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 const exportDefault = "export default "; + +export const beautifierConf = { + html: { + indent_size: "2", + indent_char: " ", + max_preserve_newlines: "-1", + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: "separate", + brace_style: "end-expand", + space_before_conditional: true, + unescape_strings: false, + jslint_happy: false, + end_with_newline: true, + wrap_line_length: "110", + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true, + }, + js: { + indent_size: "2", + indent_char: " ", + max_preserve_newlines: "-1", + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: "normal", + brace_style: "end-expand", + space_before_conditional: true, + unescape_strings: false, + jslint_happy: true, + end_with_newline: true, + wrap_line_length: "110", + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true, + }, +}; + +// 首字母大小 +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); +} + +/** + * 生成id + * @returns + */ +export const generateId = () => { + return Math.random().toString(); +}; + +/** + * 解析json数据 + * @param {string} str + */ +export const parseJSON = (str) => { + try { + return JSON.parse(str); + } catch (error) { + console.log(error); + } + + return null; +}; + +/** + * 格式化数字 + * @param {any} num 要格式化的数字 + * @param {number} n 小数后的位数 + */ +export const formatNumber = (num, n) => { + const number = Number(num); + if (Number.isNaN(number)) { + console.error("不能转化为数字格式"); + return; + } + + const result = number.toFixed(n); + if (result.split().every((n) => n == 0)) { + return number == 0 ? 0 : number.toExponential(n); + } else { + return result; + } +}; diff --git a/src/utils/jsencrypt.js b/src/utils/jsencrypt.js new file mode 100644 index 0000000..78d9523 --- /dev/null +++ b/src/utils/jsencrypt.js @@ -0,0 +1,30 @@ +import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' + +// 密钥对生成 http://web.chacuo.net/netrsakeypair + +const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' + +const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + + 'UP8iWi1Qw0Y=' + +// 加密 +export 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/permission.js b/src/utils/permission.js new file mode 100644 index 0000000..bd4c066 --- /dev/null +++ b/src/utils/permission.js @@ -0,0 +1,51 @@ +import store from '@/store' + +/** + * 字符权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkPermi(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = store.getters && store.getters.permissions + const permissionDatas = value + const all_permission = "*:*:*"; + + const hasPermission = permissions.some(permission => { + return all_permission === permission || permissionDatas.includes(permission) + }) + + if (!hasPermission) { + return false + } + return true + } else { + console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) + return false + } +} + +/** + * 角色权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkRole(value) { + if (value && value instanceof Array && value.length > 0) { + const roles = store.getters && store.getters.roles + const permissionRoles = value + const super_admin = "admin"; + + const hasRole = roles.some(role => { + return super_admin === role || permissionRoles.includes(role) + }) + + if (!hasRole) { + return false + } + return true + } else { + console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } +} diff --git a/src/utils/productTreeHelper.js b/src/utils/productTreeHelper.js new file mode 100644 index 0000000..6c33489 --- /dev/null +++ b/src/utils/productTreeHelper.js @@ -0,0 +1,71 @@ +/** + * @typedef NodeItem + * @property {string} id + * @property {string} idFake + * @property {string} name + * @property {string} type + * @property {NodeItem[]} children + */ + +/** + * 拍平 + * @param {Array} list + * @return {Array} + */ +const flat = (list) => { + const nodeList = []; + list.forEach((item) => { + const children = item.children; + nodeList.push(item); + if (children && children.length) { + nodeList.push(...flat(children)); + } + }); + return nodeList; +}; + +/** + * 根据idFake找到节点数据 + * @param {Array} list + * @param {String} idFake + */ +export const getNodeById = (list, idFake) => { + const flatList = flat(list); + return flatList.find((item) => item.idFake == idFake); +}; + +/** + * 根据id和leve找到节点数据 + * @param {Array} list + * @param {String} id + * @param {String} type + */ +export const getNodeByIdAndType = (list, id, type) => { + const flatList = flat(list); + return flatList.find((item) => item.id == id && item.type == type); +}; + +/** + * 根据id找到父节点数据 + * @param {Array} list + * @param {String|Number} idFake + */ +export const getParentNodeByIdFake = (list, idFake, parentNode) => { + for (let i = 0; i < list.length; i++) { + const item = list[i]; + // 如果找到了,返回父节点和子节点在父节点的位置 + if (item.idFake == idFake) { + return { + parentNode, + index: i, + }; + } + if (item.children) { + const find = getParentNodeByIdFake(item.children, idFake, item); + if (find) { + return find; + } + } + } + return null; +}; diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..0c4361d --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,225 @@ +import axios from "axios"; +import { Notification, MessageBox, Message, Loading } from "element-ui"; +import store from "@/store"; +import { getToken } from "@/utils/auth"; +import errorCode from "@/utils/errorCode"; +import { tansParams, blobValidate } from "@/utils/ruoyi"; +import cache from "@/plugins/cache"; +import { saveAs } from "file-saver"; +import { parseJSON } from "."; + +let downloadLoadingInstance; +// 是否显示重新登录 +export let isRelogin = { show: false }; + +axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8"; +// 对应国际化资源文件后缀 +axios.defaults.headers["Content-Language"] = "zh_CN"; +// 创建axios实例 +const service = axios.create({ + // axios中请求配置有baseURL选项,表示请求URL公共部分 + baseURL: process.env.VUE_APP_BASE_API, + // 超时 + timeout: 100000000, +}); + +const downloadFile = (response) => { + let { + "download-filename": fileName, + "content-disposition": contentDisposition, + } = response.headers; + + if (!fileName && contentDisposition) { + const result = /(?<=filename=\")(.*?)(?=\";)/.exec(contentDisposition); + fileName = result[1]; + } + + fileName = decodeURIComponent(fileName); + + const objectUrl = URL.createObjectURL(response.data); + const link = document.createElement("a"); + link.href = objectUrl; + if (fileName) { + link.setAttribute("download", fileName); + link.setAttribute("target", "_blank"); + } + document.body.appendChild(link); + link.click(); + window.URL.revokeObjectURL(link.href); + document.body.removeChild(link); +}; + +// request拦截器 +service.interceptors.request.use( + (config) => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false; + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false; + if (getToken() && !isToken) { + config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改 + } + // get请求映射params参数 + if (config.method === "get" && config.params) { + let url = config.url + "?" + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if ( + !isRepeatSubmit && + (config.method === "post" || config.method === "put") + ) { + const requestObj = { + url: config.url, + data: + typeof config.data === "object" + ? JSON.stringify(config.data) + : config.data, + time: new Date().getTime(), + }; + const sessionObj = cache.session.getJSON("sessionObj"); + if ( + sessionObj === undefined || + sessionObj === null || + sessionObj === "" + ) { + cache.session.setJSON("sessionObj", requestObj); + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if ( + s_data === requestObj.data && + requestObj.time - s_time < interval && + s_url === requestObj.url + ) { + const message = "数据正在处理,请勿重复提交"; + console.warn(`[${s_url}]: ` + message); + return Promise.reject(new Error(message)); + } else { + cache.session.setJSON("sessionObj", requestObj); + } + } + } + return config; + }, + (error) => { + console.log(error); + Promise.reject(error); + } +); + +// 响应拦截器 +service.interceptors.response.use( + async (res) => { + if (res.data instanceof Blob) { + if (res.data.type == "application/json") { + const text = await res.data.text(); + res.data = parseJSON(text); + } else { + downloadFile(res); + return; + } + } + + // 未设置状态码则默认成功状态 + const code = res.data.code || 200; + // 获取错误信息 + const msg = errorCode[code] || res.data.msg || errorCode["default"]; + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + MessageBox.confirm( + "登录状态已过期,您可以继续留在该页面,或者重新登录", + "系统提示", + { + confirmButtonText: "重新登录", + cancelButtonText: "取消", + type: "warning", + } + ) + .then(() => { + isRelogin.show = false; + store.dispatch("LogOut").then(() => { + location.href = process.env.VUE_APP_CONTEXT_PATH; + }); + }) + .catch(() => { + isRelogin.show = false; + }); + } + return Promise.reject("无效的会话,或者会话已过期,请重新登录。"); + } else if (code === 500) { + Message({ + message: msg, + type: "error", + dangerouslyUseHTMLString: msg.includes("
"), + }); + return Promise.reject(new Error(msg)); + } else if (code === 601) { + Message({ message: msg, type: "warning" }); + return Promise.reject("error"); + } else if (code !== 200) { + Notification.error({ title: msg }); + return Promise.reject("error"); + } else { + return res.data; + } + }, + (error) => { + console.log("err" + error); + let { message } = error; + if (message == "Network Error") { + message = "后端接口连接异常"; + } else if (message.includes("timeout")) { + message = "系统接口请求超时"; + } else if (message.includes("Request failed with status code")) { + message = "系统接口" + message.substr(message.length - 3) + "异常"; + } + Message({ message: message, type: "error", duration: 5 * 1000 }); + return Promise.reject(error); + } +); + +// 通用下载方法 +export function download(url, params, filename, config) { + downloadLoadingInstance = Loading.service({ + text: "正在下载数据,请稍候", + spinner: "el-icon-loading", + background: "rgba(0, 0, 0, 0.7)", + }); + return service + .post(url, params, { + transformRequest: [ + (params) => { + return tansParams(params); + }, + ], + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + responseType: "blob", + ...config, + }) + .then(async (data) => { + const isBlob = blobValidate(data); + if (isBlob) { + 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"]; + Message.error(errMsg); + } + downloadLoadingInstance.close(); + }) + .catch((r) => { + console.error(r); + Message.error("下载文件出现错误,请联系管理员!"); + downloadLoadingInstance.close(); + }); +} + +export default service; diff --git a/src/utils/ruoyi.js b/src/utils/ruoyi.js new file mode 100644 index 0000000..44bf9c4 --- /dev/null +++ b/src/utils/ruoyi.js @@ -0,0 +1,233 @@ + + +/** + * 通用js方法封装处理 + * Copyright (c) 2019 ruoyi + */ + +// 日期格式化 +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +// 表单重置 +export function resetForm(refName) { + if (this.$refs[refName]) { + this.$refs[refName].resetFields(); + } +} + +// 添加日期范围 +export function addDateRange(params, dateRange, propName) { + let search = params; + search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}; + dateRange = Array.isArray(dateRange) ? dateRange : []; + if (typeof (propName) === 'undefined') { + search.params['beginTime'] = dateRange[0]; + search.params['endTime'] = dateRange[1]; + } else { + search.params['begin' + propName] = dateRange[0]; + search.params['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].value == ('' + value)) { + actions.push(datas[key].label); + return true; + } + }) + if (actions.length === 0) { + actions.push(value); + } + return actions.join(''); +} + +// 回显数据字典(字符串、数组) +export function selectDictLabels(datas, value, separator) { + if (value === undefined || value.length ===0) { + return ""; + } + if (Array.isArray(value)) { + value = value.join(","); + } + var actions = []; + var currentSeparator = undefined === separator ? "," : separator; + var temp = value.split(currentSeparator); + Object.keys(value.split(currentSeparator)).some((val) => { + var match = false; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + temp[val])) { + actions.push(datas[key].label + currentSeparator); + match = true; + } + }) + if (!match) { + actions.push(temp[val] + currentSeparator); + } + }) + return actions.join('').substring(0, actions.join('').length - 1); +} + +// 字符串格式化(%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, parentId, children) { + let config = { + id: id || 'id', + parentId: parentId || 'parentId', + childrenList: children || 'children' + }; + + var childrenListMap = {}; + var nodeIds = {}; + var tree = []; + + for (let d of data) { + let parentId = d[config.parentId]; + if (childrenListMap[parentId] == null) { + childrenListMap[parentId] = []; + } + nodeIds[d[config.id]] = d; + childrenListMap[parentId].push(d); + } + + for (let d of data) { + let parentId = d[config.parentId]; + if (nodeIds[parentId] == null) { + tree.push(d); + } + } + + for (let t of tree) { + adaptToChildrenList(t); + } + + function adaptToChildrenList(o) { + if (childrenListMap[o[config.id]] !== null) { + o[config.childrenList] = childrenListMap[o[config.id]]; + } + if (o[config.childrenList]) { + for (let c of o[config.childrenList]) { + adaptToChildrenList(c); + } + } + } + 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 && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']'; + var subPart = encodeURIComponent(params) + "="; + result += subPart + encodeURIComponent(value[key]) + "&"; + } + } + } else { + result += part + encodeURIComponent(value) + "&"; + } + } + } + return result +} + +// 验证是否为blob格式 +export function blobValidate(data) { + return data.type !== 'application/json' +} 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..adfa254 --- /dev/null +++ b/src/utils/validate.js @@ -0,0 +1,83 @@ +/** + * @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/vueBus.js b/src/utils/vueBus.js new file mode 100644 index 0000000..95235a0 --- /dev/null +++ b/src/utils/vueBus.js @@ -0,0 +1,5 @@ +import Bus from 'vue'; +let install = function (Vue) { + Vue.prototype.$bus = new Bus() +} +export default { install }; \ No newline at end of file diff --git a/src/views/HighDimensionalData/index.vue b/src/views/HighDimensionalData/index.vue new file mode 100644 index 0000000..561ab83 --- /dev/null +++ b/src/views/HighDimensionalData/index.vue @@ -0,0 +1,334 @@ + + + + + diff --git a/src/views/components/AdjustableChart/index.vue b/src/views/components/AdjustableChart/index.vue new file mode 100644 index 0000000..e7a4368 --- /dev/null +++ b/src/views/components/AdjustableChart/index.vue @@ -0,0 +1,175 @@ + + + + + \ No newline at end of file diff --git a/src/views/components/PlaneList/index.vue b/src/views/components/PlaneList/index.vue new file mode 100644 index 0000000..099f2c4 --- /dev/null +++ b/src/views/components/PlaneList/index.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/src/views/components/PlanePartsTree/index.vue b/src/views/components/PlanePartsTree/index.vue new file mode 100644 index 0000000..7248c8b --- /dev/null +++ b/src/views/components/PlanePartsTree/index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/views/components/StressTag/index.vue b/src/views/components/StressTag/index.vue new file mode 100644 index 0000000..47738de --- /dev/null +++ b/src/views/components/StressTag/index.vue @@ -0,0 +1,47 @@ + + + + + \ No newline at end of file diff --git a/src/views/components/icons/element-icons.js b/src/views/components/icons/element-icons.js new file mode 100644 index 0000000..9ea4d63 --- /dev/null +++ b/src/views/components/icons/element-icons.js @@ -0,0 +1,3 @@ +const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'] + +export default elementIcons diff --git a/src/views/components/icons/index.vue b/src/views/components/icons/index.vue new file mode 100644 index 0000000..d3c9a71 --- /dev/null +++ b/src/views/components/icons/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/views/components/icons/svg-icons.js b/src/views/components/icons/svg-icons.js new file mode 100644 index 0000000..724cd8e --- /dev/null +++ b/src/views/components/icons/svg-icons.js @@ -0,0 +1,10 @@ +const req = require.context('../../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const svgIcons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default svgIcons diff --git a/src/views/demo/demo/index.vue b/src/views/demo/demo/index.vue new file mode 100644 index 0000000..2bfefd4 --- /dev/null +++ b/src/views/demo/demo/index.vue @@ -0,0 +1,432 @@ + + + diff --git a/src/views/demo/tree/index.vue b/src/views/demo/tree/index.vue new file mode 100644 index 0000000..d66c6f9 --- /dev/null +++ b/src/views/demo/tree/index.vue @@ -0,0 +1,314 @@ + + + diff --git a/src/views/error/401.vue b/src/views/error/401.vue new file mode 100644 index 0000000..448b6ec --- /dev/null +++ b/src/views/error/401.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..96f075c --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/src/views/evaluation-model/config/index.js b/src/views/evaluation-model/config/index.js new file mode 100644 index 0000000..0338c4e --- /dev/null +++ b/src/views/evaluation-model/config/index.js @@ -0,0 +1,84 @@ +import { FormItemType } from "@/components/HForm/enum"; + +// 模型类型增删改查接口配置 +export const typeUrls = { + list: "/system/modelType/list", + add: "/system/modelType", + edit: "/system/modelType", + delete: "/system/modelType", +}; + +// 搜索栏配置 +export const searchItems = [ + { + label: "模型名称", + prop: "modelName", + placeholder: "请输入模型名称", + span: 6, + }, + { + label: "算法参数", + prop: "remarks", + placeholder: "请输入描述", + span: 6, + }, +]; + +// 模型增删改查接口配置 +export const tableUrls = { + list: "/system/model/list", + add: "/system/model", + edit: "/system/model", + delete: "/system/model", + import: "/system/model/import", + export: "/system/model/export", +}; + +// 模型表格列配置 +export const tableColumns = [ + { + title: "模型名称", + dataIndex: "modelName", + width: 350, + ellipsis: true, + align: "left", + }, + { title: "算法模型公式", dataIndex: "displayFormula", width: 500, align: "left" }, + { title: "算法参数", dataIndex: "remarks", minWidth: 300, align: "left" }, + { + title: "操作", + dataIndex: "action", + fixed: "right", + width: 120, + align: "center", + }, +]; + +// 模型表单项配置 +export const tableFormItems = [ + { + label: "模型名称", + prop: "modelName", + placeholder: "请输入模型名称", + span: 24, + }, + { label: "算法模型公式", prop: "displayFormula", span: 24 }, + { + label: "算法参数", + prop: "remarks", + placeholder: "请输入描述", + type: FormItemType.richText, + attrs: { + rows: 6, + }, + span: 24, + }, +]; + +// 模型表单项校验配置 +export const tableFormRules = { + modelName: [{ required: true, message: "请输入模型名称" }], + displayFormula: [{ required: true, message: "请输入显示公式" }], + decimalPlaces: [{ required: true, message: "请输入小数位数" }], + remarks: [{ required: true, message: "请输入描述" }], +}; diff --git a/src/views/evaluation-model/index.vue b/src/views/evaluation-model/index.vue new file mode 100644 index 0000000..2cbf4db --- /dev/null +++ b/src/views/evaluation-model/index.vue @@ -0,0 +1,226 @@ + + + diff --git a/src/views/help/index.vue b/src/views/help/index.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/views/home/components/BulletTargetIntersectionShootingLine.vue b/src/views/home/components/BulletTargetIntersectionShootingLine.vue new file mode 100644 index 0000000..1187bdd --- /dev/null +++ b/src/views/home/components/BulletTargetIntersectionShootingLine.vue @@ -0,0 +1,362 @@ + + + + + + diff --git a/src/views/home/components/Controls.vue b/src/views/home/components/Controls.vue new file mode 100644 index 0000000..57d789f --- /dev/null +++ b/src/views/home/components/Controls.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/src/views/home/components/DamageDistributionDisplay.vue b/src/views/home/components/DamageDistributionDisplay.vue new file mode 100644 index 0000000..fcba365 --- /dev/null +++ b/src/views/home/components/DamageDistributionDisplay.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/views/home/components/FightModel.vue b/src/views/home/components/FightModel.vue new file mode 100644 index 0000000..cf50ed2 --- /dev/null +++ b/src/views/home/components/FightModel.vue @@ -0,0 +1,550 @@ + + + + + + diff --git a/src/views/home/components/KillingElementPowerField.vue b/src/views/home/components/KillingElementPowerField.vue new file mode 100644 index 0000000..d115b49 --- /dev/null +++ b/src/views/home/components/KillingElementPowerField.vue @@ -0,0 +1,338 @@ + + + + + + diff --git a/src/views/home/components/SimulationTree.vue b/src/views/home/components/SimulationTree.vue new file mode 100644 index 0000000..0334635 --- /dev/null +++ b/src/views/home/components/SimulationTree.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/src/views/home/components/libgif.js b/src/views/home/components/libgif.js new file mode 100644 index 0000000..b14e0e9 --- /dev/null +++ b/src/views/home/components/libgif.js @@ -0,0 +1,990 @@ +/* + SuperGif + + Example usage: + + + + + + Image tag attributes: + + rel:animated_src - If this url is specified, it's loaded into the player instead of src. + This allows a preview frame to be shown until animated gif data is streamed into the canvas + + rel:auto_play - Defaults to 1 if not specified. If set to zero, a call to the play() method is needed + + Constructor options args + + gif Required. The DOM element of an img tag. + loop_mode Optional. Setting this to false will force disable looping of the gif. + auto_play Optional. Same as the rel:auto_play attribute above, this arg overrides the img tag info. + max_width Optional. Scale images over max_width down to max_width. Helpful with mobile. + on_end Optional. Add a callback for when the gif reaches the end of a single loop (one iteration). The first argument passed will be the gif HTMLElement. + loop_delay Optional. The amount of time to pause (in ms) after each single loop (iteration). + draw_while_loading Optional. Determines whether the gif will be drawn to the canvas whilst it is loaded. + show_progress_bar Optional. Only applies when draw_while_loading is set to true. + + Instance methods + + // loading + load( callback ) Loads the gif specified by the src or rel:animated_src sttributie of the img tag into a canvas element and then calls callback if one is passed + load_url( src, callback ) Loads the gif file specified in the src argument into a canvas element and then calls callback if one is passed + + // play controls + play - Start playing the gif + pause - Stop playing the gif + move_to(i) - Move to frame i of the gif + move_relative(i) - Move i frames ahead (or behind if i < 0) + + // getters + get_canvas The canvas element that the gif is playing in. Handy for assigning event handlers to. + get_playing Whether or not the gif is currently playing + get_loading Whether or not the gif has finished loading/parsing + get_auto_play Whether or not the gif is set to play automatically + get_length The number of frames in the gif + get_current_frame The index of the currently displayed frame of the gif + + For additional customization (viewport inside iframe) these params may be passed: + c_w, c_h - width and height of canvas + vp_t, vp_l, vp_ w, vp_h - top, left, width and height of the viewport + + A bonus: few articles to understand what is going on + http://enthusiasms.org/post/16976438906 + http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp + http://humpy77.deviantart.com/journal/Frame-Delay-Times-for-Animated-GIFs-214150546 + +*/ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define([], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.SuperGif = factory(); + } +}(this, function () { + // Generic functions + var bitsToNum = function (ba) { + return ba.reduce(function (s, n) { + return s * 2 + n; + }, 0); + }; + + var byteToBitArr = function (bite) { + var a = []; + for (var i = 7; i >= 0; i--) { + a.push( !! (bite & (1 << i))); + } + return a; + }; + + // Stream + /** + * @constructor + */ + // Make compiler happy. + var Stream = function (data) { + this.data = data; + this.len = this.data.length; + this.pos = 0; + + this.readByte = function () { + if (this.pos >= this.data.length) { + throw new Error('Attempted to read past end of stream.'); + } + if (data instanceof Uint8Array) + return data[this.pos++]; + else + return data.charCodeAt(this.pos++) & 0xFF; + }; + + this.readBytes = function (n) { + var bytes = []; + for (var i = 0; i < n; i++) { + bytes.push(this.readByte()); + } + return bytes; + }; + + this.read = function (n) { + var s = ''; + for (var i = 0; i < n; i++) { + s += String.fromCharCode(this.readByte()); + } + return s; + }; + + this.readUnsigned = function () { // Little-endian. + var a = this.readBytes(2); + return (a[1] << 8) + a[0]; + }; + }; + + var lzwDecode = function (minCodeSize, data) { + // TODO: Now that the GIF parser is a bit different, maybe this should get an array of bytes instead of a String? + var pos = 0; // Maybe this streaming thing should be merged with the Stream? + var readCode = function (size) { + var code = 0; + for (var i = 0; i < size; i++) { + if (data.charCodeAt(pos >> 3) & (1 << (pos & 7))) { + code |= 1 << i; + } + pos++; + } + return code; + }; + + var output = []; + + var clearCode = 1 << minCodeSize; + var eoiCode = clearCode + 1; + + var codeSize = minCodeSize + 1; + + var dict = []; + + var clear = function () { + dict = []; + codeSize = minCodeSize + 1; + for (var i = 0; i < clearCode; i++) { + dict[i] = [i]; + } + dict[clearCode] = []; + dict[eoiCode] = null; + + }; + + var code; + var last; + + while (true) { + last = code; + code = readCode(codeSize); + + if (code === clearCode) { + clear(); + continue; + } + if (code === eoiCode) break; + + if (code < dict.length) { + if (last !== clearCode) { + dict.push(dict[last].concat(dict[code][0])); + } + } + else { + if (code !== dict.length) throw new Error('Invalid LZW code.'); + dict.push(dict[last].concat(dict[last][0])); + } + output.push.apply(output, dict[code]); + + if (dict.length === (1 << codeSize) && codeSize < 12) { + // If we're at the last code and codeSize is 12, the next code will be a clearCode, and it'll be 12 bits long. + codeSize++; + } + } + + // I don't know if this is technically an error, but some GIFs do it. + //if (Math.ceil(pos / 8) !== data.length) throw new Error('Extraneous LZW bytes.'); + return output; + }; + + + // The actual parsing; returns an object with properties. + var parseGIF = function (st, handler) { + handler || (handler = {}); + + // LZW (GIF-specific) + var parseCT = function (entries) { // Each entry is 3 bytes, for RGB. + var ct = []; + for (var i = 0; i < entries; i++) { + ct.push(st.readBytes(3)); + } + return ct; + }; + + var readSubBlocks = function () { + var size, data; + data = ''; + do { + size = st.readByte(); + data += st.read(size); + } while (size !== 0); + return data; + }; + + var parseHeader = function () { + var hdr = {}; + hdr.sig = st.read(3); + hdr.ver = st.read(3); + if (hdr.sig !== 'GIF') throw new Error('Not a GIF file.'); // XXX: This should probably be handled more nicely. + hdr.width = st.readUnsigned(); + hdr.height = st.readUnsigned(); + + var bits = byteToBitArr(st.readByte()); + hdr.gctFlag = bits.shift(); + hdr.colorRes = bitsToNum(bits.splice(0, 3)); + hdr.sorted = bits.shift(); + hdr.gctSize = bitsToNum(bits.splice(0, 3)); + + hdr.bgColor = st.readByte(); + hdr.pixelAspectRatio = st.readByte(); // if not 0, aspectRatio = (pixelAspectRatio + 15) / 64 + if (hdr.gctFlag) { + hdr.gct = parseCT(1 << (hdr.gctSize + 1)); + } + handler.hdr && handler.hdr(hdr); + }; + + var parseExt = function (block) { + var parseGCExt = function (block) { + var blockSize = st.readByte(); // Always 4 + var bits = byteToBitArr(st.readByte()); + block.reserved = bits.splice(0, 3); // Reserved; should be 000. + block.disposalMethod = bitsToNum(bits.splice(0, 3)); + block.userInput = bits.shift(); + block.transparencyGiven = bits.shift(); + + block.delayTime = st.readUnsigned(); + + block.transparencyIndex = st.readByte(); + + block.terminator = st.readByte(); + + handler.gce && handler.gce(block); + }; + + var parseComExt = function (block) { + block.comment = readSubBlocks(); + handler.com && handler.com(block); + }; + + var parsePTExt = function (block) { + // No one *ever* uses this. If you use it, deal with parsing it yourself. + var blockSize = st.readByte(); // Always 12 + block.ptHeader = st.readBytes(12); + block.ptData = readSubBlocks(); + handler.pte && handler.pte(block); + }; + + var parseAppExt = function (block) { + var parseNetscapeExt = function (block) { + var blockSize = st.readByte(); // Always 3 + block.unknown = st.readByte(); // ??? Always 1? What is this? + block.iterations = st.readUnsigned(); + block.terminator = st.readByte(); + handler.app && handler.app.NETSCAPE && handler.app.NETSCAPE(block); + }; + + var parseUnknownAppExt = function (block) { + block.appData = readSubBlocks(); + // FIXME: This won't work if a handler wants to match on any identifier. + handler.app && handler.app[block.identifier] && handler.app[block.identifier](block); + }; + + var blockSize = st.readByte(); // Always 11 + block.identifier = st.read(8); + block.authCode = st.read(3); + switch (block.identifier) { + case 'NETSCAPE': + parseNetscapeExt(block); + break; + default: + parseUnknownAppExt(block); + break; + } + }; + + var parseUnknownExt = function (block) { + block.data = readSubBlocks(); + handler.unknown && handler.unknown(block); + }; + + block.label = st.readByte(); + switch (block.label) { + case 0xF9: + block.extType = 'gce'; + parseGCExt(block); + break; + case 0xFE: + block.extType = 'com'; + parseComExt(block); + break; + case 0x01: + block.extType = 'pte'; + parsePTExt(block); + break; + case 0xFF: + block.extType = 'app'; + parseAppExt(block); + break; + default: + block.extType = 'unknown'; + parseUnknownExt(block); + break; + } + }; + + var parseImg = function (img) { + var deinterlace = function (pixels, width) { + // Of course this defeats the purpose of interlacing. And it's *probably* + // the least efficient way it's ever been implemented. But nevertheless... + var newPixels = new Array(pixels.length); + var rows = pixels.length / width; + var cpRow = function (toRow, fromRow) { + var fromPixels = pixels.slice(fromRow * width, (fromRow + 1) * width); + newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels)); + }; + + // See appendix E. + var offsets = [0, 4, 2, 1]; + var steps = [8, 8, 4, 2]; + + var fromRow = 0; + for (var pass = 0; pass < 4; pass++) { + for (var toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) { + cpRow(toRow, fromRow) + fromRow++; + } + } + + return newPixels; + }; + + img.leftPos = st.readUnsigned(); + img.topPos = st.readUnsigned(); + img.width = st.readUnsigned(); + img.height = st.readUnsigned(); + + var bits = byteToBitArr(st.readByte()); + img.lctFlag = bits.shift(); + img.interlaced = bits.shift(); + img.sorted = bits.shift(); + img.reserved = bits.splice(0, 2); + img.lctSize = bitsToNum(bits.splice(0, 3)); + + if (img.lctFlag) { + img.lct = parseCT(1 << (img.lctSize + 1)); + } + + img.lzwMinCodeSize = st.readByte(); + + var lzwData = readSubBlocks(); + + img.pixels = lzwDecode(img.lzwMinCodeSize, lzwData); + + if (img.interlaced) { // Move + img.pixels = deinterlace(img.pixels, img.width); + } + + handler.img && handler.img(img); + }; + + var parseBlock = function () { + var block = {}; + block.sentinel = st.readByte(); + + switch (String.fromCharCode(block.sentinel)) { // For ease of matching + case '!': + block.type = 'ext'; + parseExt(block); + break; + case ',': + block.type = 'img'; + parseImg(block); + break; + case ';': + block.type = 'eof'; + handler.eof && handler.eof(block); + break; + default: + throw new Error('Unknown block: 0x' + block.sentinel.toString(16)); // TODO: Pad this with a 0. + } + + if (block.type !== 'eof') setTimeout(parseBlock, 0); + }; + + var parse = function () { + parseHeader(); + setTimeout(parseBlock, 0); + }; + + parse(); + }; + + var SuperGif = function ( opts ) { + var options = { + //viewport position + vp_l: 0, + vp_t: 0, + vp_w: null, + vp_h: null, + //canvas sizes + c_w: null, + c_h: null + }; + for (var i in opts ) { options[i] = opts[i] } + if (options.vp_w && options.vp_h) options.is_vp = true; + + var stream; + var hdr; + + var loadError = null; + var loading = false; + + var transparency = null; + var delay = null; + var disposalMethod = null; + var disposalRestoreFromIdx = null; + var lastDisposalMethod = null; + var frame = null; + var lastImg = null; + + var playing = true; + var forward = true; + + var ctx_scaled = false; + + var frames = []; + var frameOffsets = []; // elements have .x and .y properties + + var gif = options.gif; + if (typeof options.auto_play == 'undefined') + options.auto_play = (!gif.getAttribute('rel:auto_play') || gif.getAttribute('rel:auto_play') == '1'); + + var onEndListener = (options.hasOwnProperty('on_end') ? options.on_end : null); + var loopDelay = (options.hasOwnProperty('loop_delay') ? options.loop_delay : 0); + var overrideLoopMode = (options.hasOwnProperty('loop_mode') ? options.loop_mode : 'auto'); + var drawWhileLoading = (options.hasOwnProperty('draw_while_loading') ? options.draw_while_loading : true); + var showProgressBar = drawWhileLoading ? (options.hasOwnProperty('show_progress_bar') ? options.show_progress_bar : true) : false; + var progressBarHeight = (options.hasOwnProperty('progressbar_height') ? options.progressbar_height : 25); + var progressBarBackgroundColor = (options.hasOwnProperty('progressbar_background_color') ? options.progressbar_background_color : 'rgba(255,255,255,0.4)'); + var progressBarForegroundColor = (options.hasOwnProperty('progressbar_foreground_color') ? options.progressbar_foreground_color : 'rgba(255,0,22,.8)'); + + var clear = function () { + transparency = null; + delay = null; + lastDisposalMethod = disposalMethod; + disposalMethod = null; + frame = null; + }; + + // XXX: There's probably a better way to handle catching exceptions when + // callbacks are involved. + var doParse = function () { + try { + parseGIF(stream, handler); + } + catch (err) { + doLoadError('parse'); + } + }; + + var doText = function (text) { + toolbar.innerHTML = text; // innerText? Escaping? Whatever. + toolbar.style.visibility = 'visible'; + }; + + var setSizes = function(w, h) { + canvas.width = w * get_canvas_scale(); + canvas.height = h * get_canvas_scale(); + toolbar.style.minWidth = ( w * get_canvas_scale() ) + 'px'; + + tmpCanvas.width = w; + tmpCanvas.height = h; + tmpCanvas.style.width = w + 'px'; + tmpCanvas.style.height = h + 'px'; + tmpCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0); + }; + + var setFrameOffset = function(frame, offset) { + if (!frameOffsets[frame]) { + frameOffsets[frame] = offset; + return; + } + if (typeof offset.x !== 'undefined') { + frameOffsets[frame].x = offset.x; + } + if (typeof offset.y !== 'undefined') { + frameOffsets[frame].y = offset.y; + } + }; + + var doShowProgress = function (pos, length, draw) { + if (draw && showProgressBar) { + var height = progressBarHeight; + var left, mid, top, width; + if (options.is_vp) { + if (!ctx_scaled) { + top = (options.vp_t + options.vp_h - height); + height = height; + left = options.vp_l; + mid = left + (pos / length) * options.vp_w; + width = canvas.width; + } else { + top = (options.vp_t + options.vp_h - height) / get_canvas_scale(); + height = height / get_canvas_scale(); + left = (options.vp_l / get_canvas_scale() ); + mid = left + (pos / length) * (options.vp_w / get_canvas_scale()); + width = canvas.width / get_canvas_scale(); + } + //some debugging, draw rect around viewport + if (false) { + if (!ctx_scaled) { + var l = options.vp_l, t = options.vp_t; + var w = options.vp_w, h = options.vp_h; + } else { + var l = options.vp_l/get_canvas_scale(), t = options.vp_t/get_canvas_scale(); + var w = options.vp_w/get_canvas_scale(), h = options.vp_h/get_canvas_scale(); + } + ctx.rect(l,t,w,h); + ctx.stroke(); + } + } + else { + top = (canvas.height - height) / (ctx_scaled ? get_canvas_scale() : 1); + mid = ((pos / length) * canvas.width) / (ctx_scaled ? get_canvas_scale() : 1); + width = canvas.width / (ctx_scaled ? get_canvas_scale() : 1 ); + height /= ctx_scaled ? get_canvas_scale() : 1; + } + + ctx.fillStyle = progressBarBackgroundColor; + ctx.fillRect(mid, top, width - mid, height); + + ctx.fillStyle = progressBarForegroundColor; + ctx.fillRect(0, top, mid, height); + } + }; + + var doLoadError = function (originOfError) { + var drawError = function () { + ctx.fillStyle = 'black'; + ctx.fillRect(0, 0, options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height); + ctx.strokeStyle = 'red'; + ctx.lineWidth = 3; + ctx.moveTo(0, 0); + ctx.lineTo(options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height); + ctx.moveTo(0, options.c_h ? options.c_h : hdr.height); + ctx.lineTo(options.c_w ? options.c_w : hdr.width, 0); + ctx.stroke(); + }; + + loadError = originOfError; + hdr = { + width: gif.width, + height: gif.height + }; // Fake header. + frames = []; + drawError(); + }; + + var doHdr = function (_hdr) { + hdr = _hdr; + setSizes(hdr.width, hdr.height) + }; + + var doGCE = function (gce) { + pushFrame(); + clear(); + transparency = gce.transparencyGiven ? gce.transparencyIndex : null; + delay = gce.delayTime; + disposalMethod = gce.disposalMethod; + // We don't have much to do with the rest of GCE. + }; + + var pushFrame = function () { + if (!frame) return; + frames.push({ + data: frame.getImageData(0, 0, hdr.width, hdr.height), + delay: delay + }); + frameOffsets.push({ x: 0, y: 0 }); + }; + + var doImg = function (img) { + if (!frame) frame = tmpCanvas.getContext('2d'); + + var currIdx = frames.length; + + //ct = color table, gct = global color table + var ct = img.lctFlag ? img.lct : hdr.gct; // TODO: What if neither exists? + + /* + Disposal method indicates the way in which the graphic is to + be treated after being displayed. + + Values : 0 - No disposal specified. The decoder is + not required to take any action. + 1 - Do not dispose. The graphic is to be left + in place. + 2 - Restore to background color. The area used by the + graphic must be restored to the background color. + 3 - Restore to previous. The decoder is required to + restore the area overwritten by the graphic with + what was there prior to rendering the graphic. + + Importantly, "previous" means the frame state + after the last disposal of method 0, 1, or 2. + */ + if (currIdx > 0) { + if (lastDisposalMethod === 3) { + // Restore to previous + // If we disposed every frame including first frame up to this point, then we have + // no composited frame to restore to. In this case, restore to background instead. + if (disposalRestoreFromIdx !== null) { + frame.putImageData(frames[disposalRestoreFromIdx].data, 0, 0); + } else { + frame.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height); + } + } else { + disposalRestoreFromIdx = currIdx - 1; + } + + if (lastDisposalMethod === 2) { + // Restore to background color + // Browser implementations historically restore to transparent; we do the same. + // http://www.wizards-toolkit.org/discourse-server/viewtopic.php?f=1&t=21172#p86079 + frame.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height); + } + } + // else, Undefined/Do not dispose. + // frame contains final pixel data from the last frame; do nothing + + //Get existing pixels for img region after applying disposal method + var imgData = frame.getImageData(img.leftPos, img.topPos, img.width, img.height); + + //apply color table colors + img.pixels.forEach(function (pixel, i) { + // imgData.data === [R,G,B,A,R,G,B,A,...] + if (pixel !== transparency) { + imgData.data[i * 4 + 0] = ct[pixel][0]; + imgData.data[i * 4 + 1] = ct[pixel][1]; + imgData.data[i * 4 + 2] = ct[pixel][2]; + imgData.data[i * 4 + 3] = 255; // Opaque. + } + }); + + frame.putImageData(imgData, img.leftPos, img.topPos); + + if (!ctx_scaled) { + ctx.scale(get_canvas_scale(),get_canvas_scale()); + ctx_scaled = true; + } + + // We could use the on-page canvas directly, except that we draw a progress + // bar for each image chunk (not just the final image). + if (drawWhileLoading) { + ctx.drawImage(tmpCanvas, 0, 0); + drawWhileLoading = options.auto_play; + } + + lastImg = img; + }; + + var player = (function () { + var i = -1; + var iterationCount = 0; + + var showingInfo = false; + var pinned = false; + + /** + * Gets the index of the frame "up next". + * @returns {number} + */ + var getNextFrameNo = function () { + var delta = (forward ? 1 : -1); + return (i + delta + frames.length) % frames.length; + }; + + var stepFrame = function (amount) { // XXX: Name is confusing. + i = i + amount; + + putFrame(); + }; + + var step = (function () { + var stepping = false; + + var completeLoop = function () { + if (onEndListener !== null) + onEndListener(gif); + iterationCount++; + + if (overrideLoopMode !== false || iterationCount < 0) { + doStep(); + } else { + stepping = false; + playing = false; + } + }; + + var doStep = function () { + stepping = playing; + if (!stepping) return; + + stepFrame(1); + var delay = frames[i].delay * 10; + if (!delay) delay = 100; // FIXME: Should this even default at all? What should it be? + + var nextFrameNo = getNextFrameNo(); + if (nextFrameNo === 0) { + delay += loopDelay; + setTimeout(completeLoop, delay); + } else { + setTimeout(doStep, delay); + } + }; + + return function () { + if (!stepping) setTimeout(doStep, 0); + }; + }()); + + var putFrame = function () { + var offset; + i = parseInt(i, 10); + + if (i > frames.length - 1){ + i = 0; + } + + if (i < 0){ + i = 0; + } + + offset = frameOffsets[i]; + + tmpCanvas.getContext("2d").putImageData(frames[i].data, offset.x, offset.y); + ctx.globalCompositeOperation = "copy"; + ctx.drawImage(tmpCanvas, 0, 0); + }; + + var play = function () { + playing = true; + step(); + }; + + var pause = function () { + playing = false; + }; + + + return { + init: function () { + if (loadError) return; + + if ( ! (options.c_w && options.c_h) ) { + ctx.scale(get_canvas_scale(),get_canvas_scale()); + } + + if (options.auto_play) { + step(); + } + else { + i = 0; + putFrame(); + } + }, + step: step, + play: play, + pause: pause, + playing: playing, + move_relative: stepFrame, + current_frame: function() { return i; }, + length: function() { return frames.length }, + move_to: function ( frame_idx ) { + i = frame_idx; + putFrame(); + } + } + }()); + + var doDecodeProgress = function (draw) { + doShowProgress(stream.pos, stream.data.length, draw); + }; + + var doNothing = function () {}; + /** + * @param{boolean=} draw Whether to draw progress bar or not; this is not idempotent because of translucency. + * Note that this means that the text will be unsynchronized with the progress bar on non-frames; + * but those are typically so small (GCE etc.) that it doesn't really matter. TODO: Do this properly. + */ + var withProgress = function (fn, draw) { + return function (block) { + fn(block); + doDecodeProgress(draw); + }; + }; + + + var handler = { + hdr: withProgress(doHdr), + gce: withProgress(doGCE), + com: withProgress(doNothing), + // I guess that's all for now. + app: { + // TODO: Is there much point in actually supporting iterations? + NETSCAPE: withProgress(doNothing) + }, + img: withProgress(doImg, true), + eof: function (block) { + //toolbar.style.display = ''; + pushFrame(); + doDecodeProgress(false); + if ( ! (options.c_w && options.c_h) ) { + canvas.width = hdr.width * get_canvas_scale(); + canvas.height = hdr.height * get_canvas_scale(); + } + player.init(); + loading = false; + if (load_callback) { + load_callback(gif); + } + + } + }; + + var init = function () { + var parent = gif.parentNode; + + var div = document.createElement('div'); + canvas = document.createElement('canvas'); + ctx = canvas.getContext('2d'); + toolbar = document.createElement('div'); + + tmpCanvas = document.createElement('canvas'); + + div.width = canvas.width = gif.width; + div.height = canvas.height = gif.height; + toolbar.style.minWidth = gif.width + 'px'; + + div.className = 'jsgif'; + toolbar.className = 'jsgif_toolbar'; + div.appendChild(canvas); + div.appendChild(toolbar); + + parent.insertBefore(div, gif); + parent.removeChild(gif); + + if (options.c_w && options.c_h) setSizes(options.c_w, options.c_h); + initialized=true; + }; + + var get_canvas_scale = function() { + var scale; + if (options.max_width && hdr && hdr.width > options.max_width) { + scale = options.max_width / hdr.width; + } + else { + scale = 1; + } + return scale; + } + + var canvas, ctx, toolbar, tmpCanvas; + var initialized = false; + var load_callback = false; + + var load_setup = function(callback) { + if (loading) return false; + if (callback) load_callback = callback; + else load_callback = false; + + loading = true; + frames = []; + clear(); + disposalRestoreFromIdx = null; + lastDisposalMethod = null; + frame = null; + lastImg = null; + + return true; + } + + return { + // play controls + play: player.play, + pause: player.pause, + move_relative: player.move_relative, + move_to: player.move_to, + + // getters for instance vars + get_playing : function() { return playing }, + get_canvas : function() { return canvas }, + get_canvas_scale : function() { return get_canvas_scale() }, + get_loading : function() { return loading }, + get_auto_play : function() { return options.auto_play }, + get_length : function() { return player.length() }, + get_current_frame: function() { return player.current_frame() }, + load_url: function(src,callback){ + if (!load_setup(callback)) return; + + var h = new XMLHttpRequest(); + // new browsers (XMLHttpRequest2-compliant) + h.open('GET', src, true); + + if ('overrideMimeType' in h) { + h.overrideMimeType('text/plain; charset=x-user-defined'); + } + + // old browsers (XMLHttpRequest-compliant) + else if ('responseType' in h) { + h.responseType = 'arraybuffer'; + } + + // IE9 (Microsoft.XMLHTTP-compliant) + else { + h.setRequestHeader('Accept-Charset', 'x-user-defined'); + } + + h.onloadstart = function() { + // Wait until connection is opened to replace the gif element with a canvas to avoid a blank img + if (!initialized) init(); + }; + h.onload = function(e) { + if (this.status != 200) { + doLoadError('xhr - response'); + } + // emulating response field for IE9 + if (!('response' in this)) { + this.response = new VBArray(this.responseText).toArray().map(String.fromCharCode).join(''); + } + var data = this.response; + if (data.toString().indexOf("ArrayBuffer") > 0) { + data = new Uint8Array(data); + } + + stream = new Stream(data); + setTimeout(doParse, 0); + }; + h.onprogress = function (e) { + if (e.lengthComputable) doShowProgress(e.loaded, e.total, true); + }; + h.onerror = function() { doLoadError('xhr'); }; + h.send(); + }, + load: function (callback) { + this.load_url(gif.getAttribute('rel:animated_src') || gif.src,callback); + }, + load_raw: function(arr, callback) { + if (!load_setup(callback)) return; + if (!initialized) init(); + stream = new Stream(arr); + setTimeout(doParse, 0); + }, + set_frame_offset: setFrameOffset + }; + }; + + return SuperGif; +})); + + diff --git a/src/views/home/config/index.js b/src/views/home/config/index.js new file mode 100644 index 0000000..6ff54fb --- /dev/null +++ b/src/views/home/config/index.js @@ -0,0 +1,224 @@ +import { + BOOM_TYPE, + MISSILE_TARGET_RENDEZVOUS_MODEL_TYPE, +} from "@/utils/dict/DefaultOption"; + +/** + * 模型类型 + */ +export const ELEMENT_TYPE = { + PLANE: "PLANE", + MISSLE: "MISSLE", +}; + +export const RequestUrls = { + planeList: "/project/plane/listAll", + missileList: "/project/missile/listAll", +}; + +// 中间区域展示类型 +export const EMULATION_TYPE = { + PLANE: "1", // 飞机导弹对撞 + KILLING_ELEMENT_POWER_FIELD: "2", // 杀伤元威力场 + BULLET_INTERSECTION: "3", // 弹目交汇 + DAMAGE_DISTRIBUTION_DISPLAY: "4", +}; + +// 飞机装备表单配置 +export const PlaneFormItems = [ + { + label: "机长", + prop: "length", + unit: "米", + }, + { + label: "机翼后缘前掠角", + prop: "wingTrailForangle", + unit: "°", + }, + { + label: "前缘襟翼面积", + prop: "leadFlapArea", + unit: "㎡", + }, + { + label: "飞机高度", + prop: "planeHeight", + unit: "米", + }, + { + label: "机翼面积", + prop: "wingArea", + unit: "㎡", + }, + { + label: "襟副翼面积", + prop: "flaperonArea", + unit: "㎡", + }, + { + label: "翼展", + prop: "wingspan", + unit: "米", + }, + { + label: "武器舱离地高度", + prop: "weaponBayHeight", + unit: "m", + }, + { + label: "副翼面积", + prop: "aileronArea", + unit: "㎡", + }, + { + label: "机翼展弦比", + prop: "wingAspectRatio", + }, + { + label: "正面雷达反射面积", + prop: "radarReflecArea", + unit: "㎡", + }, + { + label: "水平尾翼面积", + prop: "horizonTailArea", + unit: "㎡", + }, + { + label: "机翼前缘后掠角", + prop: "wingLeadBacangle", + unit: "°", + }, + { + label: "垂直尾翼前缘掠角", + prop: "verticalTailLeadAngle", + unit: "°", + }, + { + label: "水平尾翼翼展", + prop: "horizontalTailSpan", + unit: "㎡", + }, + { + label: "垂直尾翼后缘掠角", + prop: "verticalTailAngle", + unit: "°", + }, + { + label: "方向舵面积", + prop: "rudderArea", + unit: "㎡", + }, + { + label: "水平尾翼前缘后掠角", + prop: "horizonTailLeadBacangle", + unit: "°", + }, +]; + +// 杀爆战斗部表单配置 +export const MissleFormItems = [ + { + label: "装药等效TNT当量", + prop: "powderChargeQuality", + unit: "kg", + }, + { + label: "破片飞散角", + prop: "debrisFlyoffHorn", + unit: "°", + }, + { + label: "破片平均速度", + prop: "debrisAverageSpeed", + unit: "m/s", + }, + { + label: "破片飞散中心角", + prop: "debrisFlyoffCentralangle", + unit: "°", + }, + { + label: "破片质量", + prop: "debrisQuality", + unit: "g", + }, + { + label: "破片总数", + prop: "debrisTotal", + unit: "枚", + }, + { + label: "弹体坐标系", + prop: "7", + type: "text", + }, + { + label: "起爆模式", + prop: "detonateWay", + type: "select", + options: BOOM_TYPE, + }, +]; + +// 弹目交会表单配置 +export const MissileTargetRendezvousFormItems = [ + { + label: "弹目相对速度", + prop: "9", + unit: "m/s", + }, + { + label: "弹体攻角", + prop: "10", + unit: "°", + }, + { + label: "弹体侧滑角", + prop: "11", + unit: "°", + }, + { + label: "弹体偏航角", + prop: "12", + unit: "°", + }, + { + label: "爆炸点", + prop: "13", + type: "text", + }, + { + label: "", + prop: "14", + type: "radioGroup", + options: MISSILE_TARGET_RENDEZVOUS_MODEL_TYPE, + }, +]; + +// 弹目交会初始信息 +export const InitialMissileTargetRendezvousModel = { + 9: 1000, + 10: 30, + 11: 0, + 12: 0, + 13: "13.5, 12, 3", + 7: "13.5, 12, 3", + 14: MISSILE_TARGET_RENDEZVOUS_MODEL_TYPE[0].value, +}; + +// 毁伤结果列表表格配置 +export const DestroyTableColumns = [ + { title: "部件名称", dataIndex: "name" }, + { dataIndex: "jizhong", align: "center" }, + { dataIndex: "jichuan", align: "center" }, + { dataIndex: "inSpeed", align: "center" }, + { dataIndex: "inAngle", align: "center" }, + { dataIndex: "inAttitude", align: "center" }, + { dataIndex: "breakdownRate", align: "center" }, + { dataIndex: "density", align: "center" }, + { dataIndex: "shockwave", align: "center" }, + { title: "破片毁伤", dataIndex: "destroy", align: "center" }, + { title: "冲击波毁伤", dataIndex: "destroy2", align: "center" }, +]; diff --git a/src/views/home/index.vue b/src/views/home/index.vue new file mode 100644 index 0000000..5342a27 --- /dev/null +++ b/src/views/home/index.vue @@ -0,0 +1,1019 @@ + + + + + diff --git a/src/views/login.vue b/src/views/login.vue new file mode 100644 index 0000000..97f48d7 --- /dev/null +++ b/src/views/login.vue @@ -0,0 +1,368 @@ + + + + + diff --git a/src/views/monitor/admin/index.vue b/src/views/monitor/admin/index.vue new file mode 100644 index 0000000..44322a6 --- /dev/null +++ b/src/views/monitor/admin/index.vue @@ -0,0 +1,15 @@ + + diff --git a/src/views/monitor/cache/index.vue b/src/views/monitor/cache/index.vue new file mode 100644 index 0000000..e81da2e --- /dev/null +++ b/src/views/monitor/cache/index.vue @@ -0,0 +1,144 @@ + + + diff --git a/src/views/monitor/cache/list.vue b/src/views/monitor/cache/list.vue new file mode 100644 index 0000000..a4be540 --- /dev/null +++ b/src/views/monitor/cache/list.vue @@ -0,0 +1,241 @@ + + + diff --git a/src/views/monitor/logininfor/index.vue b/src/views/monitor/logininfor/index.vue new file mode 100644 index 0000000..8fe2e8e --- /dev/null +++ b/src/views/monitor/logininfor/index.vue @@ -0,0 +1,246 @@ + + + + diff --git a/src/views/monitor/online/index.vue b/src/views/monitor/online/index.vue new file mode 100644 index 0000000..ad613c9 --- /dev/null +++ b/src/views/monitor/online/index.vue @@ -0,0 +1,122 @@ + + + + diff --git a/src/views/monitor/operlog/index.vue b/src/views/monitor/operlog/index.vue new file mode 100644 index 0000000..8e672f9 --- /dev/null +++ b/src/views/monitor/operlog/index.vue @@ -0,0 +1,306 @@ + + + + diff --git a/src/views/monitor/xxljob/index.vue b/src/views/monitor/xxljob/index.vue new file mode 100644 index 0000000..7167b48 --- /dev/null +++ b/src/views/monitor/xxljob/index.vue @@ -0,0 +1,15 @@ + + diff --git a/src/views/redirect.vue b/src/views/redirect.vue new file mode 100644 index 0000000..db4c1d6 --- /dev/null +++ b/src/views/redirect.vue @@ -0,0 +1,12 @@ + diff --git a/src/views/register.vue b/src/views/register.vue new file mode 100644 index 0000000..6fdd179 --- /dev/null +++ b/src/views/register.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/views/system/AircraftEquipmentModelManage/components/NodeRow.vue b/src/views/system/AircraftEquipmentModelManage/components/NodeRow.vue new file mode 100644 index 0000000..0c29b94 --- /dev/null +++ b/src/views/system/AircraftEquipmentModelManage/components/NodeRow.vue @@ -0,0 +1,47 @@ + + + diff --git a/src/views/system/AircraftEquipmentModelManage/components/tree.vue b/src/views/system/AircraftEquipmentModelManage/components/tree.vue new file mode 100644 index 0000000..9ae8d40 --- /dev/null +++ b/src/views/system/AircraftEquipmentModelManage/components/tree.vue @@ -0,0 +1,304 @@ + + + + diff --git a/src/views/system/AircraftEquipmentModelManage/index.vue b/src/views/system/AircraftEquipmentModelManage/index.vue new file mode 100644 index 0000000..9657a54 --- /dev/null +++ b/src/views/system/AircraftEquipmentModelManage/index.vue @@ -0,0 +1,1012 @@ + + + + + + diff --git a/src/views/system/Audit/index.vue b/src/views/system/Audit/index.vue new file mode 100644 index 0000000..8420779 --- /dev/null +++ b/src/views/system/Audit/index.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/src/views/system/DamageLimitValue/index.vue b/src/views/system/DamageLimitValue/index.vue new file mode 100644 index 0000000..5286698 --- /dev/null +++ b/src/views/system/DamageLimitValue/index.vue @@ -0,0 +1,291 @@ + + + + + diff --git a/src/views/system/Field/index.vue b/src/views/system/Field/index.vue new file mode 100644 index 0000000..7f45c83 --- /dev/null +++ b/src/views/system/Field/index.vue @@ -0,0 +1,315 @@ + + + + + diff --git a/src/views/system/ModelManageOfExplosiveWarhead/components/DrawSvg.vue b/src/views/system/ModelManageOfExplosiveWarhead/components/DrawSvg.vue new file mode 100644 index 0000000..27fa4fc --- /dev/null +++ b/src/views/system/ModelManageOfExplosiveWarhead/components/DrawSvg.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/views/system/ModelManageOfExplosiveWarhead/components/MoTree.vue b/src/views/system/ModelManageOfExplosiveWarhead/components/MoTree.vue new file mode 100644 index 0000000..69a41cf --- /dev/null +++ b/src/views/system/ModelManageOfExplosiveWarhead/components/MoTree.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/src/views/system/ModelManageOfExplosiveWarhead/index.vue b/src/views/system/ModelManageOfExplosiveWarhead/index.vue new file mode 100644 index 0000000..124e220 --- /dev/null +++ b/src/views/system/ModelManageOfExplosiveWarhead/index.vue @@ -0,0 +1,1986 @@ + + + + + diff --git a/src/views/system/Permission/index.vue b/src/views/system/Permission/index.vue new file mode 100644 index 0000000..61fd612 --- /dev/null +++ b/src/views/system/Permission/index.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/views/system/ThreeMembers/index.vue b/src/views/system/ThreeMembers/index.vue new file mode 100644 index 0000000..a39c55e --- /dev/null +++ b/src/views/system/ThreeMembers/index.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/views/system/config/index.vue b/src/views/system/config/index.vue new file mode 100644 index 0000000..984b7e2 --- /dev/null +++ b/src/views/system/config/index.vue @@ -0,0 +1,344 @@ + + + diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue new file mode 100644 index 0000000..e502b4e --- /dev/null +++ b/src/views/system/dept/index.vue @@ -0,0 +1,340 @@ + + + diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue new file mode 100644 index 0000000..c36cffc --- /dev/null +++ b/src/views/system/dict/data.vue @@ -0,0 +1,402 @@ + + + diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue new file mode 100644 index 0000000..2102df0 --- /dev/null +++ b/src/views/system/dict/index.vue @@ -0,0 +1,348 @@ + + + diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..a8971d1 --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,452 @@ + + + diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue new file mode 100644 index 0000000..19e25a0 --- /dev/null +++ b/src/views/system/notice/index.vue @@ -0,0 +1,312 @@ + + + \ No newline at end of file diff --git a/src/views/system/oss/config.vue b/src/views/system/oss/config.vue new file mode 100644 index 0000000..d045715 --- /dev/null +++ b/src/views/system/oss/config.vue @@ -0,0 +1,402 @@ + + + diff --git a/src/views/system/oss/index.vue b/src/views/system/oss/index.vue new file mode 100644 index 0000000..7600bf5 --- /dev/null +++ b/src/views/system/oss/index.vue @@ -0,0 +1,413 @@ + + + diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue new file mode 100644 index 0000000..444bf63 --- /dev/null +++ b/src/views/system/post/index.vue @@ -0,0 +1,309 @@ + + + diff --git a/src/views/system/role/authUser.vue b/src/views/system/role/authUser.vue new file mode 100644 index 0000000..147aa33 --- /dev/null +++ b/src/views/system/role/authUser.vue @@ -0,0 +1,199 @@ + + + \ No newline at end of file diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..8a8817e --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,607 @@ + + + + diff --git a/src/views/system/role/selectUser.vue b/src/views/system/role/selectUser.vue new file mode 100644 index 0000000..a612d71 --- /dev/null +++ b/src/views/system/role/selectUser.vue @@ -0,0 +1,138 @@ + + + diff --git a/src/views/system/user/authRole.vue b/src/views/system/user/authRole.vue new file mode 100644 index 0000000..7abe26a --- /dev/null +++ b/src/views/system/user/authRole.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..99944df --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,671 @@ + + + diff --git a/src/views/system/user/profile/index.vue b/src/views/system/user/profile/index.vue new file mode 100644 index 0000000..2cc7c2f --- /dev/null +++ b/src/views/system/user/profile/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/views/system/user/profile/resetPwd.vue b/src/views/system/user/profile/resetPwd.vue new file mode 100644 index 0000000..64e8f8c --- /dev/null +++ b/src/views/system/user/profile/resetPwd.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/views/system/user/profile/userAvatar.vue b/src/views/system/user/profile/userAvatar.vue new file mode 100644 index 0000000..18b23a4 --- /dev/null +++ b/src/views/system/user/profile/userAvatar.vue @@ -0,0 +1,190 @@ + + + + diff --git a/src/views/system/user/profile/userInfo.vue b/src/views/system/user/profile/userInfo.vue new file mode 100644 index 0000000..068b714 --- /dev/null +++ b/src/views/system/user/profile/userInfo.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/views/tool/build/CodeTypeDialog.vue b/src/views/tool/build/CodeTypeDialog.vue new file mode 100644 index 0000000..b5c2e2e --- /dev/null +++ b/src/views/tool/build/CodeTypeDialog.vue @@ -0,0 +1,106 @@ + + diff --git a/src/views/tool/build/DraggableItem.vue b/src/views/tool/build/DraggableItem.vue new file mode 100644 index 0000000..e881778 --- /dev/null +++ b/src/views/tool/build/DraggableItem.vue @@ -0,0 +1,100 @@ + diff --git a/src/views/tool/build/IconsDialog.vue b/src/views/tool/build/IconsDialog.vue new file mode 100644 index 0000000..958be50 --- /dev/null +++ b/src/views/tool/build/IconsDialog.vue @@ -0,0 +1,123 @@ + + + diff --git a/src/views/tool/build/RightPanel.vue b/src/views/tool/build/RightPanel.vue new file mode 100644 index 0000000..c2760eb --- /dev/null +++ b/src/views/tool/build/RightPanel.vue @@ -0,0 +1,946 @@ + + + + + diff --git a/src/views/tool/build/TreeNodeDialog.vue b/src/views/tool/build/TreeNodeDialog.vue new file mode 100644 index 0000000..fa7f0b2 --- /dev/null +++ b/src/views/tool/build/TreeNodeDialog.vue @@ -0,0 +1,149 @@ + + diff --git a/src/views/tool/build/index.vue b/src/views/tool/build/index.vue new file mode 100644 index 0000000..ed5506e --- /dev/null +++ b/src/views/tool/build/index.vue @@ -0,0 +1,770 @@ + + + + + diff --git a/src/views/tool/gen/basicInfoForm.vue b/src/views/tool/gen/basicInfoForm.vue new file mode 100644 index 0000000..7029529 --- /dev/null +++ b/src/views/tool/gen/basicInfoForm.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/views/tool/gen/editTable.vue b/src/views/tool/gen/editTable.vue new file mode 100644 index 0000000..f34327d --- /dev/null +++ b/src/views/tool/gen/editTable.vue @@ -0,0 +1,234 @@ + + + diff --git a/src/views/tool/gen/genInfoForm.vue b/src/views/tool/gen/genInfoForm.vue new file mode 100644 index 0000000..0a1de16 --- /dev/null +++ b/src/views/tool/gen/genInfoForm.vue @@ -0,0 +1,299 @@ + + + diff --git a/src/views/tool/gen/importTable.vue b/src/views/tool/gen/importTable.vue new file mode 100644 index 0000000..5542a94 --- /dev/null +++ b/src/views/tool/gen/importTable.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/views/tool/gen/index.vue b/src/views/tool/gen/index.vue new file mode 100644 index 0000000..66bd13f --- /dev/null +++ b/src/views/tool/gen/index.vue @@ -0,0 +1,348 @@ + + + diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..7cfc591 --- /dev/null +++ b/vue.config.js @@ -0,0 +1,132 @@ +'use strict' +const path = require('path') + +function resolve(dir) { + return path.join(__dirname, dir) +} + +const CompressionPlugin = require('compression-webpack-plugin') + +const name = process.env.VUE_APP_TITLE || '人机适配性高维数据管理平台' // 网页标题 + +const port = process.env.port || process.env.npm_config_port || 80 // 端口 + +// vue.config.js 配置说明 +//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions +// 这里只列一部分,具体配置参考文档 +module.exports = { + // 部署生产环境和开发环境下的URL。 + // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上 + // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 + publicPath: process.env.VUE_APP_CONTEXT_PATH, + // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist) + outputDir: "dist", + // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) + assetsDir: "static", + // 是否开启eslint保存检测,有效值:ture | false | 'error' + lintOnSave: process.env.NODE_ENV === "development", + // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 + productionSourceMap: false, + // webpack-dev-server 相关配置 + devServer: { + host: "0.0.0.0", + port: port, + open: true, + proxy: { + // detail: https://cli.vuejs.org/config/#devserver-proxy + [process.env.VUE_APP_BASE_API]: { + target: `http://192.168.1.15:8400`, + // target: `http://192.168.1.17:8081`, + changeOrigin: true, + pathRewrite: { + ["^" + process.env.VUE_APP_BASE_API]: "", + }, + }, + }, + disableHostCheck: true, + }, + css: { + loaderOptions: { + sass: { + sassOptions: { outputStyle: "expanded" }, + }, + }, + }, + configureWebpack: { + name: name, + resolve: { + alias: { + "@": resolve("src"), + }, + }, + plugins: [ + // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 + new CompressionPlugin({ + cache: false, // 不启用文件缓存 + test: /\.(js|css|html)?$/i, // 压缩文件格式 + filename: "[path].gz[query]", // 压缩后的文件名 + algorithm: "gzip", // 使用gzip压缩 + minRatio: 0.8, // 压缩率小于1才会压缩 + }), + ], + }, + chainWebpack(config) { + config.plugins.delete("preload"); // TODO: need test + config.plugins.delete("prefetch"); // TODO: need test + + // set svg-sprite-loader + config.module.rule("svg").exclude.add(resolve("src/assets/icons")).end(); + config.module + .rule("icons") + .test(/\.svg$/) + .include.add(resolve("src/assets/icons")) + .end() + .use("svg-sprite-loader") + .loader("svg-sprite-loader") + .options({ + symbolId: "icon-[name]", + }) + .end(); + + config.when(process.env.NODE_ENV !== "development", (config) => { + config + .plugin("ScriptExtHtmlWebpackPlugin") + .after("html") + .use("script-ext-html-webpack-plugin", [ + { + // `runtime` must same as runtimeChunk name. default is `runtime` + inline: /runtime\..*\.js$/, + }, + ]) + .end(); + config.optimization.splitChunks({ + chunks: "all", + cacheGroups: { + libs: { + name: "chunk-libs", + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: "initial", // only package third parties that are initially dependent + }, + elementUI: { + name: "chunk-elementUI", // split elementUI into a single package + priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app + test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm + }, + commons: { + name: "chunk-commons", + test: resolve("src/components"), // can customize your rules + minChunks: 3, // minimum common number + priority: 5, + reuseExistingChunk: true, + }, + }, + }); + config.optimization.runtimeChunk("single"), + { + from: path.resolve(__dirname, "./public/robots.txt"), //防爬虫文件 + to: "./", //到根目录下 + }; + }); + }, +};