chore: 基于vue-cli的standard代码规范格式化代码

This commit is contained in:
hankaibo
2021-08-18 14:51:51 +08:00
parent 5c155f5f11
commit 2211400ecc
171 changed files with 19195 additions and 19380 deletions

3
ruoyi-ui/.browserslistrc Normal file
View File

@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead

View File

@ -1,22 +1,22 @@
# 告诉EditorConfig插件这是根文件不用继续往上查找 # 告诉EditorConfig插件这是根文件不用继续往上查找
root = true root = true
# 匹配全部文件 # 匹配全部文件
[*] [*]
# 设置字符集 # 设置字符集
charset = utf-8 charset = utf-8
# 缩进风格可选space、tab # 缩进风格可选space、tab
indent_style = space indent_style = space
# 缩进的空格数 # 缩进的空格数
indent_size = 2 indent_size = 2
# 结尾换行符可选lf、cr、crlf # 结尾换行符可选lf、cr、crlf
end_of_line = lf end_of_line = lf
# 在文件结尾插入新行 # 在文件结尾插入新行
insert_final_newline = true insert_final_newline = true
# 删除一行中的前后空格 # 删除一行中的前后空格
trim_trailing_whitespace = true trim_trailing_whitespace = true
# 匹配md结尾的文件 # 匹配md结尾的文件
[*.md] [*.md]
insert_final_newline = false insert_final_newline = false
trim_trailing_whitespace = false trim_trailing_whitespace = false

View File

@ -1,11 +1,11 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
# 开发环境配置 # 开发环境配置
ENV = 'development' ENV = 'development'
# 若依管理系统/开发环境 # 若依管理系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -1,8 +1,8 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'
# 若依管理系统/生产环境 # 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'

View File

@ -1,10 +1,10 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
NODE_ENV = production NODE_ENV = production
# 测试环境配置 # 测试环境配置
ENV = 'staging' ENV = 'staging'
# 若依管理系统/测试环境 # 若依管理系统/测试环境
VUE_APP_BASE_API = '/stage-api' VUE_APP_BASE_API = '/stage-api'

View File

@ -1,10 +1 @@
# 忽略build目录下类型为js的文件的语法检查 vue.config.js
build/*.js
# 忽略src/assets目录下文件的语法检查
src/assets
# 忽略public目录下文件的语法检查
public
# 忽略当前目录下为js的文件的语法检查
*.js
# 忽略当前目录下为vue的文件的语法检查
*.vue

View File

@ -1,199 +1,21 @@
// ESlint 检查配置 module.exports = {
module.exports = { root: true,
root: true, env: {
parserOptions: { browser: true,
parser: 'babel-eslint', node: true,
sourceType: 'module' es6: true
}, },
env: { extends: [
browser: true, 'plugin:vue/essential',
node: true, '@vue/standard'
es6: true, ],
}, parserOptions: {
extends: ['plugin:vue/recommended', 'eslint:recommended'], parser: 'babel-eslint'
},
// add your custom rules here rules: {
//it is base on https://github.com/vuejs/eslint-config-vue // 允许props修改
rules: { 'vue/no-mutating-props': 'off',
"vue/max-attributes-per-line": [2, { 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
"singleline": 10, 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
"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']
}
}

46
ruoyi-ui/.gitignore vendored
View File

@ -1,23 +1,23 @@
.DS_Store .DS_Store
node_modules/ node_modules
dist/ /dist
npm-debug.log*
yarn-debug.log*
yarn-error.log* # local env files
**/*.log .env.local
.env.*.local
tests/**/coverage/
tests/e2e/reports # Log files
selenium-debug.log npm-debug.log*
yarn-debug.log*
# Editor directories and files yarn-error.log*
.idea pnpm-debug.log*
.vscode
*.suo # Editor directories and files
*.ntvs* .idea
*.njsproj .vscode
*.sln *.suo
*.local *.ntvs*
*.njsproj
package-lock.json *.sln
yarn.lock *.sw?

View File

@ -1,30 +1,30 @@
## 开发 ## 开发
```bash ```bash
# 克隆项目 # 克隆项目
git clone https://gitee.com/y_project/RuoYi-Vue git clone https://gitee.com/y_project/RuoYi-Vue
# 进入项目目录 # 进入项目目录
cd ruoyi-ui cd ruoyi-ui
# 安装依赖 # 安装依赖
npm install npm install
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 # 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org npm install --registry=https://registry.npm.taobao.org
# 启动服务 # 启动服务
npm run dev npm run dev
``` ```
浏览器访问 http://localhost:80 浏览器访问 http://localhost:80
## 发布 ## 发布
```bash ```bash
# 构建测试环境 # 构建测试环境
npm run build:stage npm run build:stage
# 构建生产环境 # 构建生产环境
npm run build:prod npm run build:prod
``` ```

View File

@ -1,13 +1,12 @@
module.exports = { module.exports = {
presets: [ presets: [
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app '@vue/cli-plugin-babel/preset'
'@vue/cli-plugin-babel/preset' ],
], env: {
'env': { development: {
'development': { // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// 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.
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages. plugins: ['dynamic-import-node']
'plugins': ['dynamic-import-node'] }
} }
} }
}

View File

@ -1,6 +1,6 @@
@echo off @echo off
echo. echo.
echo [<EFBFBD><EFBFBD>Ϣ] <20><><EFBFBD><EFBFBD>Web<65><62><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>dist<73>ļ<EFBFBD><C4BC><EFBFBD> echo [信息] 打包Web工程生成dist文件。
echo. echo.
%~d0 %~d0

View File

@ -1,12 +1,12 @@
@echo off @echo off
echo. echo.
echo [<EFBFBD><EFBFBD>Ϣ] <20><>װWeb<65><62><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>node_modules<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> echo [信息] 安装Web工程生成node_modules文件。
echo. echo.
%~d0 %~d0
cd %~dp0 cd %~dp0
cd .. cd ..
npm install --registry=https://registry.npm.taobao.org npm install --registry=https://registry.npm.taobao.org
pause pause

View File

@ -1,12 +1,12 @@
@echo off @echo off
echo. echo.
echo [<EFBFBD><EFBFBD>Ϣ] ʹ<><CAB9> Vue CLI <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Web <20><><EFBFBD>̡<EFBFBD> echo [信息] 使用 Vue CLI 命令运行 Web 工程。
echo. echo.
%~d0 %~d0
cd %~dp0 cd %~dp0
cd .. cd ..
npm run dev npm run dev
pause pause

View File

@ -1,35 +1,35 @@
const { run } = require('runjs') const { run } = require('runjs')
const chalk = require('chalk') const chalk = require('chalk')
const config = require('../vue.config.js') const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2) const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ') const args = rawArgv.join(' ')
if (process.env.npm_config_preview || rawArgv.includes('--preview')) { if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
const report = rawArgv.includes('--report') const report = rawArgv.includes('--report')
run(`vue-cli-service build ${args}`) run(`vue-cli-service build ${args}`)
const port = 9526 const port = 9526
const publicPath = config.publicPath const publicPath = config.publicPath
var connect = require('connect') var connect = require('connect')
var serveStatic = require('serve-static') var serveStatic = require('serve-static')
const app = connect() const app = connect()
app.use( app.use(
publicPath, publicPath,
serveStatic('./dist', { serveStatic('./dist', {
index: ['index.html', '/'] index: ['index.html', '/']
}) })
) )
app.listen(port, function () { app.listen(port, function () {
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
if (report) { if (report) {
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
} }
}) })
} else { } else {
run(`vue-cli-service build ${args}`) run(`vue-cli-service build ${args}`)
} }

View File

@ -1,88 +1,89 @@
{ {
"name": "ruoyi", "name": "ruoyi-template",
"version": "3.6.0", "version": "3.6.0",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src" "lint": "vue-cli-service lint"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
"pre-commit": "lint-staged" "pre-commit": "lint-staged"
} }
}, },
"lint-staged": { "lint-staged": {
"src/**/*.{js,vue}": [ "src/**/*.{js,vue}": [
"eslint --fix", "eslint --fix",
"git add" "git add"
] ]
}, },
"keywords": [ "keywords": [
"vue", "vue",
"admin", "admin",
"dashboard", "dashboard",
"element-ui", "element-ui",
"boilerplate", "boilerplate",
"admin-template", "admin-template",
"management-system" "management-system"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitee.com/y_project/RuoYi-Vue.git" "url": "https://gitee.com/y_project/RuoYi-Vue.git"
}, },
"dependencies": { "dependencies": {
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.21.0", "axios": "0.21.0",
"clipboard": "2.0.6", "clipboard": "2.0.6",
"core-js": "3.8.1", "core-js": "3.8.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"element-ui": "2.15.5", "element-ui": "2.15.5",
"file-saver": "2.0.4", "file-saver": "2.0.4",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "2.2.1", "js-cookie": "2.2.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "1.3.7", "quill": "1.3.7",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "^2.4.0", "vue-meta": "^2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.6", "@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6", "@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6", "@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0", "@vue/eslint-config-standard": "^6.1.0",
"chalk": "4.1.0", "babel-eslint": "10.1.0",
"connect": "3.6.6", "chalk": "4.1.0",
"eslint": "7.15.0", "connect": "3.6.6",
"eslint-plugin-vue": "7.2.0", "eslint": "7.15.0",
"lint-staged": "10.5.3", "eslint-plugin-import": "^2.24.0",
"runjs": "4.4.2", "eslint-plugin-node": "^11.1.0",
"sass": "1.32.0", "eslint-plugin-promise": "^5.1.0",
"sass-loader": "10.1.0", "eslint-plugin-standard": "^5.0.0",
"script-ext-html-webpack-plugin": "2.1.5", "eslint-plugin-vue": "7.2.0",
"svg-sprite-loader": "5.1.1", "lint-staged": "10.5.3",
"vue-template-compiler": "2.6.12" "runjs": "4.4.2",
}, "sass": "1.32.0",
"engines": { "sass-loader": "10.1.0",
"node": ">=8.9", "script-ext-html-webpack-plugin": "2.1.5",
"npm": ">= 3.0.0" "svg-sprite-loader": "5.1.1",
}, "vue-template-compiler": "2.6.12"
"browserslist": [ },
"> 1%", "engines": {
"last 2 versions" "node": ">=8.9",
] "npm": ">= 3.0.0"
} }
}

View File

@ -43,4 +43,4 @@
</ul> </ul>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -1,208 +1,208 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title> <title><%= webpackConfig.name %></title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style> <style>
html, html,
body, body,
#app { #app {
height: 100%; height: 100%;
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
.chromeframe { .chromeframe {
margin: 0.2em 0; margin: 0.2em 0;
background: #ccc; background: #ccc;
color: #000; color: #000;
padding: 0.2em 0; padding: 0.2em 0;
} }
#loader-wrapper { #loader-wrapper {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 999999; z-index: 999999;
} }
#loader { #loader {
display: block; display: block;
position: relative; position: relative;
left: 50%; left: 50%;
top: 50%; top: 50%;
width: 150px; width: 150px;
height: 150px; height: 150px;
margin: -75px 0 0 -75px; margin: -75px 0 0 -75px;
border-radius: 50%; border-radius: 50%;
border: 3px solid transparent; border: 3px solid transparent;
border-top-color: #FFF; border-top-color: #FFF;
-webkit-animation: spin 2s linear infinite; -webkit-animation: spin 2s linear infinite;
-ms-animation: spin 2s linear infinite; -ms-animation: spin 2s linear infinite;
-moz-animation: spin 2s linear infinite; -moz-animation: spin 2s linear infinite;
-o-animation: spin 2s linear infinite; -o-animation: spin 2s linear infinite;
animation: spin 2s linear infinite; animation: spin 2s linear infinite;
z-index: 1001; z-index: 1001;
} }
#loader:before { #loader:before {
content: ""; content: "";
position: absolute; position: absolute;
top: 5px; top: 5px;
left: 5px; left: 5px;
right: 5px; right: 5px;
bottom: 5px; bottom: 5px;
border-radius: 50%; border-radius: 50%;
border: 3px solid transparent; border: 3px solid transparent;
border-top-color: #FFF; border-top-color: #FFF;
-webkit-animation: spin 3s linear infinite; -webkit-animation: spin 3s linear infinite;
-moz-animation: spin 3s linear infinite; -moz-animation: spin 3s linear infinite;
-o-animation: spin 3s linear infinite; -o-animation: spin 3s linear infinite;
-ms-animation: spin 3s linear infinite; -ms-animation: spin 3s linear infinite;
animation: spin 3s linear infinite; animation: spin 3s linear infinite;
} }
#loader:after { #loader:after {
content: ""; content: "";
position: absolute; position: absolute;
top: 15px; top: 15px;
left: 15px; left: 15px;
right: 15px; right: 15px;
bottom: 15px; bottom: 15px;
border-radius: 50%; border-radius: 50%;
border: 3px solid transparent; border: 3px solid transparent;
border-top-color: #FFF; border-top-color: #FFF;
-moz-animation: spin 1.5s linear infinite; -moz-animation: spin 1.5s linear infinite;
-o-animation: spin 1.5s linear infinite; -o-animation: spin 1.5s linear infinite;
-ms-animation: spin 1.5s linear infinite; -ms-animation: spin 1.5s linear infinite;
-webkit-animation: spin 1.5s linear infinite; -webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite; animation: spin 1.5s linear infinite;
} }
@-webkit-keyframes spin { @-webkit-keyframes spin {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg); -ms-transform: rotate(0deg);
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg); -ms-transform: rotate(360deg);
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
@keyframes spin { @keyframes spin {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg); -ms-transform: rotate(0deg);
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg); -ms-transform: rotate(360deg);
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
#loader-wrapper .loader-section { #loader-wrapper .loader-section {
position: fixed; position: fixed;
top: 0; top: 0;
width: 51%; width: 51%;
height: 100%; height: 100%;
background: #7171C6; background: #7171C6;
z-index: 1000; z-index: 1000;
-webkit-transform: translateX(0); -webkit-transform: translateX(0);
-ms-transform: translateX(0); -ms-transform: translateX(0);
transform: translateX(0); transform: translateX(0);
} }
#loader-wrapper .loader-section.section-left { #loader-wrapper .loader-section.section-left {
left: 0; left: 0;
} }
#loader-wrapper .loader-section.section-right { #loader-wrapper .loader-section.section-right {
right: 0; right: 0;
} }
.loaded #loader-wrapper .loader-section.section-left { .loaded #loader-wrapper .loader-section.section-left {
-webkit-transform: translateX(-100%); -webkit-transform: translateX(-100%);
-ms-transform: translateX(-100%); -ms-transform: translateX(-100%);
transform: translateX(-100%); transform: translateX(-100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
} }
.loaded #loader-wrapper .loader-section.section-right { .loaded #loader-wrapper .loader-section.section-right {
-webkit-transform: translateX(100%); -webkit-transform: translateX(100%);
-ms-transform: translateX(100%); -ms-transform: translateX(100%);
transform: translateX(100%); transform: translateX(100%);
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
} }
.loaded #loader { .loaded #loader {
opacity: 0; opacity: 0;
-webkit-transition: all 0.3s ease-out; -webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out; transition: all 0.3s ease-out;
} }
.loaded #loader-wrapper { .loaded #loader-wrapper {
visibility: hidden; visibility: hidden;
-webkit-transform: translateY(-100%); -webkit-transform: translateY(-100%);
-ms-transform: translateY(-100%); -ms-transform: translateY(-100%);
transform: translateY(-100%); transform: translateY(-100%);
-webkit-transition: all 0.3s 1s ease-out; -webkit-transition: all 0.3s 1s ease-out;
transition: all 0.3s 1s ease-out; transition: all 0.3s 1s ease-out;
} }
.no-js #loader-wrapper { .no-js #loader-wrapper {
display: none; display: none;
} }
.no-js h1 { .no-js h1 {
color: #222222; color: #222222;
} }
#loader-wrapper .load_title { #loader-wrapper .load_title {
font-family: 'Open Sans'; font-family: 'Open Sans';
color: #FFF; color: #FFF;
font-size: 19px; font-size: 19px;
width: 100%; width: 100%;
text-align: center; text-align: center;
z-index: 9999999999999; z-index: 9999999999999;
position: absolute; position: absolute;
top: 60%; top: 60%;
opacity: 1; opacity: 1;
line-height: 30px; line-height: 30px;
} }
#loader-wrapper .load_title span { #loader-wrapper .load_title span {
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
font-size: 13px; font-size: 13px;
color: #FFF; color: #FFF;
opacity: 0.5; opacity: 0.5;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="app"> <div id="app">
<div id="loader-wrapper"> <div id="loader-wrapper">
<div id="loader"></div> <div id="loader"></div>
<div class="loader-section section-left"></div> <div class="loader-section section-left"></div>
<div class="loader-section section-right"></div> <div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div> <div class="load_title">正在加载系统资源,请耐心等待</div>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -1,2 +1,2 @@
User-agent: * User-agent: *
Disallow: / Disallow: /

View File

@ -1,19 +1,19 @@
<template> <template>
<div id="app"> <div id="app">
<router-view /> <router-view />
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'App', name: 'App',
metaInfo() { metaInfo () {
return { return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title, title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
titleTemplate: title => { titleTemplate: title => {
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
} }
} }
} }
} }
</script> </script>

View File

@ -1,52 +1,52 @@
import request from '@/utils/request' import request from '@/utils/request'
// 登录方法 // 登录方法
export function login(username, password, code, uuid) { export function login (username, password, code, uuid) {
const data = { const data = {
username, username,
password, password,
code, code,
uuid uuid
} }
return request({ return request({
url: '/login', url: '/login',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 注册方法 // 注册方法
export function register(data) { export function register (data) {
return request({ return request({
url: '/register', url: '/register',
headers: { headers: {
isToken: false isToken: false
}, },
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 获取用户详细信息 // 获取用户详细信息
export function getInfo() { export function getInfo () {
return request({ return request({
url: '/getInfo', url: '/getInfo',
method: 'get' method: 'get'
}) })
} }
// 退出方法 // 退出方法
export function logout() { export function logout () {
return request({ return request({
url: '/logout', url: '/logout',
method: 'post' method: 'post'
}) })
} }
// 获取验证码 // 获取验证码
export function getCodeImg() { export function getCodeImg () {
return request({ return request({
url: '/captchaImage', url: '/captchaImage',
method: 'get' method: 'get'
}) })
} }

View File

@ -1,9 +1,9 @@
import request from '@/utils/request' import request from '@/utils/request'
// 获取路由 // 获取路由
export const getRouters = () => { export const getRouters = () => {
return request({ return request({
url: '/getRouters', url: '/getRouters',
method: 'get' method: 'get'
}) })
} }

View File

@ -1,7 +1,7 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询缓存详细 // 查询缓存详细
export function getCache() { export function getCache () {
return request({ return request({
url: '/monitor/cache', url: '/monitor/cache',
method: 'get' method: 'get'

View File

@ -1,7 +1,7 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询定时任务调度列表 // 查询定时任务调度列表
export function listJob(query) { export function listJob (query) {
return request({ return request({
url: '/monitor/job/list', url: '/monitor/job/list',
method: 'get', method: 'get',
@ -10,7 +10,7 @@ export function listJob(query) {
} }
// 查询定时任务调度详细 // 查询定时任务调度详细
export function getJob(jobId) { export function getJob (jobId) {
return request({ return request({
url: '/monitor/job/' + jobId, url: '/monitor/job/' + jobId,
method: 'get' method: 'get'
@ -18,7 +18,7 @@ export function getJob(jobId) {
} }
// 新增定时任务调度 // 新增定时任务调度
export function addJob(data) { export function addJob (data) {
return request({ return request({
url: '/monitor/job', url: '/monitor/job',
method: 'post', method: 'post',
@ -27,7 +27,7 @@ export function addJob(data) {
} }
// 修改定时任务调度 // 修改定时任务调度
export function updateJob(data) { export function updateJob (data) {
return request({ return request({
url: '/monitor/job', url: '/monitor/job',
method: 'put', method: 'put',
@ -36,7 +36,7 @@ export function updateJob(data) {
} }
// 删除定时任务调度 // 删除定时任务调度
export function delJob(jobId) { export function delJob (jobId) {
return request({ return request({
url: '/monitor/job/' + jobId, url: '/monitor/job/' + jobId,
method: 'delete' method: 'delete'
@ -44,7 +44,7 @@ export function delJob(jobId) {
} }
// 导出定时任务调度 // 导出定时任务调度
export function exportJob(query) { export function exportJob (query) {
return request({ return request({
url: '/monitor/job/export', url: '/monitor/job/export',
method: 'get', method: 'get',
@ -53,7 +53,7 @@ export function exportJob(query) {
} }
// 任务状态修改 // 任务状态修改
export function changeJobStatus(jobId, status) { export function changeJobStatus (jobId, status) {
const data = { const data = {
jobId, jobId,
status status
@ -65,9 +65,8 @@ export function changeJobStatus(jobId, status) {
}) })
} }
// 定时任务立即执行一次 // 定时任务立即执行一次
export function runJob(jobId, jobGroup) { export function runJob (jobId, jobGroup) {
const data = { const data = {
jobId, jobId,
jobGroup jobGroup
@ -77,4 +76,4 @@ export function runJob(jobId, jobGroup) {
method: 'put', method: 'put',
data: data data: data
}) })
} }

View File

@ -1,7 +1,7 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询调度日志列表 // 查询调度日志列表
export function listJobLog(query) { export function listJobLog (query) {
return request({ return request({
url: '/monitor/jobLog/list', url: '/monitor/jobLog/list',
method: 'get', method: 'get',
@ -10,7 +10,7 @@ export function listJobLog(query) {
} }
// 删除调度日志 // 删除调度日志
export function delJobLog(jobLogId) { export function delJobLog (jobLogId) {
return request({ return request({
url: '/monitor/jobLog/' + jobLogId, url: '/monitor/jobLog/' + jobLogId,
method: 'delete' method: 'delete'
@ -18,7 +18,7 @@ export function delJobLog(jobLogId) {
} }
// 清空调度日志 // 清空调度日志
export function cleanJobLog() { export function cleanJobLog () {
return request({ return request({
url: '/monitor/jobLog/clean', url: '/monitor/jobLog/clean',
method: 'delete' method: 'delete'
@ -26,10 +26,10 @@ export function cleanJobLog() {
} }
// 导出调度日志 // 导出调度日志
export function exportJobLog(query) { export function exportJobLog (query) {
return request({ return request({
url: '/monitor/jobLog/export', url: '/monitor/jobLog/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,35 +1,35 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询登录日志列表 // 查询登录日志列表
export function list(query) { export function list (query) {
return request({ return request({
url: '/monitor/logininfor/list', url: '/monitor/logininfor/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 删除登录日志 // 删除登录日志
export function delLogininfor(infoId) { export function delLogininfor (infoId) {
return request({ return request({
url: '/monitor/logininfor/' + infoId, url: '/monitor/logininfor/' + infoId,
method: 'delete' method: 'delete'
}) })
} }
// 清空登录日志 // 清空登录日志
export function cleanLogininfor() { export function cleanLogininfor () {
return request({ return request({
url: '/monitor/logininfor/clean', url: '/monitor/logininfor/clean',
method: 'delete' method: 'delete'
}) })
} }
// 导出登录日志 // 导出登录日志
export function exportLogininfor(query) { export function exportLogininfor (query) {
return request({ return request({
url: '/monitor/logininfor/export', url: '/monitor/logininfor/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,18 +1,18 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询在线用户列表 // 查询在线用户列表
export function list(query) { export function list (query) {
return request({ return request({
url: '/monitor/online/list', url: '/monitor/online/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 强退用户 // 强退用户
export function forceLogout(tokenId) { export function forceLogout (tokenId) {
return request({ return request({
url: '/monitor/online/' + tokenId, url: '/monitor/online/' + tokenId,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,35 +1,35 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询操作日志列表 // 查询操作日志列表
export function list(query) { export function list (query) {
return request({ return request({
url: '/monitor/operlog/list', url: '/monitor/operlog/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 删除操作日志 // 删除操作日志
export function delOperlog(operId) { export function delOperlog (operId) {
return request({ return request({
url: '/monitor/operlog/' + operId, url: '/monitor/operlog/' + operId,
method: 'delete' method: 'delete'
}) })
} }
// 清空操作日志 // 清空操作日志
export function cleanOperlog() { export function cleanOperlog () {
return request({ return request({
url: '/monitor/operlog/clean', url: '/monitor/operlog/clean',
method: 'delete' method: 'delete'
}) })
} }
// 导出操作日志 // 导出操作日志
export function exportOperlog(query) { export function exportOperlog (query) {
return request({ return request({
url: '/monitor/operlog/export', url: '/monitor/operlog/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,9 +1,9 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询服务器详细 // 查询服务器详细
export function getServer() { export function getServer () {
return request({ return request({
url: '/monitor/server', url: '/monitor/server',
method: 'get' method: 'get'
}) })
} }

View File

@ -1,69 +1,69 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询参数列表 // 查询参数列表
export function listConfig(query) { export function listConfig (query) {
return request({ return request({
url: '/system/config/list', url: '/system/config/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询参数详细 // 查询参数详细
export function getConfig(configId) { export function getConfig (configId) {
return request({ return request({
url: '/system/config/' + configId, url: '/system/config/' + configId,
method: 'get' method: 'get'
}) })
} }
// 根据参数键名查询参数值 // 根据参数键名查询参数值
export function getConfigKey(configKey) { export function getConfigKey (configKey) {
return request({ return request({
url: '/system/config/configKey/' + configKey, url: '/system/config/configKey/' + configKey,
method: 'get' method: 'get'
}) })
} }
// 新增参数配置 // 新增参数配置
export function addConfig(data) { export function addConfig (data) {
return request({ return request({
url: '/system/config', url: '/system/config',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改参数配置 // 修改参数配置
export function updateConfig(data) { export function updateConfig (data) {
return request({ return request({
url: '/system/config', url: '/system/config',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除参数配置 // 删除参数配置
export function delConfig(configId) { export function delConfig (configId) {
return request({ return request({
url: '/system/config/' + configId, url: '/system/config/' + configId,
method: 'delete' method: 'delete'
}) })
} }
// 刷新参数缓存 // 刷新参数缓存
export function refreshCache() { export function refreshCache () {
return request({ return request({
url: '/system/config/refreshCache', url: '/system/config/refreshCache',
method: 'delete' method: 'delete'
}) })
} }
// 导出参数 // 导出参数
export function exportConfig(query) { export function exportConfig (query) {
return request({ return request({
url: '/system/config/export', url: '/system/config/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,68 +1,68 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询部门列表 // 查询部门列表
export function listDept(query) { export function listDept (query) {
return request({ return request({
url: '/system/dept/list', url: '/system/dept/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询部门列表(排除节点) // 查询部门列表(排除节点)
export function listDeptExcludeChild(deptId) { export function listDeptExcludeChild (deptId) {
return request({ return request({
url: '/system/dept/list/exclude/' + deptId, url: '/system/dept/list/exclude/' + deptId,
method: 'get' method: 'get'
}) })
} }
// 查询部门详细 // 查询部门详细
export function getDept(deptId) { export function getDept (deptId) {
return request({ return request({
url: '/system/dept/' + deptId, url: '/system/dept/' + deptId,
method: 'get' method: 'get'
}) })
} }
// 查询部门下拉树结构 // 查询部门下拉树结构
export function treeselect() { export function treeselect () {
return request({ return request({
url: '/system/dept/treeselect', url: '/system/dept/treeselect',
method: 'get' method: 'get'
}) })
} }
// 根据角色ID查询部门树结构 // 根据角色ID查询部门树结构
export function roleDeptTreeselect(roleId) { export function roleDeptTreeselect (roleId) {
return request({ return request({
url: '/system/dept/roleDeptTreeselect/' + roleId, url: '/system/dept/roleDeptTreeselect/' + roleId,
method: 'get' method: 'get'
}) })
} }
// 新增部门 // 新增部门
export function addDept(data) { export function addDept (data) {
return request({ return request({
url: '/system/dept', url: '/system/dept',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改部门 // 修改部门
export function updateDept(data) { export function updateDept (data) {
return request({ return request({
url: '/system/dept', url: '/system/dept',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除部门 // 删除部门
export function delDept(deptId) { export function delDept (deptId) {
return request({ return request({
url: '/system/dept/' + deptId, url: '/system/dept/' + deptId,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,61 +1,61 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询字典数据列表 // 查询字典数据列表
export function listData(query) { export function listData (query) {
return request({ return request({
url: '/system/dict/data/list', url: '/system/dict/data/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询字典数据详细 // 查询字典数据详细
export function getData(dictCode) { export function getData (dictCode) {
return request({ return request({
url: '/system/dict/data/' + dictCode, url: '/system/dict/data/' + dictCode,
method: 'get' method: 'get'
}) })
} }
// 根据字典类型查询字典数据信息 // 根据字典类型查询字典数据信息
export function getDicts(dictType) { export function getDicts (dictType) {
return request({ return request({
url: '/system/dict/data/type/' + dictType, url: '/system/dict/data/type/' + dictType,
method: 'get' method: 'get'
}) })
} }
// 新增字典数据 // 新增字典数据
export function addData(data) { export function addData (data) {
return request({ return request({
url: '/system/dict/data', url: '/system/dict/data',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改字典数据 // 修改字典数据
export function updateData(data) { export function updateData (data) {
return request({ return request({
url: '/system/dict/data', url: '/system/dict/data',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除字典数据 // 删除字典数据
export function delData(dictCode) { export function delData (dictCode) {
return request({ return request({
url: '/system/dict/data/' + dictCode, url: '/system/dict/data/' + dictCode,
method: 'delete' method: 'delete'
}) })
} }
// 导出字典数据 // 导出字典数据
export function exportData(query) { export function exportData (query) {
return request({ return request({
url: '/system/dict/data/export', url: '/system/dict/data/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,69 +1,69 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询字典类型列表 // 查询字典类型列表
export function listType(query) { export function listType (query) {
return request({ return request({
url: '/system/dict/type/list', url: '/system/dict/type/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询字典类型详细 // 查询字典类型详细
export function getType(dictId) { export function getType (dictId) {
return request({ return request({
url: '/system/dict/type/' + dictId, url: '/system/dict/type/' + dictId,
method: 'get' method: 'get'
}) })
} }
// 新增字典类型 // 新增字典类型
export function addType(data) { export function addType (data) {
return request({ return request({
url: '/system/dict/type', url: '/system/dict/type',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改字典类型 // 修改字典类型
export function updateType(data) { export function updateType (data) {
return request({ return request({
url: '/system/dict/type', url: '/system/dict/type',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除字典类型 // 删除字典类型
export function delType(dictId) { export function delType (dictId) {
return request({ return request({
url: '/system/dict/type/' + dictId, url: '/system/dict/type/' + dictId,
method: 'delete' method: 'delete'
}) })
} }
// 刷新字典缓存 // 刷新字典缓存
export function refreshCache() { export function refreshCache () {
return request({ return request({
url: '/system/dict/type/refreshCache', url: '/system/dict/type/refreshCache',
method: 'delete' method: 'delete'
}) })
} }
// 导出字典类型 // 导出字典类型
export function exportType(query) { export function exportType (query) {
return request({ return request({
url: '/system/dict/type/export', url: '/system/dict/type/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 获取字典选择框列表 // 获取字典选择框列表
export function optionselect() { export function optionselect () {
return request({ return request({
url: '/system/dict/type/optionselect', url: '/system/dict/type/optionselect',
method: 'get' method: 'get'
}) })
} }

View File

@ -1,60 +1,60 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询菜单列表 // 查询菜单列表
export function listMenu(query) { export function listMenu (query) {
return request({ return request({
url: '/system/menu/list', url: '/system/menu/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询菜单详细 // 查询菜单详细
export function getMenu(menuId) { export function getMenu (menuId) {
return request({ return request({
url: '/system/menu/' + menuId, url: '/system/menu/' + menuId,
method: 'get' method: 'get'
}) })
} }
// 查询菜单下拉树结构 // 查询菜单下拉树结构
export function treeselect() { export function treeselect () {
return request({ return request({
url: '/system/menu/treeselect', url: '/system/menu/treeselect',
method: 'get' method: 'get'
}) })
} }
// 根据角色ID查询菜单下拉树结构 // 根据角色ID查询菜单下拉树结构
export function roleMenuTreeselect(roleId) { export function roleMenuTreeselect (roleId) {
return request({ return request({
url: '/system/menu/roleMenuTreeselect/' + roleId, url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get' method: 'get'
}) })
} }
// 新增菜单 // 新增菜单
export function addMenu(data) { export function addMenu (data) {
return request({ return request({
url: '/system/menu', url: '/system/menu',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改菜单 // 修改菜单
export function updateMenu(data) { export function updateMenu (data) {
return request({ return request({
url: '/system/menu', url: '/system/menu',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除菜单 // 删除菜单
export function delMenu(menuId) { export function delMenu (menuId) {
return request({ return request({
url: '/system/menu/' + menuId, url: '/system/menu/' + menuId,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,44 +1,44 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询公告列表 // 查询公告列表
export function listNotice(query) { export function listNotice (query) {
return request({ return request({
url: '/system/notice/list', url: '/system/notice/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询公告详细 // 查询公告详细
export function getNotice(noticeId) { export function getNotice (noticeId) {
return request({ return request({
url: '/system/notice/' + noticeId, url: '/system/notice/' + noticeId,
method: 'get' method: 'get'
}) })
} }
// 新增公告 // 新增公告
export function addNotice(data) { export function addNotice (data) {
return request({ return request({
url: '/system/notice', url: '/system/notice',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改公告 // 修改公告
export function updateNotice(data) { export function updateNotice (data) {
return request({ return request({
url: '/system/notice', url: '/system/notice',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除公告 // 删除公告
export function delNotice(noticeId) { export function delNotice (noticeId) {
return request({ return request({
url: '/system/notice/' + noticeId, url: '/system/notice/' + noticeId,
method: 'delete' method: 'delete'
}) })
} }

View File

@ -1,53 +1,53 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询岗位列表 // 查询岗位列表
export function listPost(query) { export function listPost (query) {
return request({ return request({
url: '/system/post/list', url: '/system/post/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询岗位详细 // 查询岗位详细
export function getPost(postId) { export function getPost (postId) {
return request({ return request({
url: '/system/post/' + postId, url: '/system/post/' + postId,
method: 'get' method: 'get'
}) })
} }
// 新增岗位 // 新增岗位
export function addPost(data) { export function addPost (data) {
return request({ return request({
url: '/system/post', url: '/system/post',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改岗位 // 修改岗位
export function updatePost(data) { export function updatePost (data) {
return request({ return request({
url: '/system/post', url: '/system/post',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除岗位 // 删除岗位
export function delPost(postId) { export function delPost (postId) {
return request({ return request({
url: '/system/post/' + postId, url: '/system/post/' + postId,
method: 'delete' method: 'delete'
}) })
} }
// 导出岗位 // 导出岗位
export function exportPost(query) { export function exportPost (query) {
return request({ return request({
url: '/system/post/export', url: '/system/post/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }

View File

@ -1,120 +1,120 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询角色列表 // 查询角色列表
export function listRole(query) { export function listRole (query) {
return request({ return request({
url: '/system/role/list', url: '/system/role/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询角色详细 // 查询角色详细
export function getRole(roleId) { export function getRole (roleId) {
return request({ return request({
url: '/system/role/' + roleId, url: '/system/role/' + roleId,
method: 'get' method: 'get'
}) })
} }
// 新增角色 // 新增角色
export function addRole(data) { export function addRole (data) {
return request({ return request({
url: '/system/role', url: '/system/role',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改角色 // 修改角色
export function updateRole(data) { export function updateRole (data) {
return request({ return request({
url: '/system/role', url: '/system/role',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 角色数据权限 // 角色数据权限
export function dataScope(data) { export function dataScope (data) {
return request({ return request({
url: '/system/role/dataScope', url: '/system/role/dataScope',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 角色状态修改 // 角色状态修改
export function changeRoleStatus(roleId, status) { export function changeRoleStatus (roleId, status) {
const data = { const data = {
roleId, roleId,
status status
} }
return request({ return request({
url: '/system/role/changeStatus', url: '/system/role/changeStatus',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除角色 // 删除角色
export function delRole(roleId) { export function delRole (roleId) {
return request({ return request({
url: '/system/role/' + roleId, url: '/system/role/' + roleId,
method: 'delete' method: 'delete'
}) })
} }
// 导出角色 // 导出角色
export function exportRole(query) { export function exportRole (query) {
return request({ return request({
url: '/system/role/export', url: '/system/role/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询角色已授权用户列表 // 查询角色已授权用户列表
export function allocatedUserList(query) { export function allocatedUserList (query) {
return request({ return request({
url: '/system/role/authUser/allocatedList', url: '/system/role/authUser/allocatedList',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询角色未授权用户列表 // 查询角色未授权用户列表
export function unallocatedUserList(query) { export function unallocatedUserList (query) {
return request({ return request({
url: '/system/role/authUser/unallocatedList', url: '/system/role/authUser/unallocatedList',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 取消用户授权角色 // 取消用户授权角色
export function authUserCancel(data) { export function authUserCancel (data) {
return request({ return request({
url: '/system/role/authUser/cancel', url: '/system/role/authUser/cancel',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 批量取消用户授权角色 // 批量取消用户授权角色
export function authUserCancelAll(data) { export function authUserCancelAll (data) {
return request({ return request({
url: '/system/role/authUser/cancelAll', url: '/system/role/authUser/cancelAll',
method: 'put', method: 'put',
params: data params: data
}) })
} }
// 授权用户选择 // 授权用户选择
export function authUserSelectAll(data) { export function authUserSelectAll (data) {
return request({ return request({
url: '/system/role/authUser/selectAll', url: '/system/role/authUser/selectAll',
method: 'put', method: 'put',
params: data params: data
}) })
} }

View File

@ -1,144 +1,144 @@
import request from '@/utils/request' import request from '@/utils/request'
import { praseStrEmpty } from "@/utils/ruoyi"; import { praseStrEmpty } from '@/utils/ruoyi'
// 查询用户列表 // 查询用户列表
export function listUser(query) { export function listUser (query) {
return request({ return request({
url: '/system/user/list', url: '/system/user/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询用户详细 // 查询用户详细
export function getUser(userId) { export function getUser (userId) {
return request({ return request({
url: '/system/user/' + praseStrEmpty(userId), url: '/system/user/' + praseStrEmpty(userId),
method: 'get' method: 'get'
}) })
} }
// 新增用户 // 新增用户
export function addUser(data) { export function addUser (data) {
return request({ return request({
url: '/system/user', url: '/system/user',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 修改用户 // 修改用户
export function updateUser(data) { export function updateUser (data) {
return request({ return request({
url: '/system/user', url: '/system/user',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 删除用户 // 删除用户
export function delUser(userId) { export function delUser (userId) {
return request({ return request({
url: '/system/user/' + userId, url: '/system/user/' + userId,
method: 'delete' method: 'delete'
}) })
} }
// 导出用户 // 导出用户
export function exportUser(query) { export function exportUser (query) {
return request({ return request({
url: '/system/user/export', url: '/system/user/export',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 用户密码重置 // 用户密码重置
export function resetUserPwd(userId, password) { export function resetUserPwd (userId, password) {
const data = { const data = {
userId, userId,
password password
} }
return request({ return request({
url: '/system/user/resetPwd', url: '/system/user/resetPwd',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 用户状态修改 // 用户状态修改
export function changeUserStatus(userId, status) { export function changeUserStatus (userId, status) {
const data = { const data = {
userId, userId,
status status
} }
return request({ return request({
url: '/system/user/changeStatus', url: '/system/user/changeStatus',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 查询用户个人信息 // 查询用户个人信息
export function getUserProfile() { export function getUserProfile () {
return request({ return request({
url: '/system/user/profile', url: '/system/user/profile',
method: 'get' method: 'get'
}) })
} }
// 修改用户个人信息 // 修改用户个人信息
export function updateUserProfile(data) { export function updateUserProfile (data) {
return request({ return request({
url: '/system/user/profile', url: '/system/user/profile',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 用户密码重置 // 用户密码重置
export function updateUserPwd(oldPassword, newPassword) { export function updateUserPwd (oldPassword, newPassword) {
const data = { const data = {
oldPassword, oldPassword,
newPassword newPassword
} }
return request({ return request({
url: '/system/user/profile/updatePwd', url: '/system/user/profile/updatePwd',
method: 'put', method: 'put',
params: data params: data
}) })
} }
// 用户头像上传 // 用户头像上传
export function uploadAvatar(data) { export function uploadAvatar (data) {
return request({ return request({
url: '/system/user/profile/avatar', url: '/system/user/profile/avatar',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 下载用户导入模板 // 下载用户导入模板
export function importTemplate() { export function importTemplate () {
return request({ return request({
url: '/system/user/importTemplate', url: '/system/user/importTemplate',
method: 'get' method: 'get'
}) })
} }
// 查询授权角色 // 查询授权角色
export function getAuthRole(userId) { export function getAuthRole (userId) {
return request({ return request({
url: '/system/user/authRole/' + userId, url: '/system/user/authRole/' + userId,
method: 'get' method: 'get'
}) })
} }
// 保存授权角色 // 保存授权角色
export function updateAuthRole(data) { export function updateAuthRole (data) {
return request({ return request({
url: '/system/user/authRole', url: '/system/user/authRole',
method: 'put', method: 'put',
params: data params: data
}) })
} }

View File

@ -1,76 +1,76 @@
import request from '@/utils/request' import request from '@/utils/request'
// 查询生成表数据 // 查询生成表数据
export function listTable(query) { export function listTable (query) {
return request({ return request({
url: '/tool/gen/list', url: '/tool/gen/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询db数据库列表 // 查询db数据库列表
export function listDbTable(query) { export function listDbTable (query) {
return request({ return request({
url: '/tool/gen/db/list', url: '/tool/gen/db/list',
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 查询表详细信息 // 查询表详细信息
export function getGenTable(tableId) { export function getGenTable (tableId) {
return request({ return request({
url: '/tool/gen/' + tableId, url: '/tool/gen/' + tableId,
method: 'get' method: 'get'
}) })
} }
// 修改代码生成信息 // 修改代码生成信息
export function updateGenTable(data) { export function updateGenTable (data) {
return request({ return request({
url: '/tool/gen', url: '/tool/gen',
method: 'put', method: 'put',
data: data data: data
}) })
} }
// 导入表 // 导入表
export function importTable(data) { export function importTable (data) {
return request({ return request({
url: '/tool/gen/importTable', url: '/tool/gen/importTable',
method: 'post', method: 'post',
params: data params: data
}) })
} }
// 预览生成代码 // 预览生成代码
export function previewTable(tableId) { export function previewTable (tableId) {
return request({ return request({
url: '/tool/gen/preview/' + tableId, url: '/tool/gen/preview/' + tableId,
method: 'get' method: 'get'
}) })
} }
// 删除表数据 // 删除表数据
export function delTable(tableId) { export function delTable (tableId) {
return request({ return request({
url: '/tool/gen/' + tableId, url: '/tool/gen/' + tableId,
method: 'delete' method: 'delete'
}) })
} }
// 生成代码(自定义路径) // 生成代码(自定义路径)
export function genCode(tableName) { export function genCode (tableName) {
return request({ return request({
url: '/tool/gen/genCode/' + tableName, url: '/tool/gen/genCode/' + tableName,
method: 'get' method: 'get'
}) })
} }
// 同步数据库 // 同步数据库
export function synchDb(tableName) { export function synchDb (tableName) {
return request({ return request({
url: '/tool/gen/synchDb/' + tableName, url: '/tool/gen/synchDb/' + tableName,
method: 'get' method: 'get'
}) })
} }

View File

@ -1,9 +1,9 @@
import Vue from 'vue' import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component import SvgIcon from '@/components/SvgIcon'// svg component
// register globally // register globally
Vue.component('svg-icon', SvgIcon) Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/) const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext) const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req) requireAll(req)

View File

@ -1,2 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; } <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg> </style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg>

Before

Width:  |  Height:  |  Size: 884 B

After

Width:  |  Height:  |  Size: 883 B

View File

@ -1,2 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; } <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
</style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234" fill="#bfbfbf"></path></svg> </style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234" fill="#bfbfbf"></path></svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,22 +1,22 @@
# replace default config # replace default config
# multipass: true # multipass: true
# full: true # full: true
plugins: plugins:
# - name # - name
# #
# or: # or:
# - name: false # - name: false
# - name: true # - name: true
# #
# or: # or:
# - name: # - name:
# param1: 1 # param1: 1
# param2: 2 # param2: 2
- removeAttrs: - removeAttrs:
attrs: attrs:
- 'fill' - 'fill'
- 'fill-rule' - 'fill-rule'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,99 +1,99 @@
@import './variables.scss'; @import './variables.scss';
@mixin colorBtn($color) { @mixin colorBtn($color) {
background: $color; background: $color;
&:hover { &:hover {
color: $color; color: $color;
&:before, &:before,
&:after { &:after {
background: $color; background: $color;
} }
} }
} }
.blue-btn { .blue-btn {
@include colorBtn($blue) @include colorBtn($blue)
} }
.light-blue-btn { .light-blue-btn {
@include colorBtn($light-blue) @include colorBtn($light-blue)
} }
.red-btn { .red-btn {
@include colorBtn($red) @include colorBtn($red)
} }
.pink-btn { .pink-btn {
@include colorBtn($pink) @include colorBtn($pink)
} }
.green-btn { .green-btn {
@include colorBtn($green) @include colorBtn($green)
} }
.tiffany-btn { .tiffany-btn {
@include colorBtn($tiffany) @include colorBtn($tiffany)
} }
.yellow-btn { .yellow-btn {
@include colorBtn($yellow) @include colorBtn($yellow)
} }
.pan-btn { .pan-btn {
font-size: 14px; font-size: 14px;
color: #fff; color: #fff;
padding: 14px 36px; padding: 14px 36px;
border-radius: 8px; border-radius: 8px;
border: none; border: none;
outline: none; outline: none;
transition: 600ms ease all; transition: 600ms ease all;
position: relative; position: relative;
display: inline-block; display: inline-block;
&:hover { &:hover {
background: #fff; background: #fff;
&:before, &:before,
&:after { &:after {
width: 100%; width: 100%;
transition: 600ms ease all; transition: 600ms ease all;
} }
} }
&:before, &:before,
&:after { &:after {
content: ''; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
height: 2px; height: 2px;
width: 0; width: 0;
transition: 400ms ease all; transition: 400ms ease all;
} }
&::after { &::after {
right: inherit; right: inherit;
top: inherit; top: inherit;
left: 0; left: 0;
bottom: 0; bottom: 0;
} }
} }
.custom-button { .custom-button {
display: inline-block; display: inline-block;
line-height: 1; line-height: 1;
white-space: nowrap; white-space: nowrap;
cursor: pointer; cursor: pointer;
background: #fff; background: #fff;
color: #fff; color: #fff;
-webkit-appearance: none; -webkit-appearance: none;
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
outline: 0; outline: 0;
margin: 0; margin: 0;
padding: 10px 15px; padding: 10px 15px;
font-size: 14px; font-size: 14px;
border-radius: 4px; border-radius: 4px;
} }

View File

@ -1,31 +1,31 @@
/** /**
* I think element-ui's default theme color is too light for long-term use. * 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. * So I modified the default color and you can modify it to your liking.
**/ **/
/* theme color */ /* theme color */
$--color-primary: #1890ff; $--color-primary: #1890ff;
$--color-success: #13ce66; $--color-success: #13ce66;
$--color-warning: #ffba00; $--color-warning: #ffba00;
$--color-danger: #ff4949; $--color-danger: #ff4949;
// $--color-info: #1E1E1E; // $--color-info: #1E1E1E;
$--button-font-weight: 400; $--button-font-weight: 400;
// $--color-text-regular: #1f2d3d; // $--color-text-regular: #1f2d3d;
$--border-color-light: #dfe4ed; $--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5; $--border-color-lighter: #e6ebf5;
$--table-border:1px solid#dfe6ec; $--table-border:1px solid#dfe6ec;
/* icon font path, required */ /* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts'; $--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index"; @import "~element-ui/packages/theme-chalk/src/index";
// the :export directive is the magic sauce for webpack // the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export { :export {
theme: $--color-primary; theme: $--color-primary;
} }

View File

@ -1,191 +1,191 @@
@import './variables.scss'; @import './variables.scss';
@import './mixin.scss'; @import './mixin.scss';
@import './transition.scss'; @import './transition.scss';
@import './element-ui.scss'; @import './element-ui.scss';
@import './sidebar.scss'; @import './sidebar.scss';
@import './btn.scss'; @import './btn.scss';
body { body {
height: 100%; height: 100%;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
} }
label { label {
font-weight: 700; font-weight: 700;
} }
html { html {
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
} }
#app { #app {
height: 100%; height: 100%;
} }
*, *,
*:before, *:before,
*:after { *:after {
box-sizing: inherit; box-sizing: inherit;
} }
.no-padding { .no-padding {
padding: 0px !important; padding: 0px !important;
} }
.padding-content { .padding-content {
padding: 4px 0; padding: 4px 0;
} }
a:focus, a:focus,
a:active { a:active {
outline: none; outline: none;
} }
a, a,
a:focus, a:focus,
a:hover { a:hover {
cursor: pointer; cursor: pointer;
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
} }
div:focus { div:focus {
outline: none; outline: none;
} }
.fr { .fr {
float: right; float: right;
} }
.fl { .fl {
float: left; float: left;
} }
.pr-5 { .pr-5 {
padding-right: 5px; padding-right: 5px;
} }
.pl-5 { .pl-5 {
padding-left: 5px; padding-left: 5px;
} }
.block { .block {
display: block; display: block;
} }
.pointer { .pointer {
cursor: pointer; cursor: pointer;
} }
.inlineBlock { .inlineBlock {
display: block; display: block;
} }
.clearfix { .clearfix {
&:after { &:after {
visibility: hidden; visibility: hidden;
display: block; display: block;
font-size: 0; font-size: 0;
content: " "; content: " ";
clear: both; clear: both;
height: 0; height: 0;
} }
} }
aside { aside {
background: #eef1f6; background: #eef1f6;
padding: 8px 24px; padding: 8px 24px;
margin-bottom: 20px; margin-bottom: 20px;
border-radius: 2px; border-radius: 2px;
display: block; display: block;
line-height: 32px; line-height: 32px;
font-size: 16px; font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
color: #2c3e50; color: #2c3e50;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
a { a {
color: #337ab7; color: #337ab7;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
color: rgb(32, 160, 255); color: rgb(32, 160, 255);
} }
} }
} }
//main-container全局样式 //main-container全局样式
.app-container { .app-container {
padding: 20px; padding: 20px;
} }
.components-container { .components-container {
margin: 30px 50px; margin: 30px 50px;
position: relative; position: relative;
} }
.pagination-container { .pagination-container {
margin-top: 30px; margin-top: 30px;
} }
.text-center { .text-center {
text-align: center text-align: center
} }
.sub-navbar { .sub-navbar {
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
position: relative; position: relative;
width: 100%; width: 100%;
text-align: right; text-align: right;
padding-right: 20px; padding-right: 20px;
transition: 600ms ease position; 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%); 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 { .subtitle {
font-size: 20px; font-size: 20px;
color: #fff; color: #fff;
} }
&.draft { &.draft {
background: #d0d0d0; background: #d0d0d0;
} }
&.deleted { &.deleted {
background: #d0d0d0; background: #d0d0d0;
} }
} }
.link-type, .link-type,
.link-type:focus { .link-type:focus {
color: #337ab7; color: #337ab7;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
color: rgb(32, 160, 255); color: rgb(32, 160, 255);
} }
} }
.filter-container { .filter-container {
padding-bottom: 10px; padding-bottom: 10px;
.filter-item { .filter-item {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
margin-bottom: 10px; margin-bottom: 10px;
} }
} }
//refine vue-multiselect plugin //refine vue-multiselect plugin
.multiselect { .multiselect {
line-height: 16px; line-height: 16px;
} }
.multiselect--active { .multiselect--active {
z-index: 1000 !important; z-index: 1000 !important;
} }

View File

@ -1,66 +1,66 @@
@mixin clearfix { @mixin clearfix {
&:after { &:after {
content: ""; content: "";
display: table; display: table;
clear: both; clear: both;
} }
} }
@mixin scrollBar { @mixin scrollBar {
&::-webkit-scrollbar-track-piece { &::-webkit-scrollbar-track-piece {
background: #d3dce6; background: #d3dce6;
} }
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 6px; width: 6px;
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #99a9bf; background: #99a9bf;
border-radius: 20px; border-radius: 20px;
} }
} }
@mixin relative { @mixin relative {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
@mixin pct($pct) { @mixin pct($pct) {
width: #{$pct}; width: #{$pct};
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
} }
@mixin triangle($width, $height, $color, $direction) { @mixin triangle($width, $height, $color, $direction) {
$width: $width/2; $width: $width/2;
$color-border-style: $height solid $color; $color-border-style: $height solid $color;
$transparent-border-style: $width solid transparent; $transparent-border-style: $width solid transparent;
height: 0; height: 0;
width: 0; width: 0;
@if $direction==up { @if $direction==up {
border-bottom: $color-border-style; border-bottom: $color-border-style;
border-left: $transparent-border-style; border-left: $transparent-border-style;
border-right: $transparent-border-style; border-right: $transparent-border-style;
} }
@else if $direction==right { @else if $direction==right {
border-left: $color-border-style; border-left: $color-border-style;
border-top: $transparent-border-style; border-top: $transparent-border-style;
border-bottom: $transparent-border-style; border-bottom: $transparent-border-style;
} }
@else if $direction==down { @else if $direction==down {
border-top: $color-border-style; border-top: $color-border-style;
border-left: $transparent-border-style; border-left: $transparent-border-style;
border-right: $transparent-border-style; border-right: $transparent-border-style;
} }
@else if $direction==left { @else if $direction==left {
border-right: $color-border-style; border-right: $color-border-style;
border-top: $transparent-border-style; border-top: $transparent-border-style;
border-bottom: $transparent-border-style; border-bottom: $transparent-border-style;
} }
} }

View File

@ -1,266 +1,266 @@
/** /**
* 通用css样式布局处理 * 通用css样式布局处理
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
/** 基础通用 **/ /** 基础通用 **/
.pt5 { .pt5 {
padding-top: 5px; padding-top: 5px;
} }
.pr5 { .pr5 {
padding-right: 5px; padding-right: 5px;
} }
.pb5 { .pb5 {
padding-bottom: 5px; padding-bottom: 5px;
} }
.mt5 { .mt5 {
margin-top: 5px; margin-top: 5px;
} }
.mr5 { .mr5 {
margin-right: 5px; margin-right: 5px;
} }
.mb5 { .mb5 {
margin-bottom: 5px; margin-bottom: 5px;
} }
.mb8 { .mb8 {
margin-bottom: 8px; margin-bottom: 8px;
} }
.ml5 { .ml5 {
margin-left: 5px; margin-left: 5px;
} }
.mt10 { .mt10 {
margin-top: 10px; margin-top: 10px;
} }
.mr10 { .mr10 {
margin-right: 10px; margin-right: 10px;
} }
.mb10 { .mb10 {
margin-bottom: 10px; margin-bottom: 10px;
} }
.ml0 { .ml0 {
margin-left: 10px; margin-left: 10px;
} }
.mt20 { .mt20 {
margin-top: 20px; margin-top: 20px;
} }
.mr20 { .mr20 {
margin-right: 20px; margin-right: 20px;
} }
.mb20 { .mb20 {
margin-bottom: 20px; margin-bottom: 20px;
} }
.m20 { .m20 {
margin-left: 20px; margin-left: 20px;
} }
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { .h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
font-family: inherit; font-family: inherit;
font-weight: 500; font-weight: 500;
line-height: 1.1; line-height: 1.1;
color: inherit; color: inherit;
} }
.el-dialog:not(.is-fullscreen){ .el-dialog:not(.is-fullscreen){
margin-top: 6vh !important; margin-top: 6vh !important;
} }
.el-table { .el-table {
.el-table__header-wrapper, .el-table__fixed-header-wrapper { .el-table__header-wrapper, .el-table__fixed-header-wrapper {
th { th {
word-break: break-word; word-break: break-word;
background-color: #f8f8f9; background-color: #f8f8f9;
color: #515a6e; color: #515a6e;
height: 40px; height: 40px;
font-size: 13px; font-size: 13px;
} }
} }
.el-table__body-wrapper { .el-table__body-wrapper {
.el-button [class*="el-icon-"] + span { .el-button [class*="el-icon-"] + span {
margin-left: 1px; margin-left: 1px;
} }
} }
} }
/** 表单布局 **/ /** 表单布局 **/
.form-header { .form-header {
font-size:15px; font-size:15px;
color:#6379bb; color:#6379bb;
border-bottom:1px solid #ddd; border-bottom:1px solid #ddd;
margin:8px 10px 25px 10px; margin:8px 10px 25px 10px;
padding-bottom:5px padding-bottom:5px
} }
/** 表格布局 **/ /** 表格布局 **/
.pagination-container { .pagination-container {
position: relative; position: relative;
height: 25px; height: 25px;
margin-bottom: 10px; margin-bottom: 10px;
margin-top: 15px; margin-top: 15px;
padding: 10px 20px !important; padding: 10px 20px !important;
} }
/* tree border */ /* tree border */
.tree-border { .tree-border {
margin-top: 5px; margin-top: 5px;
border: 1px solid #e5e6e7; border: 1px solid #e5e6e7;
background: #FFFFFF none; background: #FFFFFF none;
border-radius:4px; border-radius:4px;
} }
.pagination-container .el-pagination { .pagination-container .el-pagination {
right: 0; right: 0;
position: absolute; position: absolute;
} }
@media ( max-width : 768px) { @media ( max-width : 768px) {
.pagination-container .el-pagination > .el-pagination__jump { .pagination-container .el-pagination > .el-pagination__jump {
display: none !important; display: none !important;
} }
.pagination-container .el-pagination > .el-pagination__sizes { .pagination-container .el-pagination > .el-pagination__sizes {
display: none !important; display: none !important;
} }
} }
.el-table .fixed-width .el-button--mini { .el-table .fixed-width .el-button--mini {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
width: inherit; width: inherit;
} }
/** 表格更多操作下拉样式 */ /** 表格更多操作下拉样式 */
.el-table .el-dropdown-link { .el-table .el-dropdown-link {
cursor: pointer; cursor: pointer;
color: #1890ff; color: #1890ff;
margin-left: 5px; margin-left: 5px;
} }
.el-table .el-dropdown, .el-icon-arrow-down { .el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px; font-size: 12px;
} }
.el-tree-node__content > .el-checkbox { .el-tree-node__content > .el-checkbox {
margin-right: 8px; margin-right: 8px;
} }
.list-group-striped > .list-group-item { .list-group-striped > .list-group-item {
border-left: 0; border-left: 0;
border-right: 0; border-right: 0;
border-radius: 0; border-radius: 0;
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
.list-group { .list-group {
padding-left: 0px; padding-left: 0px;
list-style: none; list-style: none;
} }
.list-group-item { .list-group-item {
border-bottom: 1px solid #e7eaec; border-bottom: 1px solid #e7eaec;
border-top: 1px solid #e7eaec; border-top: 1px solid #e7eaec;
margin-bottom: -1px; margin-bottom: -1px;
padding: 11px 0px; padding: 11px 0px;
font-size: 13px; font-size: 13px;
} }
.pull-right { .pull-right {
float: right !important; float: right !important;
} }
.el-card__header { .el-card__header {
padding: 14px 15px 7px; padding: 14px 15px 7px;
min-height: 40px; min-height: 40px;
} }
.el-card__body { .el-card__body {
padding: 15px 20px 20px 20px; padding: 15px 20px 20px 20px;
} }
.card-box { .card-box {
padding-right: 15px; padding-right: 15px;
padding-left: 15px; padding-left: 15px;
margin-bottom: 10px; margin-bottom: 10px;
} }
/* button color */ /* button color */
.el-button--cyan.is-active, .el-button--cyan.is-active,
.el-button--cyan:active { .el-button--cyan:active {
background: #20B2AA; background: #20B2AA;
border-color: #20B2AA; border-color: #20B2AA;
color: #FFFFFF; color: #FFFFFF;
} }
.el-button--cyan:focus, .el-button--cyan:focus,
.el-button--cyan:hover { .el-button--cyan:hover {
background: #48D1CC; background: #48D1CC;
border-color: #48D1CC; border-color: #48D1CC;
color: #FFFFFF; color: #FFFFFF;
} }
.el-button--cyan { .el-button--cyan {
background-color: #20B2AA; background-color: #20B2AA;
border-color: #20B2AA; border-color: #20B2AA;
color: #FFFFFF; color: #FFFFFF;
} }
/* text color */ /* text color */
.text-navy { .text-navy {
color: #1ab394; color: #1ab394;
} }
.text-primary { .text-primary {
color: inherit; color: inherit;
} }
.text-success { .text-success {
color: #1c84c6; color: #1c84c6;
} }
.text-info { .text-info {
color: #23c6c8; color: #23c6c8;
} }
.text-warning { .text-warning {
color: #f8ac59; color: #f8ac59;
} }
.text-danger { .text-danger {
color: #ed5565; color: #ed5565;
} }
.text-muted { .text-muted {
color: #888888; color: #888888;
} }
/* image */ /* image */
.img-circle { .img-circle {
border-radius: 50%; border-radius: 50%;
} }
.img-lg { .img-lg {
width: 120px; width: 120px;
height: 120px; height: 120px;
} }
.avatar-upload-preview { .avatar-upload-preview {
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: translate(50%, -50%); transform: translate(50%, -50%);
width: 200px; width: 200px;
height: 200px; height: 200px;
border-radius: 50%; border-radius: 50%;
box-shadow: 0 0 4px #ccc; box-shadow: 0 0 4px #ccc;
overflow: hidden; overflow: hidden;
} }
/* 拖拽列样式 */ /* 拖拽列样式 */
.sortable-ghost{ .sortable-ghost{
opacity: .8; opacity: .8;
color: #fff!important; color: #fff!important;
background: #42b983!important; background: #42b983!important;
} }
.top-right-btn { .top-right-btn {
position: relative; position: relative;
float: right; float: right;
} }

View File

@ -1,223 +1,223 @@
#app { #app {
.main-container { .main-container {
min-height: 100%; min-height: 100%;
transition: margin-left .28s; transition: margin-left .28s;
margin-left: $sideBarWidth; margin-left: $sideBarWidth;
position: relative; position: relative;
} }
.sidebar-container { .sidebar-container {
-webkit-transition: width .28s; -webkit-transition: width .28s;
transition: width 0.28s; transition: width 0.28s;
width: $sideBarWidth !important; width: $sideBarWidth !important;
background-color: $menuBg; background-color: $menuBg;
height: 100%; height: 100%;
position: fixed; position: fixed;
font-size: 0px; font-size: 0px;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 1001; z-index: 1001;
overflow: hidden; overflow: hidden;
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
box-shadow: 2px 0 6px rgba(0,21,41,.35); box-shadow: 2px 0 6px rgba(0,21,41,.35);
// reset element-ui css // reset element-ui css
.horizontal-collapse-transition { .horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
} }
.scrollbar-wrapper { .scrollbar-wrapper {
overflow-x: hidden !important; overflow-x: hidden !important;
} }
.el-scrollbar__bar.is-vertical { .el-scrollbar__bar.is-vertical {
right: 0px; right: 0px;
} }
.el-scrollbar { .el-scrollbar {
height: 100%; height: 100%;
} }
&.has-logo { &.has-logo {
.el-scrollbar { .el-scrollbar {
height: calc(100% - 50px); height: calc(100% - 50px);
} }
} }
.is-horizontal { .is-horizontal {
display: none; display: none;
} }
a { a {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
} }
.svg-icon { .svg-icon {
margin-right: 16px; margin-right: 16px;
} }
.el-menu { .el-menu {
border: none; border: none;
height: 100%; height: 100%;
width: 100% !important; width: 100% !important;
} }
.el-menu-item, .el-submenu__title { .el-menu-item, .el-submenu__title {
overflow: hidden !important; overflow: hidden !important;
text-overflow: ellipsis !important; text-overflow: ellipsis !important;
white-space: nowrap !important; white-space: nowrap !important;
} }
// menu hover // menu hover
.submenu-title-noDropdown, .submenu-title-noDropdown,
.el-submenu__title { .el-submenu__title {
&:hover { &:hover {
background-color: rgba(0, 0, 0, 0.06) !important; background-color: rgba(0, 0, 0, 0.06) !important;
} }
} }
& .theme-dark .is-active > .el-submenu__title { & .theme-dark .is-active > .el-submenu__title {
color: $subMenuActiveText !important; color: $subMenuActiveText !important;
} }
& .nest-menu .el-submenu>.el-submenu__title, & .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item { & .el-submenu .el-menu-item {
min-width: $sideBarWidth !important; min-width: $sideBarWidth !important;
&:hover { &:hover {
background-color: rgba(0, 0, 0, 0.06) !important; background-color: rgba(0, 0, 0, 0.06) !important;
} }
} }
& .theme-dark .nest-menu .el-submenu>.el-submenu__title, & .theme-dark .nest-menu .el-submenu>.el-submenu__title,
& .theme-dark .el-submenu .el-menu-item { & .theme-dark .el-submenu .el-menu-item {
background-color: $subMenuBg !important; background-color: $subMenuBg !important;
&:hover { &:hover {
background-color: $subMenuHover !important; background-color: $subMenuHover !important;
} }
} }
} }
.hideSidebar { .hideSidebar {
.sidebar-container { .sidebar-container {
width: 54px !important; width: 54px !important;
} }
.main-container { .main-container {
margin-left: 54px; margin-left: 54px;
} }
.submenu-title-noDropdown { .submenu-title-noDropdown {
padding: 0 !important; padding: 0 !important;
position: relative; position: relative;
.el-tooltip { .el-tooltip {
padding: 0 !important; padding: 0 !important;
.svg-icon { .svg-icon {
margin-left: 20px; margin-left: 20px;
} }
} }
} }
.el-submenu { .el-submenu {
overflow: hidden; overflow: hidden;
&>.el-submenu__title { &>.el-submenu__title {
padding: 0 !important; padding: 0 !important;
.svg-icon { .svg-icon {
margin-left: 20px; margin-left: 20px;
} }
} }
} }
.el-menu--collapse { .el-menu--collapse {
.el-submenu { .el-submenu {
&>.el-submenu__title { &>.el-submenu__title {
&>span { &>span {
height: 0; height: 0;
width: 0; width: 0;
overflow: hidden; overflow: hidden;
visibility: hidden; visibility: hidden;
display: inline-block; display: inline-block;
} }
} }
} }
} }
} }
.el-menu--collapse .el-menu .el-submenu { .el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important; min-width: $sideBarWidth !important;
} }
// mobile responsive // mobile responsive
.mobile { .mobile {
.main-container { .main-container {
margin-left: 0px; margin-left: 0px;
} }
.sidebar-container { .sidebar-container {
transition: transform .28s; transition: transform .28s;
width: $sideBarWidth !important; width: $sideBarWidth !important;
} }
&.hideSidebar { &.hideSidebar {
.sidebar-container { .sidebar-container {
pointer-events: none; pointer-events: none;
transition-duration: 0.3s; transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0); transform: translate3d(-$sideBarWidth, 0, 0);
} }
} }
} }
.withoutAnimation { .withoutAnimation {
.main-container, .main-container,
.sidebar-container { .sidebar-container {
transition: none; transition: none;
} }
} }
} }
// when menu collapsed // when menu collapsed
.el-menu--vertical { .el-menu--vertical {
&>.el-menu { &>.el-menu {
.svg-icon { .svg-icon {
margin-right: 16px; margin-right: 16px;
} }
} }
.nest-menu .el-submenu>.el-submenu__title, .nest-menu .el-submenu>.el-submenu__title,
.el-menu-item { .el-menu-item {
&:hover { &:hover {
// you can use $subMenuHover // you can use $subMenuHover
background-color: rgba(0, 0, 0, 0.06) !important; background-color: rgba(0, 0, 0, 0.06) !important;
} }
} }
// the scroll bar appears when the subMenu is too long // the scroll bar appears when the subMenu is too long
>.el-menu--popup { >.el-menu--popup {
max-height: 100vh; max-height: 100vh;
overflow-y: auto; overflow-y: auto;
&::-webkit-scrollbar-track-piece { &::-webkit-scrollbar-track-piece {
background: #d3dce6; background: #d3dce6;
} }
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 6px; width: 6px;
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background: #99a9bf; background: #99a9bf;
border-radius: 20px; border-radius: 20px;
} }
} }
} }

View File

@ -1,48 +1,48 @@
// global transition css // global transition css
/* fade */ /* fade */
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.28s; transition: opacity 0.28s;
} }
.fade-enter, .fade-enter,
.fade-leave-active { .fade-leave-active {
opacity: 0; opacity: 0;
} }
/* fade-transform */ /* fade-transform */
.fade-transform-leave-active, .fade-transform-leave-active,
.fade-transform-enter-active { .fade-transform-enter-active {
transition: all .5s; transition: all .5s;
} }
.fade-transform-enter { .fade-transform-enter {
opacity: 0; opacity: 0;
transform: translateX(-30px); transform: translateX(-30px);
} }
.fade-transform-leave-to { .fade-transform-leave-to {
opacity: 0; opacity: 0;
transform: translateX(30px); transform: translateX(30px);
} }
/* breadcrumb transition */ /* breadcrumb transition */
.breadcrumb-enter-active, .breadcrumb-enter-active,
.breadcrumb-leave-active { .breadcrumb-leave-active {
transition: all .5s; transition: all .5s;
} }
.breadcrumb-enter, .breadcrumb-enter,
.breadcrumb-leave-active { .breadcrumb-leave-active {
opacity: 0; opacity: 0;
transform: translateX(20px); transform: translateX(20px);
} }
.breadcrumb-move { .breadcrumb-move {
transition: all .5s; transition: all .5s;
} }
.breadcrumb-leave-active { .breadcrumb-leave-active {
position: absolute; position: absolute;
} }

View File

@ -1,44 +1,44 @@
// base color // base color
$blue:#324157; $blue:#324157;
$light-blue:#3A71A8; $light-blue:#3A71A8;
$red:#C03639; $red:#C03639;
$pink: #E65D6E; $pink: #E65D6E;
$green: #30B08F; $green: #30B08F;
$tiffany: #4AB7BD; $tiffany: #4AB7BD;
$yellow:#FEC171; $yellow:#FEC171;
$panGreen: #30B08F; $panGreen: #30B08F;
// sidebar // sidebar
$menuText:#bfcbd9; $menuText:#bfcbd9;
$menuActiveText:#409EFF; $menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951 $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156; $menuBg:#304156;
$menuHover:#263445; $menuHover:#263445;
$sidebarTitle: #ffffff; $sidebarTitle: #ffffff;
$menuLightBg:#ffffff; $menuLightBg:#ffffff;
$menuLightHover:#f0f1f5; $menuLightHover:#f0f1f5;
$sidebarLightTitle: #001529; $sidebarLightTitle: #001529;
$subMenuBg:#1f2d3d; $subMenuBg:#1f2d3d;
$subMenuHover:#001528; $subMenuHover:#001528;
$sideBarWidth: 200px; $sideBarWidth: 200px;
// the :export directive is the magic sauce for webpack // the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export { :export {
menuText: $menuText; menuText: $menuText;
menuActiveText: $menuActiveText; menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText; subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg; menuBg: $menuBg;
menuHover: $menuHover; menuHover: $menuHover;
menuLightBg: $menuLightBg; menuLightBg: $menuLightBg;
menuLightHover: $menuLightHover; menuLightHover: $menuLightHover;
subMenuBg: $subMenuBg; subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover; subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth; sideBarWidth: $sideBarWidth;
sidebarTitle: $sidebarTitle; sidebarTitle: $sidebarTitle;
sidebarLightTitle: $sidebarLightTitle sidebarLightTitle: $sidebarLightTitle
} }

View File

@ -2,7 +2,7 @@
<el-breadcrumb class="app-breadcrumb" separator="/"> <el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb"> <transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> <span v-if="item.redirect==='noRedirect'||index===levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item> </el-breadcrumb-item>
</transition-group> </transition-group>
@ -11,13 +11,13 @@
<script> <script>
export default { export default {
data() { data () {
return { return {
levelList: null levelList: null
} }
}, },
watch: { watch: {
$route(route) { $route (route) {
// if you go to the redirect page, do not update the breadcrumbs // if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) { if (route.path.startsWith('/redirect/')) {
return return
@ -25,29 +25,29 @@ export default {
this.getBreadcrumb() this.getBreadcrumb()
} }
}, },
created() { created () {
this.getBreadcrumb() this.getBreadcrumb()
}, },
methods: { methods: {
getBreadcrumb() { getBreadcrumb () {
// only show routes with meta.title // only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title) let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0] const first = matched[0]
if (!this.isDashboard(first)) { if (!this.isDashboard(first)) {
matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched) matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched)
} }
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}, },
isDashboard(route) { isDashboard (route) {
const name = route && route.name const name = route && route.name
if (!name) { if (!name) {
return false return false
} }
return name.trim() === 'Index' return name.trim() === 'Index'
}, },
handleLink(item) { handleLink (item) {
const { redirect, path } = item const { redirect, path } = item
if (redirect) { if (redirect) {
this.$router.push(redirect) this.$router.push(redirect)

View File

@ -3,7 +3,7 @@
<template v-for="(item, index) in options"> <template v-for="(item, index) in options">
<template v-if="values.includes(item.dictValue)"> <template v-if="values.includes(item.dictValue)">
<span <span
v-if="item.listClass == 'default' || item.listClass == ''" v-if="item.listClass === 'default' || item.listClass === ''"
:key="item.dictValue" :key="item.dictValue"
:index="index" :index="index"
:class="item.cssClass" :class="item.cssClass"
@ -13,7 +13,7 @@
v-else v-else
:key="item.dictValue" :key="item.dictValue"
:index="index" :index="index"
:type="item.listClass == 'primary' ? '' : item.listClass" :type="item.listClass === 'primary' ? '' : item.listClass"
:class="item.cssClass" :class="item.cssClass"
> >
{{ item.dictLabel }} {{ item.dictLabel }}
@ -25,27 +25,27 @@
<script> <script>
export default { export default {
name: "DictTag", name: 'DictTag',
props: { props: {
options: { options: {
type: Array, type: Array,
default: null, default: null
}, },
value: [String, Array], value: [String, Array]
}, },
computed: { computed: {
values() { values () {
if (this.value) { if (this.value) {
return Array.isArray(this.value) ? this.value : [this.value]; return Array.isArray(this.value) ? this.value : [this.value]
} else { } else {
return []; return []
} }
}, }
}, }
}; }
</script> </script>
<style scoped> <style scoped>
.el-tag + .el-tag { .el-tag + .el-tag {
margin-left: 10px; margin-left: 10px;
} }
</style> </style>

View File

@ -10,7 +10,7 @@
:headers="headers" :headers="headers"
style="display: none" style="display: none"
ref="upload" ref="upload"
v-if="this.type == 'url'" v-if="this.type === 'url'"
> >
</el-upload> </el-upload>
<div class="editor" ref="editor" :style="styles"></div> <div class="editor" ref="editor" :style="styles"></div>
@ -18,176 +18,176 @@
</template> </template>
<script> <script>
import Quill from "quill"; import Quill from 'quill'
import "quill/dist/quill.core.css"; import 'quill/dist/quill.core.css'
import "quill/dist/quill.snow.css"; import 'quill/dist/quill.snow.css'
import "quill/dist/quill.bubble.css"; import 'quill/dist/quill.bubble.css'
import { getToken } from "@/utils/auth"; import { getToken } from '@/utils/auth'
export default { export default {
name: "Editor", name: 'Editor',
props: { props: {
/* 编辑器的内容 */ /* 编辑器的内容 */
value: { value: {
type: String, type: String,
default: "", default: ''
}, },
/* 高度 */ /* 高度 */
height: { height: {
type: Number, type: Number,
default: null, default: null
}, },
/* 最小高度 */ /* 最小高度 */
minHeight: { minHeight: {
type: Number, type: Number,
default: null, default: null
}, },
/* 只读 */ /* 只读 */
readOnly: { readOnly: {
type: Boolean, type: Boolean,
default: false, default: false
}, },
// 上传文件大小限制(MB) // 上传文件大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5, default: 5
}, },
/* 类型base64格式、url格式 */ /* 类型base64格式、url格式 */
type: { type: {
type: String, type: String,
default: "url", default: 'url'
} }
}, },
data() { data () {
return { return {
uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 uploadUrl: process.env.VUE_APP_BASE_API + '/common/upload', // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken() Authorization: 'Bearer ' + getToken()
}, },
Quill: null, Quill: null,
currentValue: "", currentValue: '',
options: { options: {
theme: "snow", theme: 'snow',
bounds: document.body, bounds: document.body,
debug: "warn", debug: 'warn',
modules: { modules: {
// 工具栏配置 // 工具栏配置
toolbar: [ toolbar: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线 ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块 ['blockquote', 'code-block'], // 引用 代码块
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表 [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
[{ indent: "-1" }, { indent: "+1" }], // 缩进 [{ indent: '-1' }, { indent: '+1' }], // 缩进
[{ size: ["small", false, "large", "huge"] }], // 字体大小 [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题 [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色 [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式 [{ align: [] }], // 对齐方式
["clean"], // 清除文本格式 ['clean'], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频 ['link', 'image', 'video'] // 链接、图片、视频
], ]
}, },
placeholder: "请输入内容", placeholder: '请输入内容',
readOnly: this.readOnly, readOnly: this.readOnly
}, }
}; }
}, },
computed: { computed: {
styles() { styles () {
let style = {}; const style = {}
if (this.minHeight) { if (this.minHeight) {
style.minHeight = `${this.minHeight}px`; style.minHeight = `${this.minHeight}px`
} }
if (this.height) { if (this.height) {
style.height = `${this.height}px`; style.height = `${this.height}px`
} }
return style; return style
}, }
}, },
watch: { watch: {
value: { value: {
handler(val) { handler (val) {
if (val !== this.currentValue) { if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val; this.currentValue = val === null ? '' : val
if (this.Quill) { if (this.Quill) {
this.Quill.pasteHTML(this.currentValue); this.Quill.pasteHTML(this.currentValue)
} }
} }
}, },
immediate: true, immediate: true
}, }
}, },
mounted() { mounted () {
this.init(); this.init()
}, },
beforeDestroy() { beforeDestroy () {
this.Quill = null; this.Quill = null
}, },
methods: { methods: {
init() { init () {
const editor = this.$refs.editor; const editor = this.$refs.editor
this.Quill = new Quill(editor, this.options); this.Quill = new Quill(editor, this.options)
// 如果设置了上传地址则自定义图片上传事件 // 如果设置了上传地址则自定义图片上传事件
if (this.type == 'url') { if (this.type === 'url') {
let toolbar = this.Quill.getModule("toolbar"); const toolbar = this.Quill.getModule('toolbar')
toolbar.addHandler("image", (value) => { toolbar.addHandler('image', (value) => {
this.uploadType = "image"; this.uploadType = 'image'
if (value) { if (value) {
this.$refs.upload.$children[0].$refs.input.click(); this.$refs.upload.$children[0].$refs.input.click()
} else { } else {
this.quill.format("image", false); this.quill.format('image', false)
} }
}); })
} }
this.Quill.pasteHTML(this.currentValue); this.Quill.pasteHTML(this.currentValue)
this.Quill.on("text-change", (delta, oldDelta, source) => { this.Quill.on('text-change', (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML; const html = this.$refs.editor.children[0].innerHTML
const text = this.Quill.getText(); const text = this.Quill.getText()
const quill = this.Quill; const quill = this.Quill
this.currentValue = html; this.currentValue = html
this.$emit("input", html); this.$emit('input', html)
this.$emit("on-change", { html, text, quill }); this.$emit('on-change', { html, text, quill })
}); })
this.Quill.on("text-change", (delta, oldDelta, source) => { this.Quill.on('text-change', (delta, oldDelta, source) => {
this.$emit("on-text-change", delta, oldDelta, source); this.$emit('on-text-change', delta, oldDelta, source)
}); })
this.Quill.on("selection-change", (range, oldRange, source) => { this.Quill.on('selection-change', (range, oldRange, source) => {
this.$emit("on-selection-change", range, oldRange, source); this.$emit('on-selection-change', range, oldRange, source)
}); })
this.Quill.on("editor-change", (eventName, ...args) => { this.Quill.on('editor-change', (eventName, ...args) => {
this.$emit("on-editor-change", eventName, ...args); this.$emit('on-editor-change', eventName, ...args)
}); })
}, },
// 上传前校检格式和大小 // 上传前校检格式和大小
handleBeforeUpload(file) { handleBeforeUpload (file) {
// 校检文件大小 // 校检文件大小
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`); this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
return true; return true
}, },
handleUploadSuccess(res, file) { handleUploadSuccess (res, file) {
// 获取富文本组件实例 // 获取富文本组件实例
let quill = this.Quill; const quill = this.Quill
// 如果上传成功 // 如果上传成功
if (res.code == 200) { if (res.code === 200) {
// 获取光标所在位置 // 获取光标所在位置
let length = quill.getSelection().index; const length = quill.getSelection().index
// 插入图片 res.url为服务器返回的图片地址 // 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName); quill.insertEmbed(length, 'image', process.env.VUE_APP_BASE_API + res.fileName)
// 调整光标到最后 // 调整光标到最后
quill.setSelection(length + 1); quill.setSelection(length + 1)
} else { } else {
this.$message.error("图片插入失败"); this.$message.error('图片插入失败')
} }
}, },
handleUploadError() { handleUploadError () {
this.$message.error("图片插入失败"); this.$message.error('图片插入失败')
}, }
}, }
}; }
</script> </script>
<style> <style>

View File

@ -39,27 +39,27 @@
</template> </template>
<script> <script>
import { getToken } from "@/utils/auth"; import { getToken } from '@/utils/auth'
export default { export default {
name: "FileUpload", name: 'FileUpload',
props: { props: {
// 值 // 值
value: [String, Object, Array], value: [String, Object, Array],
// 数量限制 // 数量限制
limit: { limit: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 文件类型, 例如['png', 'jpg', 'jpeg'] // 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: { fileType: {
type: Array, type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf"], default: () => ['doc', 'xls', 'ppt', 'txt', 'pdf']
}, },
// 是否显示提示 // 是否显示提示
isShowTip: { isShowTip: {
@ -67,34 +67,34 @@ export default {
default: true default: true
} }
}, },
data() { data () {
return { return {
baseUrl: process.env.VUE_APP_BASE_API, baseUrl: process.env.VUE_APP_BASE_API,
uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 uploadFileUrl: process.env.VUE_APP_BASE_API + '/common/upload', // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: 'Bearer ' + getToken()
}, },
fileList: [], fileList: []
}; }
}, },
watch: { watch: {
value: { value: {
handler(val) { handler (val) {
if (val) { if (val) {
let temp = 1; let temp = 1
// 首先将值转为数组 // 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(','); const list = Array.isArray(val) ? val : this.value.split(',')
// 然后将数组转为对象数组 // 然后将数组转为对象数组
this.fileList = list.map(item => { this.fileList = list.map(item => {
if (typeof item === "string") { if (typeof item === 'string') {
item = { name: item, url: item }; item = { name: item, url: item }
} }
item.uid = item.uid || new Date().getTime() + temp++; item.uid = item.uid || new Date().getTime() + temp++
return item; return item
}); })
} else { } else {
this.fileList = []; this.fileList = []
return []; return []
} }
}, },
deep: true, deep: true,
@ -103,77 +103,77 @@ export default {
}, },
computed: { computed: {
// 是否显示提示 // 是否显示提示
showTip() { showTip () {
return this.isShowTip && (this.fileType || this.fileSize); return this.isShowTip && (this.fileType || this.fileSize)
}, }
}, },
methods: { methods: {
// 上传前校检格式和大小 // 上传前校检格式和大小
handleBeforeUpload(file) { handleBeforeUpload (file) {
// 校检文件类型 // 校检文件类型
if (this.fileType) { if (this.fileType) {
let fileExtension = ""; let fileExtension = ''
if (file.name.lastIndexOf(".") > -1) { if (file.name.lastIndexOf('.') > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
} }
const isTypeOk = this.fileType.some((type) => { const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true; if (file.type.indexOf(type) > -1) return true
if (fileExtension && fileExtension.indexOf(type) > -1) return true; if (fileExtension && fileExtension.indexOf(type) > -1) return true
return false; return false
}); })
if (!isTypeOk) { if (!isTypeOk) {
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`); this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
return false; return false
} }
} }
// 校检文件大小 // 校检文件大小
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`); this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
return true; return true
}, },
// 文件个数超出 // 文件个数超出
handleExceed() { handleExceed () {
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`); this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`)
}, },
// 上传失败 // 上传失败
handleUploadError(err) { handleUploadError () {
this.$message.error("上传失败, 请重试"); this.$message.error('上传失败, 请重试')
}, },
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res, file) { handleUploadSuccess (res, file) {
this.$message.success("上传成功"); this.$message.success('上传成功')
this.fileList.push({ name: res.fileName, url: res.fileName }); this.fileList.push({ name: res.fileName, url: res.fileName })
this.$emit("input", this.listToString(this.fileList)); this.$emit('input', this.listToString(this.fileList))
}, },
// 删除文件 // 删除文件
handleDelete(index) { handleDelete (index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1)
this.$emit("input", this.listToString(this.fileList)); this.$emit('input', this.listToString(this.fileList))
}, },
// 获取文件名称 // 获取文件名称
getFileName(name) { getFileName (name) {
if (name.lastIndexOf("/") > -1) { if (name.lastIndexOf('/') > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase(); return name.slice(name.lastIndexOf('/') + 1).toLowerCase()
} else { } else {
return ""; return ''
} }
}, },
// 对象转成指定字符串分隔 // 对象转成指定字符串分隔
listToString(list, separator) { listToString (list, separator) {
let strs = ""; let strs = ''
separator = separator || ","; separator = separator || ','
for (let i in list) { for (const i in list) {
strs += list[i].url + separator; strs += list[i].url + separator
} }
return strs != '' ? strs.substr(0, strs.length - 1) : ''; return strs !== '' ? strs.substr(0, strs.length - 1) : ''
} }
} }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -195,4 +195,4 @@ export default {
.ele-upload-list__item-content-action .el-link { .ele-upload-list__item-content-action .el-link {
margin-right: 10px; margin-right: 10px;
} }
</style> </style>

View File

@ -1,44 +1,44 @@
<template> <template>
<div style="padding: 0 15px;" @click="toggleClick"> <div style="padding: 0 15px;" @click="toggleClick">
<svg <svg
:class="{'is-active':isActive}" :class="{'is-active':isActive}"
class="hamburger" class="hamburger"
viewBox="0 0 1024 1024" viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="64" width="64"
height="64" height="64"
> >
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" /> <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
</svg> </svg>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Hamburger', name: 'Hamburger',
props: { props: {
isActive: { isActive: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
methods: { methods: {
toggleClick() { toggleClick () {
this.$emit('toggleClick') this.$emit('toggleClick')
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.hamburger { .hamburger {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
.hamburger.is-active { .hamburger.is-active {
transform: rotate(180deg); transform: rotate(180deg);
} }
</style> </style>

View File

@ -1,190 +1,190 @@
<template> <template>
<div :class="{'show':show}" class="header-search"> <div :class="{'show':show}" class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
<el-select <el-select
ref="headerSearchSelect" ref="headerSearchSelect"
v-model="search" v-model="search"
:remote-method="querySearch" :remote-method="querySearch"
filterable filterable
default-first-option default-first-option
remote remote
placeholder="Search" placeholder="Search"
class="header-search-select" class="header-search-select"
@change="change" @change="change"
> >
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
</el-select> </el-select>
</div> </div>
</template> </template>
<script> <script>
// fuse is a lightweight fuzzy-search module // fuse is a lightweight fuzzy-search module
// make search results more in line with expectations // make search results more in line with expectations
import Fuse from 'fuse.js/dist/fuse.min.js' import Fuse from 'fuse.js/dist/fuse.min.js'
import path from 'path' import path from 'path'
export default { export default {
name: 'HeaderSearch', name: 'HeaderSearch',
data() { data () {
return { return {
search: '', search: '',
options: [], options: [],
searchPool: [], searchPool: [],
show: false, show: false,
fuse: undefined fuse: undefined
} }
}, },
computed: { computed: {
routes() { routes () {
return this.$store.getters.permission_routes return this.$store.getters.permission_routes
} }
}, },
watch: { watch: {
routes() { routes () {
this.searchPool = this.generateRoutes(this.routes) this.searchPool = this.generateRoutes(this.routes)
}, },
searchPool(list) { searchPool (list) {
this.initFuse(list) this.initFuse(list)
}, },
show(value) { show (value) {
if (value) { if (value) {
document.body.addEventListener('click', this.close) document.body.addEventListener('click', this.close)
} else { } else {
document.body.removeEventListener('click', this.close) document.body.removeEventListener('click', this.close)
} }
} }
}, },
mounted() { mounted () {
this.searchPool = this.generateRoutes(this.routes) this.searchPool = this.generateRoutes(this.routes)
}, },
methods: { methods: {
click() { click () {
this.show = !this.show this.show = !this.show
if (this.show) { if (this.show) {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
} }
}, },
close() { close () {
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
this.options = [] this.options = []
this.show = false this.show = false
}, },
change(val) { change (val) {
const path = val.path; const path = val.path
if(this.ishttp(val.path)) { if (this.ishttp(val.path)) {
// http(s):// 路径新窗口打开 // http(s):// 路径新窗口打开
const pindex = path.indexOf("http"); const pindex = path.indexOf('http')
window.open(path.substr(pindex, path.length), "_blank"); window.open(path.substr(pindex, path.length), '_blank')
} else { } else {
this.$router.push(val.path) this.$router.push(val.path)
} }
this.search = '' this.search = ''
this.options = [] this.options = []
this.$nextTick(() => { this.$nextTick(() => {
this.show = false this.show = false
}) })
}, },
initFuse(list) { initFuse (list) {
this.fuse = new Fuse(list, { this.fuse = new Fuse(list, {
shouldSort: true, shouldSort: true,
threshold: 0.4, threshold: 0.4,
location: 0, location: 0,
distance: 100, distance: 100,
maxPatternLength: 32, maxPatternLength: 32,
minMatchCharLength: 1, minMatchCharLength: 1,
keys: [{ keys: [{
name: 'title', name: 'title',
weight: 0.7 weight: 0.7
}, { }, {
name: 'path', name: 'path',
weight: 0.3 weight: 0.3
}] }]
}) })
}, },
// Filter out the routes that can be displayed in the sidebar // Filter out the routes that can be displayed in the sidebar
// And generate the internationalized title // And generate the internationalized title
generateRoutes(routes, basePath = '/', prefixTitle = []) { generateRoutes (routes, basePath = '/', prefixTitle = []) {
let res = [] let res = []
for (const router of routes) { for (const router of routes) {
// skip hidden router // skip hidden router
if (router.hidden) { continue } if (router.hidden) { continue }
const data = { const data = {
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
title: [...prefixTitle] title: [...prefixTitle]
} }
if (router.meta && router.meta.title) { if (router.meta && router.meta.title) {
data.title = [...data.title, router.meta.title] data.title = [...data.title, router.meta.title]
if (router.redirect !== 'noRedirect') { if (router.redirect !== 'noRedirect') {
// only push the routes with title // only push the routes with title
// special case: need to exclude parent router without redirect // special case: need to exclude parent router without redirect
res.push(data) res.push(data)
} }
} }
// recursive child routes // recursive child routes
if (router.children) { if (router.children) {
const tempRoutes = this.generateRoutes(router.children, data.path, data.title) const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
if (tempRoutes.length >= 1) { if (tempRoutes.length >= 1) {
res = [...res, ...tempRoutes] res = [...res, ...tempRoutes]
} }
} }
} }
return res return res
}, },
querySearch(query) { querySearch (query) {
if (query !== '') { if (query !== '') {
this.options = this.fuse.search(query) this.options = this.fuse.search(query)
} else { } else {
this.options = [] this.options = []
} }
}, },
ishttp(url) { ishttp (url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.header-search { .header-search {
font-size: 0 !important; font-size: 0 !important;
.search-icon { .search-icon {
cursor: pointer; cursor: pointer;
font-size: 18px; font-size: 18px;
vertical-align: middle; vertical-align: middle;
} }
.header-search-select { .header-search-select {
font-size: 18px; font-size: 18px;
transition: width 0.2s; transition: width 0.2s;
width: 0; width: 0;
overflow: hidden; overflow: hidden;
background: transparent; background: transparent;
border-radius: 0; border-radius: 0;
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
::v-deep .el-input__inner { ::v-deep .el-input__inner {
border-radius: 0; border-radius: 0;
border: 0; border: 0;
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
box-shadow: none !important; box-shadow: none !important;
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
vertical-align: middle; vertical-align: middle;
} }
} }
&.show { &.show {
.header-search-select { .header-search-select {
width: 210px; width: 210px;
margin-left: 10px; margin-left: 10px;
} }
} }
} }
</style> </style>

View File

@ -1,68 +1,68 @@
<!-- @author zhengjie --> <!-- @author zhengjie -->
<template> <template>
<div class="icon-body"> <div class="icon-body">
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons"> <el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons">
<i slot="suffix" class="el-icon-search el-input__icon" /> <i slot="suffix" class="el-icon-search el-input__icon" />
</el-input> </el-input>
<div class="icon-list"> <div class="icon-list">
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)"> <div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)">
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" /> <svg-icon :icon-class="item" style="height: 30px;width: 16px;" />
<span>{{ item }}</span> <span>{{ item }}</span>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import icons from './requireIcons' import icons from './requireIcons'
export default { export default {
name: 'IconSelect', name: 'IconSelect',
data() { data () {
return { return {
name: '', name: '',
iconList: icons iconList: icons
} }
}, },
methods: { methods: {
filterIcons() { filterIcons () {
this.iconList = icons this.iconList = icons
if (this.name) { if (this.name) {
this.iconList = this.iconList.filter(item => item.includes(this.name)) this.iconList = this.iconList.filter(item => item.includes(this.name))
} }
}, },
selectedIcon(name) { selectedIcon (name) {
this.$emit('selected', name) this.$emit('selected', name)
document.body.click() document.body.click()
}, },
reset() { reset () {
this.name = '' this.name = ''
this.iconList = icons this.iconList = icons
} }
} }
} }
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.icon-body { .icon-body {
width: 100%; width: 100%;
padding: 10px; padding: 10px;
.icon-list { .icon-list {
height: 200px; height: 200px;
overflow-y: scroll; overflow-y: scroll;
div { div {
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
margin-bottom: -5px; margin-bottom: -5px;
cursor: pointer; cursor: pointer;
width: 33%; width: 33%;
float: left; float: left;
} }
span { span {
display: inline-block; display: inline-block;
vertical-align: -0.15em; vertical-align: -0.15em;
fill: currentColor; fill: currentColor;
overflow: hidden; overflow: hidden;
} }
} }
} }
</style> </style>

View File

@ -1,11 +1,11 @@
const req = require.context('../../assets/icons/svg', false, /\.svg$/) const req = require.context('../../assets/icons/svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys() const requireAll = requireContext => requireContext.keys()
const re = /\.\/(.*)\.svg/ const re = /\.\/(.*)\.svg/
const icons = requireAll(req).map(i => { const icons = requireAll(req).map(i => {
return i.match(re)[1] return i.match(re)[1]
}) })
export default icons export default icons

View File

@ -18,7 +18,7 @@
> >
<i class="el-icon-plus"></i> <i class="el-icon-plus"></i>
</el-upload> </el-upload>
<!-- 上传提示 --> <!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip"> <div class="el-upload__tip" slot="tip" v-if="showTip">
请上传 请上传
@ -42,7 +42,7 @@
</template> </template>
<script> <script>
import { getToken } from "@/utils/auth"; import { getToken } from '@/utils/auth'
export default { export default {
props: { props: {
@ -50,17 +50,17 @@ export default {
// 图片数量限制 // 图片数量限制
limit: { limit: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 文件类型, 例如['png', 'jpg', 'jpeg'] // 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: { fileType: {
type: Array, type: Array,
default: () => ["png", "jpg", "jpeg"], default: () => ['png', 'jpg', 'jpeg']
}, },
// 是否显示提示 // 是否显示提示
isShowTip: { isShowTip: {
@ -68,39 +68,39 @@ export default {
default: true default: true
} }
}, },
data() { data () {
return { return {
dialogImageUrl: "", dialogImageUrl: '',
dialogVisible: false, dialogVisible: false,
hideUpload: false, hideUpload: false,
baseUrl: process.env.VUE_APP_BASE_API, baseUrl: process.env.VUE_APP_BASE_API,
uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 uploadImgUrl: process.env.VUE_APP_BASE_API + '/common/upload', // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: 'Bearer ' + getToken()
}, },
fileList: [] fileList: []
}; }
}, },
watch: { watch: {
value: { value: {
handler(val) { handler (val) {
if (val) { if (val) {
// 首先将值转为数组 // 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(','); const list = Array.isArray(val) ? val : this.value.split(',')
// 然后将数组转为对象数组 // 然后将数组转为对象数组
this.fileList = list.map(item => { this.fileList = list.map(item => {
if (typeof item === "string") { if (typeof item === 'string') {
if (item.indexOf(this.baseUrl) === -1) { if (item.indexOf(this.baseUrl) === -1) {
item = { name: this.baseUrl + item, url: this.baseUrl + item }; item = { name: this.baseUrl + item, url: this.baseUrl + item }
} else { } else {
item = { name: item, url: item }; item = { name: item, url: item }
} }
} }
return item; return item
}); })
} else { } else {
this.fileList = []; this.fileList = []
return []; return []
} }
}, },
deep: true, deep: true,
@ -109,87 +109,87 @@ export default {
}, },
computed: { computed: {
// 是否显示提示 // 是否显示提示
showTip() { showTip () {
return this.isShowTip && (this.fileType || this.fileSize); return this.isShowTip && (this.fileType || this.fileSize)
}, }
}, },
methods: { methods: {
// 删除图片 // 删除图片
handleRemove(file, fileList) { handleRemove (file, fileList) {
const findex = this.fileList.map(f => f.name).indexOf(file.name); const findex = this.fileList.map(f => f.name).indexOf(file.name)
this.fileList.splice(findex, 1); this.fileList.splice(findex, 1)
this.$emit("input", this.listToString(this.fileList)); this.$emit('input', this.listToString(this.fileList))
}, },
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res) { handleUploadSuccess (res) {
this.fileList.push({ name: res.fileName, url: res.fileName }); this.fileList.push({ name: res.fileName, url: res.fileName })
this.$emit("input", this.listToString(this.fileList)); this.$emit('input', this.listToString(this.fileList))
this.loading.close(); this.loading.close()
}, },
// 上传前loading加载 // 上传前loading加载
handleBeforeUpload(file) { handleBeforeUpload (file) {
let isImg = false; let isImg = false
if (this.fileType.length) { if (this.fileType.length) {
let fileExtension = ""; let fileExtension = ''
if (file.name.lastIndexOf(".") > -1) { if (file.name.lastIndexOf('.') > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
} }
isImg = this.fileType.some(type => { isImg = this.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true; if (file.type.indexOf(type) > -1) return true
if (fileExtension && fileExtension.indexOf(type) > -1) return true; if (fileExtension && fileExtension.indexOf(type) > -1) return true
return false; return false
}); })
} else { } else {
isImg = file.type.indexOf("image") > -1; isImg = file.type.indexOf('image') > -1
} }
if (!isImg) { if (!isImg) {
this.$message.error( this.$message.error(
`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!` `文件格式不正确, 请上传${this.fileType.join('/')}图片格式文件!`
); )
return false; return false
} }
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`); this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
this.loading = this.$loading({ this.loading = this.$loading({
lock: true, lock: true,
text: "上传中", text: '上传中',
background: "rgba(0, 0, 0, 0.7)", background: 'rgba(0, 0, 0, 0.7)'
}); })
}, },
// 文件个数超出 // 文件个数超出
handleExceed() { handleExceed () {
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`); this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`)
}, },
// 上传失败 // 上传失败
handleUploadError() { handleUploadError () {
this.$message({ this.$message({
type: "error", type: 'error',
message: "上传失败", message: '上传失败'
}); })
this.loading.close(); this.loading.close()
}, },
// 预览 // 预览
handlePictureCardPreview(file) { handlePictureCardPreview (file) {
this.dialogImageUrl = file.url; this.dialogImageUrl = file.url
this.dialogVisible = true; this.dialogVisible = true
}, },
// 对象转成指定字符串分隔 // 对象转成指定字符串分隔
listToString(list, separator) { listToString (list, separator) {
let strs = ""; let strs = ''
separator = separator || ","; separator = separator || ','
for (let i in list) { for (const i in list) {
strs += list[i].url.replace(this.baseUrl, "") + separator; strs += list[i].url.replace(this.baseUrl, '') + separator
} }
return strs != '' ? strs.substr(0, strs.length - 1) : ''; return strs !== '' ? strs.substr(0, strs.length - 1) : ''
} }
} }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
// .el-upload--picture-card 控制加号部分 // .el-upload--picture-card 控制加号部分
@ -207,4 +207,3 @@ export default {
transform: translateY(0); transform: translateY(0);
} }
</style> </style>

View File

@ -1,107 +1,107 @@
<template> <template>
<div :class="{'hidden':hidden}" class="pagination-container"> <div :class="{'hidden':hidden}" class="pagination-container">
<el-pagination <el-pagination
:background="background" :background="background"
:current-page.sync="currentPage" :current-page.sync="currentPage"
:page-size.sync="pageSize" :page-size.sync="pageSize"
:layout="layout" :layout="layout"
:page-sizes="pageSizes" :page-sizes="pageSizes"
:pager-count="pagerCount" :pager-count="pagerCount"
:total="total" :total="total"
v-bind="$attrs" v-bind="$attrs"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
/> />
</div> </div>
</template> </template>
<script> <script>
import { scrollTo } from '@/utils/scroll-to' import { scrollTo } from '@/utils/scroll-to'
export default { export default {
name: 'Pagination', name: 'Pagination',
props: { props: {
total: { total: {
required: true, required: true,
type: Number type: Number
}, },
page: { page: {
type: Number, type: Number,
default: 1 default: 1
}, },
limit: { limit: {
type: Number, type: Number,
default: 20 default: 20
}, },
pageSizes: { pageSizes: {
type: Array, type: Array,
default() { default () {
return [10, 20, 30, 50] return [10, 20, 30, 50]
} }
}, },
// 移动端页码按钮的数量端默认值5 // 移动端页码按钮的数量端默认值5
pagerCount: { pagerCount: {
type: Number, type: Number,
default: document.body.clientWidth < 992 ? 5 : 7 default: document.body.clientWidth < 992 ? 5 : 7
}, },
layout: { layout: {
type: String, type: String,
default: 'total, sizes, prev, pager, next, jumper' default: 'total, sizes, prev, pager, next, jumper'
}, },
background: { background: {
type: Boolean, type: Boolean,
default: true default: true
}, },
autoScroll: { autoScroll: {
type: Boolean, type: Boolean,
default: true default: true
}, },
hidden: { hidden: {
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
computed: { computed: {
currentPage: { currentPage: {
get() { get () {
return this.page return this.page
}, },
set(val) { set (val) {
this.$emit('update:page', val) this.$emit('update:page', val)
} }
}, },
pageSize: { pageSize: {
get() { get () {
return this.limit return this.limit
}, },
set(val) { set (val) {
this.$emit('update:limit', val) this.$emit('update:limit', val)
} }
} }
}, },
methods: { methods: {
handleSizeChange(val) { handleSizeChange (val) {
this.$emit('pagination', { page: this.currentPage, limit: val }) this.$emit('pagination', { page: this.currentPage, limit: val })
if (this.autoScroll) { if (this.autoScroll) {
scrollTo(0, 800) scrollTo(0, 800)
} }
}, },
handleCurrentChange(val) { handleCurrentChange (val) {
this.$emit('pagination', { page: val, limit: this.pageSize }) this.$emit('pagination', { page: val, limit: this.pageSize })
if (this.autoScroll) { if (this.autoScroll) {
scrollTo(0, 800) scrollTo(0, 800)
} }
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.pagination-container { .pagination-container {
background: #fff; background: #fff;
padding: 32px 16px; padding: 32px 16px;
} }
.pagination-container.hidden { .pagination-container.hidden {
display: none; display: none;
} }
</style> </style>

View File

@ -1,142 +1,142 @@
<template> <template>
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item"> <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
<div class="pan-info"> <div class="pan-info">
<div class="pan-info-roles-container"> <div class="pan-info-roles-container">
<slot /> <slot />
</div> </div>
</div> </div>
<!-- eslint-disable-next-line --> <!-- eslint-disable-next-line -->
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div> <div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'PanThumb', name: 'PanThumb',
props: { props: {
image: { image: {
type: String, type: String,
required: true required: true
}, },
zIndex: { zIndex: {
type: Number, type: Number,
default: 1 default: 1
}, },
width: { width: {
type: String, type: String,
default: '150px' default: '150px'
}, },
height: { height: {
type: String, type: String,
default: '150px' default: '150px'
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.pan-item { .pan-item {
width: 200px; width: 200px;
height: 200px; height: 200px;
border-radius: 50%; border-radius: 50%;
display: inline-block; display: inline-block;
position: relative; position: relative;
cursor: default; cursor: default;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
} }
.pan-info-roles-container { .pan-info-roles-container {
padding: 20px; padding: 20px;
text-align: center; text-align: center;
} }
.pan-thumb { .pan-thumb {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-position: center center; background-position: center center;
background-size: cover; background-size: cover;
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
transform-origin: 95% 40%; transform-origin: 95% 40%;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
/* .pan-thumb:after { /* .pan-thumb:after {
content: ''; content: '';
width: 8px; width: 8px;
height: 8px; height: 8px;
position: absolute; position: absolute;
border-radius: 50%; border-radius: 50%;
top: 40%; top: 40%;
left: 95%; left: 95%;
margin: -4px 0 0 -4px; margin: -4px 0 0 -4px;
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%); background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9); box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
} */ } */
.pan-info { .pan-info {
position: absolute; position: absolute;
width: inherit; width: inherit;
height: inherit; height: inherit;
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05); box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
} }
.pan-info h3 { .pan-info h3 {
color: #fff; color: #fff;
text-transform: uppercase; text-transform: uppercase;
position: relative; position: relative;
letter-spacing: 2px; letter-spacing: 2px;
font-size: 18px; font-size: 18px;
margin: 0 60px; margin: 0 60px;
padding: 22px 0 0 0; padding: 22px 0 0 0;
height: 85px; height: 85px;
font-family: 'Open Sans', Arial, sans-serif; font-family: 'Open Sans', Arial, sans-serif;
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3); text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
} }
.pan-info p { .pan-info p {
color: #fff; color: #fff;
padding: 10px 5px; padding: 10px 5px;
font-style: italic; font-style: italic;
margin: 0 30px; margin: 0 30px;
font-size: 12px; font-size: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.5); border-top: 1px solid rgba(255, 255, 255, 0.5);
} }
.pan-info p a { .pan-info p a {
display: block; display: block;
color: #333; color: #333;
width: 80px; width: 80px;
height: 80px; height: 80px;
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
border-radius: 50%; border-radius: 50%;
color: #fff; color: #fff;
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
font-size: 9px; font-size: 9px;
letter-spacing: 1px; letter-spacing: 1px;
padding-top: 24px; padding-top: 24px;
margin: 7px auto 0; margin: 7px auto 0;
font-family: 'Open Sans', Arial, sans-serif; font-family: 'Open Sans', Arial, sans-serif;
opacity: 0; opacity: 0;
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s; transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
transform: translateX(60px) rotate(90deg); transform: translateX(60px) rotate(90deg);
} }
.pan-info p a:hover { .pan-info p a:hover {
background: rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.5);
} }
.pan-item:hover .pan-thumb { .pan-item:hover .pan-thumb {
transform: rotate(-110deg); transform: rotate(-110deg);
} }
.pan-item:hover .pan-info p a { .pan-item:hover .pan-info p a {
opacity: 1; opacity: 1;
transform: translateX(0px) rotate(0deg); transform: translateX(0px) rotate(0deg);
} }
</style> </style>

View File

@ -1,149 +1,149 @@
<template> <template>
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container"> <div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
<div class="rightPanel-background" /> <div class="rightPanel-background" />
<div class="rightPanel"> <div class="rightPanel">
<div class="rightPanel-items"> <div class="rightPanel-items">
<slot /> <slot />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { addClass, removeClass } from '@/utils' import { addClass, removeClass } from '@/utils'
export default { export default {
name: 'RightPanel', name: 'RightPanel',
props: { props: {
clickNotClose: { clickNotClose: {
default: false, default: false,
type: Boolean type: Boolean
}, },
buttonTop: { buttonTop: {
default: 250, default: 250,
type: Number type: Number
} }
}, },
computed: { computed: {
show: { show: {
get() { get () {
return this.$store.state.settings.showSettings return this.$store.state.settings.showSettings
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'showSettings', key: 'showSettings',
value: val value: val
}) })
} }
}, },
theme() { theme () {
return this.$store.state.settings.theme return this.$store.state.settings.theme
}, }
}, },
watch: { watch: {
show(value) { show (value) {
if (value && !this.clickNotClose) { if (value && !this.clickNotClose) {
this.addEventClick() this.addEventClick()
} }
if (value) { if (value) {
addClass(document.body, 'showRightPanel') addClass(document.body, 'showRightPanel')
} else { } else {
removeClass(document.body, 'showRightPanel') removeClass(document.body, 'showRightPanel')
} }
} }
}, },
mounted() { mounted () {
this.insertToBody() this.insertToBody()
this.addEventClick() this.addEventClick()
}, },
beforeDestroy() { beforeDestroy () {
const elx = this.$refs.rightPanel const elx = this.$refs.rightPanel
elx.remove() elx.remove()
}, },
methods: { methods: {
addEventClick() { addEventClick () {
window.addEventListener('click', this.closeSidebar) window.addEventListener('click', this.closeSidebar)
}, },
closeSidebar(evt) { closeSidebar (evt) {
const parent = evt.target.closest('.rightPanel') const parent = evt.target.closest('.rightPanel')
if (!parent) { if (!parent) {
this.show = false this.show = false
window.removeEventListener('click', this.closeSidebar) window.removeEventListener('click', this.closeSidebar)
} }
}, },
insertToBody() { insertToBody () {
const elx = this.$refs.rightPanel const elx = this.$refs.rightPanel
const body = document.querySelector('body') const body = document.querySelector('body')
body.insertBefore(elx, body.firstChild) body.insertBefore(elx, body.firstChild)
} }
} }
} }
</script> </script>
<style> <style>
.showRightPanel { .showRightPanel {
overflow: hidden; overflow: hidden;
position: relative; position: relative;
width: calc(100% - 15px); width: calc(100% - 15px);
} }
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>
.rightPanel-background { .rightPanel-background {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
opacity: 0; opacity: 0;
transition: opacity .3s cubic-bezier(.7, .3, .1, 1); transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
background: rgba(0, 0, 0, .2); background: rgba(0, 0, 0, .2);
z-index: -1; z-index: -1;
} }
.rightPanel { .rightPanel {
width: 100%; width: 100%;
max-width: 260px; max-width: 260px;
height: 100vh; height: 100vh;
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05); box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
transition: all .25s cubic-bezier(.7, .3, .1, 1); transition: all .25s cubic-bezier(.7, .3, .1, 1);
transform: translate(100%); transform: translate(100%);
background: #fff; background: #fff;
z-index: 40000; z-index: 40000;
} }
.show { .show {
transition: all .3s cubic-bezier(.7, .3, .1, 1); transition: all .3s cubic-bezier(.7, .3, .1, 1);
.rightPanel-background { .rightPanel-background {
z-index: 20000; z-index: 20000;
opacity: 1; opacity: 1;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.rightPanel { .rightPanel {
transform: translate(0); transform: translate(0);
} }
} }
.handle-button { .handle-button {
width: 48px; width: 48px;
height: 48px; height: 48px;
position: absolute; position: absolute;
left: -48px; left: -48px;
text-align: center; text-align: center;
font-size: 24px; font-size: 24px;
border-radius: 6px 0 0 6px !important; border-radius: 6px 0 0 6px !important;
z-index: 0; z-index: 0;
pointer-events: auto; pointer-events: auto;
cursor: pointer; cursor: pointer;
color: #fff; color: #fff;
line-height: 48px; line-height: 48px;
i { i {
font-size: 24px; font-size: 24px;
line-height: 48px; line-height: 48px;
} }
} }
</style> </style>

View File

@ -1,87 +1,87 @@
<template> <template>
<div class="top-right-btn"> <div class="top-right-btn">
<el-row> <el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top"> <el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" /> <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip> </el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top"> <el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" /> <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
</el-tooltip> </el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns"> <el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
<el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" /> <el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" />
</el-tooltip> </el-tooltip>
</el-row> </el-row>
<el-dialog :title="title" :visible.sync="open" append-to-body> <el-dialog :title="title" :visible.sync="open" append-to-body>
<el-transfer <el-transfer
:titles="['显示', '隐藏']" :titles="['显示', '隐藏']"
v-model="value" v-model="value"
:data="columns" :data="columns"
@change="dataChange" @change="dataChange"
></el-transfer> ></el-transfer>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: "RightToolbar", name: 'RightToolbar',
data() { data () {
return { return {
// 显隐数据 // 显隐数据
value: [], value: [],
// 弹出层标题 // 弹出层标题
title: "显示/隐藏", title: '显示/隐藏',
// 是否显示弹出层 // 是否显示弹出层
open: false, open: false
}; }
}, },
props: { props: {
showSearch: { showSearch: {
type: Boolean, type: Boolean,
default: true, default: true
}, },
columns: { columns: {
type: Array, type: Array
}, }
}, },
created() { created () {
// 显隐列初始默认隐藏列 // 显隐列初始默认隐藏列
for (let item in this.columns) { for (const item in this.columns) {
if (this.columns[item].visible === false) { if (this.columns[item].visible === false) {
this.value.push(parseInt(item)); this.value.push(parseInt(item))
} }
} }
}, },
methods: { methods: {
// 搜索 // 搜索
toggleSearch() { toggleSearch () {
this.$emit("update:showSearch", !this.showSearch); this.$emit('update:showSearch', !this.showSearch)
}, },
// 刷新 // 刷新
refresh() { refresh () {
this.$emit("queryTable"); this.$emit('queryTable')
}, },
// 右侧列表元素变化 // 右侧列表元素变化
dataChange(data) { dataChange (data) {
for (var item in this.columns) { for (const item in this.columns) {
const key = this.columns[item].key; const key = this.columns[item].key
this.columns[item].visible = !data.includes(key); this.columns[item].visible = !data.includes(key)
} }
}, },
// 打开显隐列dialog // 打开显隐列dialog
showColumn() { showColumn () {
this.open = true; this.open = true
}, }
}, }
}; }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
::v-deep .el-transfer__button { ::v-deep .el-transfer__button {
border-radius: 50%; border-radius: 50%;
padding: 12px; padding: 12px;
display: block; display: block;
margin-left: 0px; margin-left: 0px;
} }
::v-deep .el-transfer__button:first-child { ::v-deep .el-transfer__button:first-child {
margin-bottom: 10px; margin-bottom: 10px;
} }
</style> </style>

View File

@ -7,15 +7,15 @@
<script> <script>
export default { export default {
name: 'RuoYiDoc', name: 'RuoYiDoc',
data() { data () {
return { return {
url: 'http://doc.ruoyi.vip/ruoyi-vue' url: 'http://doc.ruoyi.vip/ruoyi-vue'
} }
}, },
methods: { methods: {
goto() { goto () {
window.open(this.url) window.open(this.url)
} }
} }
} }
</script> </script>

View File

@ -7,15 +7,15 @@
<script> <script>
export default { export default {
name: 'RuoYiGit', name: 'RuoYiGit',
data() { data () {
return { return {
url: 'https://gitee.com/y_project/RuoYi-Vue' url: 'https://gitee.com/y_project/RuoYi-Vue'
} }
}, },
methods: { methods: {
goto() { goto () {
window.open(this.url) window.open(this.url)
} }
} }
} }
</script> </script>

View File

@ -1,57 +1,57 @@
<template> <template>
<div> <div>
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" /> <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
</div> </div>
</template> </template>
<script> <script>
import screenfull from 'screenfull' import screenfull from 'screenfull'
export default { export default {
name: 'Screenfull', name: 'Screenfull',
data() { data () {
return { return {
isFullscreen: false isFullscreen: false
} }
}, },
mounted() { mounted () {
this.init() this.init()
}, },
beforeDestroy() { beforeDestroy () {
this.destroy() this.destroy()
}, },
methods: { methods: {
click() { click () {
if (!screenfull.isEnabled) { if (!screenfull.isEnabled) {
this.$message({ message: '你的浏览器不支持全屏', type: 'warning' }) this.$message({ message: '你的浏览器不支持全屏', type: 'warning' })
return false return false
} }
screenfull.toggle() screenfull.toggle()
}, },
change() { change () {
this.isFullscreen = screenfull.isFullscreen this.isFullscreen = screenfull.isFullscreen
}, },
init() { init () {
if (screenfull.isEnabled) { if (screenfull.isEnabled) {
screenfull.on('change', this.change) screenfull.on('change', this.change)
} }
}, },
destroy() { destroy () {
if (screenfull.isEnabled) { if (screenfull.isEnabled) {
screenfull.off('change', this.change) screenfull.off('change', this.change)
} }
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.screenfull-svg { .screenfull-svg {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
fill: #5a5e66;; fill: #5a5e66;;
width: 20px; width: 20px;
height: 20px; height: 20px;
vertical-align: 10px; vertical-align: 10px;
} }
</style> </style>

View File

@ -1,57 +1,57 @@
<template> <template>
<el-dropdown trigger="click" @command="handleSetSize"> <el-dropdown trigger="click" @command="handleSetSize">
<div> <div>
<svg-icon class-name="size-icon" icon-class="size" /> <svg-icon class-name="size-icon" icon-class="size" />
</div> </div>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value"> <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
{{ {{
item.label }} item.label }}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
<script> <script>
export default { export default {
data() { data () {
return { return {
sizeOptions: [ sizeOptions: [
{ label: 'Default', value: 'default' }, { label: 'Default', value: 'default' },
{ label: 'Medium', value: 'medium' }, { label: 'Medium', value: 'medium' },
{ label: 'Small', value: 'small' }, { label: 'Small', value: 'small' },
{ label: 'Mini', value: 'mini' } { label: 'Mini', value: 'mini' }
] ]
} }
}, },
computed: { computed: {
size() { size () {
return this.$store.getters.size return this.$store.getters.size
} }
}, },
methods: { methods: {
handleSetSize(size) { handleSetSize (size) {
this.$ELEMENT.size = size this.$ELEMENT.size = size
this.$store.dispatch('app/setSize', size) this.$store.dispatch('app/setSize', size)
this.refreshView() this.refreshView()
this.$message({ this.$message({
message: 'Switch Size Success', message: 'Switch Size Success',
type: 'success' type: 'success'
}) })
}, },
refreshView() { refreshView () {
// In order to make the cached page re-rendered // In order to make the cached page re-rendered
this.$store.dispatch('tagsView/delAllCachedViews', this.$route) this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
const { fullPath } = this.$route const { fullPath } = this.$route
this.$nextTick(() => { this.$nextTick(() => {
this.$router.replace({ this.$router.replace({
path: '/redirect' + fullPath path: '/redirect' + fullPath
}) })
}) })
} }
} }
} }
</script> </script>

View File

@ -1,61 +1,61 @@
<template> <template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" /> <use :xlink:href="iconName" />
</svg> </svg>
</template> </template>
<script> <script>
import { isExternal } from '@/utils/validate' import { isExternal } from '@/utils/validate'
export default { export default {
name: 'SvgIcon', name: 'SvgIcon',
props: { props: {
iconClass: { iconClass: {
type: String, type: String,
required: true required: true
}, },
className: { className: {
type: String, type: String,
default: '' default: ''
} }
}, },
computed: { computed: {
isExternal() { isExternal () {
return isExternal(this.iconClass) return isExternal(this.iconClass)
}, },
iconName() { iconName () {
return `#icon-${this.iconClass}` return `#icon-${this.iconClass}`
}, },
svgClass() { svgClass () {
if (this.className) { if (this.className) {
return 'svg-icon ' + this.className return 'svg-icon ' + this.className
} else { } else {
return 'svg-icon' return 'svg-icon'
} }
}, },
styleExternalIcon() { styleExternalIcon () {
return { return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`, mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
} }
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.svg-icon { .svg-icon {
width: 1em; width: 1em;
height: 1em; height: 1em;
vertical-align: -0.15em; vertical-align: -0.15em;
fill: currentColor; fill: currentColor;
overflow: hidden; overflow: hidden;
} }
.svg-external-icon { .svg-external-icon {
background-color: currentColor; background-color: currentColor;
mask-size: cover!important; mask-size: cover!important;
display: inline-block; display: inline-block;
} }
</style> </style>

View File

@ -1,174 +1,174 @@
<template> <template>
<el-color-picker <el-color-picker
v-model="theme" v-model="theme"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]" :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker" class="theme-picker"
popper-class="theme-picker-dropdown" popper-class="theme-picker-dropdown"
/> />
</template> </template>
<script> <script>
const version = require('element-ui/package.json').version // element-ui version from node_modules const version = require('element-ui/package.json').version // element-ui version from node_modules
const ORIGINAL_THEME = '#409EFF' // default color const ORIGINAL_THEME = '#409EFF' // default color
export default { export default {
data() { data () {
return { return {
chalk: '', // content of theme-chalk css chalk: '', // content of theme-chalk css
theme: '' theme: ''
} }
}, },
computed: { computed: {
defaultTheme() { defaultTheme () {
return this.$store.state.settings.theme return this.$store.state.settings.theme
} }
}, },
watch: { watch: {
defaultTheme: { defaultTheme: {
handler: function(val, oldVal) { handler: function (val, oldVal) {
this.theme = val this.theme = val
}, },
immediate: true immediate: true
}, },
async theme(val) { async theme (val) {
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
if (typeof val !== 'string') return if (typeof val !== 'string') return
const themeCluster = this.getThemeCluster(val.replace('#', '')) const themeCluster = this.getThemeCluster(val.replace('#', ''))
const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
const $message = this.$message({ const $message = this.$message({
message: ' Compiling the theme', message: ' Compiling the theme',
customClass: 'theme-message', customClass: 'theme-message',
type: 'success', type: 'success',
duration: 0, duration: 0,
iconClass: 'el-icon-loading' iconClass: 'el-icon-loading'
}) })
const getHandler = (variable, id) => { const getHandler = (variable, id) => {
return () => { return () => {
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
let styleTag = document.getElementById(id) let styleTag = document.getElementById(id)
if (!styleTag) { if (!styleTag) {
styleTag = document.createElement('style') styleTag = document.createElement('style')
styleTag.setAttribute('id', id) styleTag.setAttribute('id', id)
document.head.appendChild(styleTag) document.head.appendChild(styleTag)
} }
styleTag.innerText = newStyle styleTag.innerText = newStyle
} }
} }
if (!this.chalk) { if (!this.chalk) {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
await this.getCSSString(url, 'chalk') await this.getCSSString(url, 'chalk')
} }
const chalkHandler = getHandler('chalk', 'chalk-style') const chalkHandler = getHandler('chalk', 'chalk-style')
chalkHandler() chalkHandler()
const styles = [].slice.call(document.querySelectorAll('style')) const styles = [].slice.call(document.querySelectorAll('style'))
.filter(style => { .filter(style => {
const text = style.innerText const text = style.innerText
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
}) })
styles.forEach(style => { styles.forEach(style => {
const { innerText } = style const { innerText } = style
if (typeof innerText !== 'string') return if (typeof innerText !== 'string') return
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
}) })
this.$emit('change', val) this.$emit('change', val)
$message.close() $message.close()
} }
}, },
methods: { methods: {
updateStyle(style, oldCluster, newCluster) { updateStyle (style, oldCluster, newCluster) {
let newStyle = style let newStyle = style
oldCluster.forEach((color, index) => { oldCluster.forEach((color, index) => {
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
}) })
return newStyle return newStyle
}, },
getCSSString(url, variable) { getCSSString (url, variable) {
return new Promise(resolve => { return new Promise(resolve => {
const xhr = new XMLHttpRequest() const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => { xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) { if (xhr.readyState === 4 && xhr.status === 200) {
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
resolve() resolve()
} }
} }
xhr.open('GET', url) xhr.open('GET', url)
xhr.send() xhr.send()
}) })
}, },
getThemeCluster(theme) { getThemeCluster (theme) {
const tintColor = (color, tint) => { const tintColor = (color, tint) => {
let red = parseInt(color.slice(0, 2), 16) let red = parseInt(color.slice(0, 2), 16)
let green = parseInt(color.slice(2, 4), 16) let green = parseInt(color.slice(2, 4), 16)
let blue = parseInt(color.slice(4, 6), 16) let blue = parseInt(color.slice(4, 6), 16)
if (tint === 0) { // when primary color is in its rgb space if (tint === 0) { // when primary color is in its rgb space
return [red, green, blue].join(',') return [red, green, blue].join(',')
} else { } else {
red += Math.round(tint * (255 - red)) red += Math.round(tint * (255 - red))
green += Math.round(tint * (255 - green)) green += Math.round(tint * (255 - green))
blue += Math.round(tint * (255 - blue)) blue += Math.round(tint * (255 - blue))
red = red.toString(16) red = red.toString(16)
green = green.toString(16) green = green.toString(16)
blue = blue.toString(16) blue = blue.toString(16)
return `#${red}${green}${blue}` return `#${red}${green}${blue}`
} }
} }
const shadeColor = (color, shade) => { const shadeColor = (color, shade) => {
let red = parseInt(color.slice(0, 2), 16) let red = parseInt(color.slice(0, 2), 16)
let green = parseInt(color.slice(2, 4), 16) let green = parseInt(color.slice(2, 4), 16)
let blue = parseInt(color.slice(4, 6), 16) let blue = parseInt(color.slice(4, 6), 16)
red = Math.round((1 - shade) * red) red = Math.round((1 - shade) * red)
green = Math.round((1 - shade) * green) green = Math.round((1 - shade) * green)
blue = Math.round((1 - shade) * blue) blue = Math.round((1 - shade) * blue)
red = red.toString(16) red = red.toString(16)
green = green.toString(16) green = green.toString(16)
blue = blue.toString(16) blue = blue.toString(16)
return `#${red}${green}${blue}` return `#${red}${green}${blue}`
} }
const clusters = [theme] const clusters = [theme]
for (let i = 0; i <= 9; i++) { for (let i = 0; i <= 9; i++) {
clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
} }
clusters.push(shadeColor(theme, 0.1)) clusters.push(shadeColor(theme, 0.1))
return clusters return clusters
} }
} }
} }
</script> </script>
<style> <style>
.theme-message, .theme-message,
.theme-picker-dropdown { .theme-picker-dropdown {
z-index: 99999 !important; z-index: 99999 !important;
} }
.theme-picker .el-color-picker__trigger { .theme-picker .el-color-picker__trigger {
height: 26px !important; height: 26px !important;
width: 26px !important; width: 26px !important;
padding: 2px; padding: 2px;
} }
.theme-picker-dropdown .el-color-dropdown__link-btn { .theme-picker-dropdown .el-color-dropdown__link-btn {
display: none; display: none;
} }
</style> </style>

View File

@ -28,10 +28,10 @@
</template> </template>
<script> <script>
import { constantRoutes } from "@/router"; import { constantRoutes } from '@/router'
export default { export default {
data() { data () {
return { return {
// 顶部栏初始数 // 顶部栏初始数
visibleNumber: 5, visibleNumber: 5,
@ -39,133 +39,138 @@ export default {
isFrist: false, isFrist: false,
// 当前激活菜单的 index // 当前激活菜单的 index
currentIndex: undefined currentIndex: undefined
}; }
}, },
computed: { computed: {
theme() { theme () {
return this.$store.state.settings.theme; return this.$store.state.settings.theme
}, },
// 顶部显示菜单 // 顶部显示菜单
topMenus() { topMenus () {
let topMenus = []; const topMenus = []
this.routers.map((menu) => { this.routers.map((menu) => {
if (menu.hidden !== true) { if (menu.hidden !== true) {
// 兼容顶部栏一级菜单内部跳转 // 兼容顶部栏一级菜单内部跳转
if (menu.path === "/") { if (menu.path === '/') {
topMenus.push(menu.children[0]); topMenus.push(menu.children[0])
} else { } else {
topMenus.push(menu); topMenus.push(menu)
} }
} }
}); return undefined
return topMenus; })
return topMenus
}, },
// 所有的路由信息 // 所有的路由信息
routers() { routers () {
return this.$store.state.permission.topbarRouters; return this.$store.state.permission.topbarRouters
}, },
// 设置子路由 // 设置子路由
childrenMenus() { childrenMenus () {
var childrenMenus = []; const childrenMenus = []
this.routers.map((router) => { this.routers.map((router) => {
for (var item in router.children) { for (const item in router.children) {
if (router.children[item].parentPath === undefined) { if (router.children[item].parentPath === undefined) {
if(router.path === "/") { if (router.path === '/') {
router.children[item].path = "/redirect/" + router.children[item].path; router.children[item].path = '/redirect/' + router.children[item].path
} else { } else {
if(!this.ishttp(router.children[item].path)) { if (!this.ishttp(router.children[item].path)) {
router.children[item].path = router.path + "/" + router.children[item].path; router.children[item].path = router.path + '/' + router.children[item].path
} }
} }
router.children[item].parentPath = router.path; router.children[item].parentPath = router.path
} }
childrenMenus.push(router.children[item]); childrenMenus.push(router.children[item])
} }
}); return undefined
return constantRoutes.concat(childrenMenus); })
return constantRoutes.concat(childrenMenus)
}, },
// 默认激活的菜单 // 默认激活的菜单
activeMenu() { activeMenu () {
const path = this.$route.path; const path = this.$route.path
let activePath = this.defaultRouter(); let activePath = this.defaultRouter()
if (path.lastIndexOf("/") > 0) { if (path.lastIndexOf('/') > 0) {
const tmpPath = path.substring(1, path.length); const tmpPath = path.substring(1, path.length)
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/")); activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/'))
} else if ("/index" == path || "" == path) { } else if (path === '/index' || path === '') {
if (!this.isFrist) { if (!this.isFrist) {
this.isFrist = true; // eslint-disable-next-line vue/no-side-effects-in-computed-properties
this.isFrist = true
} else { } else {
activePath = "index"; activePath = 'index'
} }
} }
var routes = this.activeRoutes(activePath); const routes = this.activeRoutes(activePath)
if (routes.length === 0) { if (routes.length === 0) {
activePath = this.currentIndex || this.defaultRouter() activePath = this.currentIndex || this.defaultRouter()
this.activeRoutes(activePath); this.activeRoutes(activePath)
} }
return activePath; return activePath
}, }
}, },
beforeMount() { beforeMount () {
window.addEventListener('resize', this.setVisibleNumber) window.addEventListener('resize', this.setVisibleNumber)
}, },
beforeDestroy() { beforeDestroy () {
window.removeEventListener('resize', this.setVisibleNumber) window.removeEventListener('resize', this.setVisibleNumber)
}, },
mounted() { mounted () {
this.setVisibleNumber(); this.setVisibleNumber()
}, },
methods: { methods: {
// 根据宽度计算设置显示栏数 // 根据宽度计算设置显示栏数
setVisibleNumber() { setVisibleNumber () {
const width = document.body.getBoundingClientRect().width / 3; const width = document.body.getBoundingClientRect().width / 3
this.visibleNumber = parseInt(width / 85); this.visibleNumber = parseInt(width / 85)
}, },
// 默认激活的路由 // 默认激活的路由
defaultRouter() { defaultRouter () {
let router; let router
Object.keys(this.routers).some((key) => { Object.keys(this.routers).some((key) => {
if (!this.routers[key].hidden) { if (!this.routers[key].hidden) {
router = this.routers[key].path; router = this.routers[key].path
return true; return true
} }
}); return undefined
return router; })
return router
}, },
// 菜单选择事件 // 菜单选择事件
handleSelect(key, keyPath) { handleSelect (key, keyPath) {
this.currentIndex = key; this.currentIndex = key
if (this.ishttp(key)) { if (this.ishttp(key)) {
// http(s):// 路径新窗口打开 // http(s):// 路径新窗口打开
window.open(key, "_blank"); window.open(key, '_blank')
} else if (key.indexOf("/redirect") !== -1) { } else if (key.indexOf('/redirect') !== -1) {
// /redirect 路径内部打开 // /redirect 路径内部打开
this.$router.push({ path: key.replace("/redirect", "") }); this.$router.push({ path: key.replace('/redirect', '') })
} else { } else {
// 显示左侧联动菜单 // 显示左侧联动菜单
this.activeRoutes(key); this.activeRoutes(key)
} }
}, },
// 当前激活的路由 // 当前激活的路由
activeRoutes(key) { activeRoutes (key) {
var routes = []; const routes = []
if (this.childrenMenus && this.childrenMenus.length > 0) { if (this.childrenMenus && this.childrenMenus.length > 0) {
this.childrenMenus.map((item) => { this.childrenMenus.map((item) => {
if (key == item.parentPath || (key == "index" && "" == item.path)) { if (key === item.parentPath || (key === 'index' && item.path === '')) {
routes.push(item); routes.push(item)
} }
}); return undefined
})
} }
if(routes.length > 0) { if (routes.length > 0) {
this.$store.commit("SET_SIDEBAR_ROUTERS", routes); this.$store.commit('SET_SIDEBAR_ROUTERS', routes)
} }
return routes; return routes
}, },
ishttp(url) { ishttp (url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
} }
}, }
}; }
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -14,23 +14,23 @@ export default {
src: { src: {
type: String, type: String,
required: true required: true
}, }
}, },
data() { data () {
return { return {
height: document.documentElement.clientHeight - 94.5 + "px;", height: document.documentElement.clientHeight - 94.5 + 'px;',
loading: true, loading: true,
url: this.src url: this.src
}; }
}, },
mounted: function () { mounted: function () {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false
}, 300); }, 300)
const that = this; const that = this
window.onresize = function temp() { window.onresize = function temp () {
that.height = document.documentElement.clientHeight - 94.5 + "px;"; that.height = document.documentElement.clientHeight - 94.5 + 'px;'
}; }
} }
}; }
</script> </script>

View File

@ -4,61 +4,60 @@
*/ */
export default { export default {
bind(el, binding, vnode, oldVnode) { bind (el, binding, vnode, oldVnode) {
const value = binding.value const value = binding.value
if (value == false) return if (value === false) return
// 获取拖拽内容头部 // 获取拖拽内容头部
const dialogHeaderEl = el.querySelector('.el-dialog__header'); const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog'); const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cursor = 'move'; dialogHeaderEl.style.cursor = 'move'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null); const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
dragDom.style.position = 'absolute'; dragDom.style.position = 'absolute'
dragDom.style.marginTop = 0; dragDom.style.marginTop = 0
let width = dragDom.style.width; let width = dragDom.style.width
if (width.includes('%')) { if (width.includes('%')) {
width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100); width = +document.body.clientWidth * (+width.replace(/%/g, '') / 100)
} else { } else {
width = +width.replace(/\px/g, ''); width = +width.replace(/\px/g, '')
} }
dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`; dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`
// 鼠标按下事件 // 鼠标按下事件
dialogHeaderEl.onmousedown = (e) => { dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离) // 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离)
const disX = e.clientX - dialogHeaderEl.offsetLeft; const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop; const disY = e.clientY - dialogHeaderEl.offsetTop
// 获取到的值带px 正则匹配替换 // 获取到的值带px 正则匹配替换
let styL, styT; let styL, styT
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) { if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100); styL = +document.body.clientWidth * (+sty.left.replace(/%/g, '') / 100)
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100); styT = +document.body.clientHeight * (+sty.top.replace(/%/g, '') / 100)
} else { } else {
styL = +sty.left.replace(/\px/g, ''); styL = +sty.left.replace(/\px/g, '')
styT = +sty.top.replace(/\px/g, ''); styT = +sty.top.replace(/\px/g, '')
}; };
// 鼠标拖拽事件 // 鼠标拖拽事件
document.onmousemove = function (e) { document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离) // 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
const l = e.clientX - disX; const l = e.clientX - disX
const t = e.clientY - disY; const t = e.clientY - disY
let finallyL = l + styL const finallyL = l + styL
let finallyT = t + styT const finallyT = t + styT
// 移动当前元素 // 移动当前元素
dragDom.style.left = `${finallyL}px`; dragDom.style.left = `${finallyL}px`
dragDom.style.top = `${finallyT}px`; dragDom.style.top = `${finallyT}px`
}
};
document.onmouseup = function (e) { document.onmouseup = function (e) {
document.onmousemove = null; document.onmousemove = null
document.onmouseup = null; document.onmouseup = null
}; }
} }
} }
}; }

View File

@ -2,17 +2,17 @@ import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi' import hasPermi from './permission/hasPermi'
import dialogDrag from './dialog/drag' import dialogDrag from './dialog/drag'
const install = function(Vue) { const install = function (Vue) {
Vue.directive('hasRole', hasRole) Vue.directive('hasRole', hasRole)
Vue.directive('hasPermi', hasPermi) Vue.directive('hasPermi', hasPermi)
Vue.directive('dialogDrag', dialogDrag) Vue.directive('dialogDrag', dialogDrag)
} }
if (window.Vue) { if (window.Vue) {
window['hasRole'] = hasRole window.hasRole = hasRole
window['hasPermi'] = hasPermi window.hasPermi = hasPermi
window['dialogDrag'] = dialogDrag window.dialogDrag = dialogDrag
Vue.use(install); // eslint-disable-line window.Vue.use(install)
} }
export default install export default install

View File

@ -1,28 +1,28 @@
/** /**
* v-hasPermi 操作权限处理 * v-hasPermi 操作权限处理
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
import store from '@/store' import store from '@/store'
export default { export default {
inserted(el, binding, vnode) { inserted (el, binding, vnode) {
const { value } = binding const { value } = binding
const all_permission = "*:*:*"; const allPermission = '*:*:*'
const permissions = store.getters && store.getters.permissions const permissions = store.getters && store.getters.permissions
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value const permissionFlag = value
const hasPermissions = permissions.some(permission => { const hasPermissions = permissions.some(permission => {
return all_permission === permission || permissionFlag.includes(permission) return allPermission === permission || permissionFlag.includes(permission)
}) })
if (!hasPermissions) { if (!hasPermissions) {
el.parentNode && el.parentNode.removeChild(el) el.parentNode && el.parentNode.removeChild(el)
} }
} else { } else {
throw new Error(`请设置操作权限标签值`) throw new Error('请设置操作权限标签值')
} }
} }
} }

View File

@ -1,28 +1,28 @@
/** /**
* v-hasRole 角色权限处理 * v-hasRole 角色权限处理
* Copyright (c) 2019 ruoyi * Copyright (c) 2019 ruoyi
*/ */
import store from '@/store' import store from '@/store'
export default { export default {
inserted(el, binding, vnode) { inserted (el, binding, vnode) {
const { value } = binding const { value } = binding
const super_admin = "admin"; const superAdmin = 'admin'
const roles = store.getters && store.getters.roles const roles = store.getters && store.getters.roles
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const roleFlag = value const roleFlag = value
const hasRole = roles.some(role => { const hasRole = roles.some(role => {
return super_admin === role || roleFlag.includes(role) return superAdmin === role || roleFlag.includes(role)
}) })
if (!hasRole) { if (!hasRole) {
el.parentNode && el.parentNode.removeChild(el) el.parentNode && el.parentNode.removeChild(el)
} }
} else { } else {
throw new Error(`请设置角色权限标签值"`) throw new Error('请设置角色权限标签值"')
} }
} }
} }

View File

@ -1,57 +1,57 @@
<template> <template>
<section class="app-main"> <section class="app-main">
<transition name="fade-transform" mode="out-in"> <transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews"> <keep-alive :include="cachedViews">
<router-view :key="key" /> <router-view :key="key" />
</keep-alive> </keep-alive>
</transition> </transition>
</section> </section>
</template> </template>
<script> <script>
export default { export default {
name: 'AppMain', name: 'AppMain',
computed: { computed: {
cachedViews() { cachedViews () {
return this.$store.state.tagsView.cachedViews return this.$store.state.tagsView.cachedViews
}, },
key() { key () {
return this.$route.path return this.$route.path
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-main { .app-main {
/* 50= navbar 50 */ /* 50= navbar 50 */
min-height: calc(100vh - 50px); min-height: calc(100vh - 50px);
width: 100%; width: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
.fixed-header+.app-main { .fixed-header+.app-main {
padding-top: 50px; padding-top: 50px;
} }
.hasTagsView { .hasTagsView {
.app-main { .app-main {
/* 84 = navbar + tags-view = 50 + 34 */ /* 84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px); min-height: calc(100vh - 84px);
} }
.fixed-header+.app-main { .fixed-header+.app-main {
padding-top: 84px; padding-top: 84px;
} }
} }
</style> </style>
<style lang="scss"> <style lang="scss">
// fix css style bug in open el-dialog // fix css style bug in open el-dialog
.el-popup-parent--hidden { .el-popup-parent--hidden {
.fixed-header { .fixed-header {
padding-right: 17px; padding-right: 17px;
} }
} }
</style> </style>

View File

@ -1,16 +1,16 @@
<script> <script>
export default { export default {
data() { data () {
return {}; return {}
}, },
render() { render () {
const { $route: { meta: { link } }, } = this; const { $route: { meta: { link } } } = this
if ({ link }.link === "") { if ({ link }.link === '') {
return "404"; return '404'
} }
let url = { link }.link; const url = { link }.link
const height = document.documentElement.clientHeight - 94.5 + "px"; const height = document.documentElement.clientHeight - 94.5 + 'px'
const style = { height: height }; const style = { height: height }
return ( return (
<div style={style}> <div style={style}>
@ -21,7 +21,7 @@ export default {
scrolling="auto" scrolling="auto"
></iframe> ></iframe>
</div> </div>
); )
}, }
}; }
</script> </script>

View File

@ -1,200 +1,200 @@
<template> <template>
<div class="navbar"> <div class="navbar">
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/> <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/> <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
<div class="right-menu"> <div class="right-menu">
<template v-if="device!=='mobile'"> <template v-if="device!=='mobile'">
<search id="header-search" class="right-menu-item" /> <search id="header-search" class="right-menu-item" />
<el-tooltip content="源码地址" effect="dark" placement="bottom"> <el-tooltip content="源码地址" effect="dark" placement="bottom">
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" /> <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
<el-tooltip content="文档地址" effect="dark" placement="bottom"> <el-tooltip content="文档地址" effect="dark" placement="bottom">
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" /> <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
<screenfull id="screenfull" class="right-menu-item hover-effect" /> <screenfull id="screenfull" class="right-menu-item hover-effect" />
<el-tooltip content="布局大小" effect="dark" placement="bottom"> <el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" /> <size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
</template> </template>
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img :src="avatar" class="user-avatar"> <img :src="avatar" class="user-avatar">
<i class="el-icon-caret-bottom" /> <i class="el-icon-caret-bottom" />
</div> </div>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<router-link to="/user/profile"> <router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item> <el-dropdown-item>个人中心</el-dropdown-item>
</router-link> </router-link>
<el-dropdown-item @click.native="setting = true"> <el-dropdown-item @click.native="setting = true">
<span>布局设置</span> <span>布局设置</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item divided @click.native="logout"> <el-dropdown-item divided @click.native="logout">
<span>退出登录</span> <span>退出登录</span>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import TopNav from '@/components/TopNav' import TopNav from '@/components/TopNav'
import Hamburger from '@/components/Hamburger' import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull' import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect' import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch' import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git' import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc' import RuoYiDoc from '@/components/RuoYi/Doc'
export default { export default {
components: { components: {
Breadcrumb, Breadcrumb,
TopNav, TopNav,
Hamburger, Hamburger,
Screenfull, Screenfull,
SizeSelect, SizeSelect,
Search, Search,
RuoYiGit, RuoYiGit,
RuoYiDoc RuoYiDoc
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
'sidebar', 'sidebar',
'avatar', 'avatar',
'device' 'device'
]), ]),
setting: { setting: {
get() { get () {
return this.$store.state.settings.showSettings return this.$store.state.settings.showSettings
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'showSettings', key: 'showSettings',
value: val value: val
}) })
} }
}, },
topNav: { topNav: {
get() { get () {
return this.$store.state.settings.topNav return this.$store.state.settings.topNav
} }
} }
}, },
methods: { methods: {
toggleSideBar() { toggleSideBar () {
this.$store.dispatch('app/toggleSideBar') this.$store.dispatch('app/toggleSideBar')
}, },
async logout() { async logout () {
this.$confirm('确定注销并退出系统吗?', '提示', { this.$confirm('确定注销并退出系统吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
this.$store.dispatch('LogOut').then(() => { this.$store.dispatch('LogOut').then(() => {
location.href = '/index'; location.href = '/index'
}) })
}).catch(() => {}); }).catch(() => {})
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.navbar { .navbar {
height: 50px; height: 50px;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
background: #fff; background: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08); box-shadow: 0 1px 4px rgba(0,21,41,.08);
.hamburger-container { .hamburger-container {
line-height: 46px; line-height: 46px;
height: 100%; height: 100%;
float: left; float: left;
cursor: pointer; cursor: pointer;
transition: background .3s; transition: background .3s;
-webkit-tap-highlight-color:transparent; -webkit-tap-highlight-color:transparent;
&:hover { &:hover {
background: rgba(0, 0, 0, .025) background: rgba(0, 0, 0, .025)
} }
} }
.breadcrumb-container { .breadcrumb-container {
float: left; float: left;
} }
.topmenu-container { .topmenu-container {
position: absolute; position: absolute;
left: 50px; left: 50px;
} }
.errLog-container { .errLog-container {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
} }
.right-menu { .right-menu {
float: right; float: right;
height: 100%; height: 100%;
line-height: 50px; line-height: 50px;
&:focus { &:focus {
outline: none; outline: none;
} }
.right-menu-item { .right-menu-item {
display: inline-block; display: inline-block;
padding: 0 8px; padding: 0 8px;
height: 100%; height: 100%;
font-size: 18px; font-size: 18px;
color: #5a5e66; color: #5a5e66;
vertical-align: text-bottom; vertical-align: text-bottom;
&.hover-effect { &.hover-effect {
cursor: pointer; cursor: pointer;
transition: background .3s; transition: background .3s;
&:hover { &:hover {
background: rgba(0, 0, 0, .025) background: rgba(0, 0, 0, .025)
} }
} }
} }
.avatar-container { .avatar-container {
margin-right: 30px; margin-right: 30px;
.avatar-wrapper { .avatar-wrapper {
margin-top: 5px; margin-top: 5px;
position: relative; position: relative;
.user-avatar { .user-avatar {
cursor: pointer; cursor: pointer;
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 10px; border-radius: 10px;
} }
.el-icon-caret-bottom { .el-icon-caret-bottom {
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
right: -20px; right: -20px;
top: 25px; top: 25px;
font-size: 12px; font-size: 12px;
} }
} }
} }
} }
} }
</style> </style>

View File

@ -1,268 +1,268 @@
<template> <template>
<div class="drawer-container"> <div class="drawer-container">
<div> <div>
<div class="setting-drawer-content"> <div class="setting-drawer-content">
<div class="setting-drawer-title"> <div class="setting-drawer-title">
<h3 class="drawer-title">主题风格设置</h3> <h3 class="drawer-title">主题风格设置</h3>
</div> </div>
<div class="setting-drawer-block-checbox"> <div class="setting-drawer-block-checbox">
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')"> <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
<img src="@/assets/images/dark.svg" alt="dark"> <img src="@/assets/images/dark.svg" alt="dark">
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check"> <i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
focusable="false" class=""> focusable="false" class="">
<path <path
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg> </svg>
</i> </i>
</div> </div>
</div> </div>
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')"> <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
<img src="@/assets/images/light.svg" alt="light"> <img src="@/assets/images/light.svg" alt="light">
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check"> <i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
focusable="false" class=""> focusable="false" class="">
<path <path
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg> </svg>
</i> </i>
</div> </div>
</div> </div>
</div> </div>
<div class="drawer-item"> <div class="drawer-item">
<span>主题颜色</span> <span>主题颜色</span>
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
</div> </div>
</div> </div>
<el-divider/> <el-divider/>
<h3 class="drawer-title">系统布局配置</h3> <h3 class="drawer-title">系统布局配置</h3>
<div class="drawer-item"> <div class="drawer-item">
<span>开启 TopNav</span> <span>开启 TopNav</span>
<el-switch v-model="topNav" class="drawer-switch" /> <el-switch v-model="topNav" class="drawer-switch" />
</div> </div>
<div class="drawer-item"> <div class="drawer-item">
<span>开启 Tags-Views</span> <span>开启 Tags-Views</span>
<el-switch v-model="tagsView" class="drawer-switch" /> <el-switch v-model="tagsView" class="drawer-switch" />
</div> </div>
<div class="drawer-item"> <div class="drawer-item">
<span>固定 Header</span> <span>固定 Header</span>
<el-switch v-model="fixedHeader" class="drawer-switch" /> <el-switch v-model="fixedHeader" class="drawer-switch" />
</div> </div>
<div class="drawer-item"> <div class="drawer-item">
<span>显示 Logo</span> <span>显示 Logo</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" /> <el-switch v-model="sidebarLogo" class="drawer-switch" />
</div> </div>
<div class="drawer-item"> <div class="drawer-item">
<span>动态标题</span> <span>动态标题</span>
<el-switch v-model="dynamicTitle" class="drawer-switch" /> <el-switch v-model="dynamicTitle" class="drawer-switch" />
</div> </div>
<el-divider/> <el-divider/>
<el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button> <el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">重置配置</el-button> <el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">重置配置</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import ThemePicker from '@/components/ThemePicker' import ThemePicker from '@/components/ThemePicker'
export default { export default {
components: { ThemePicker }, components: { ThemePicker },
data() { data () {
return { return {
theme: this.$store.state.settings.theme, theme: this.$store.state.settings.theme,
sideTheme: this.$store.state.settings.sideTheme sideTheme: this.$store.state.settings.sideTheme
}; }
}, },
computed: { computed: {
fixedHeader: { fixedHeader: {
get() { get () {
return this.$store.state.settings.fixedHeader return this.$store.state.settings.fixedHeader
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'fixedHeader', key: 'fixedHeader',
value: val value: val
}) })
} }
}, },
topNav: { topNav: {
get() { get () {
return this.$store.state.settings.topNav return this.$store.state.settings.topNav
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'topNav', key: 'topNav',
value: val value: val
}) })
if (!val) { if (!val) {
this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes); this.$store.commit('SET_SIDEBAR_ROUTERS', this.$store.state.permission.defaultRoutes)
} }
} }
}, },
tagsView: { tagsView: {
get() { get () {
return this.$store.state.settings.tagsView return this.$store.state.settings.tagsView
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'tagsView', key: 'tagsView',
value: val value: val
}) })
} }
}, },
sidebarLogo: { sidebarLogo: {
get() { get () {
return this.$store.state.settings.sidebarLogo return this.$store.state.settings.sidebarLogo
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'sidebarLogo', key: 'sidebarLogo',
value: val value: val
}) })
} }
}, },
dynamicTitle: { dynamicTitle: {
get() { get () {
return this.$store.state.settings.dynamicTitle return this.$store.state.settings.dynamicTitle
}, },
set(val) { set (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'dynamicTitle', key: 'dynamicTitle',
value: val value: val
}) })
} }
}, }
}, },
methods: { methods: {
themeChange(val) { themeChange (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'theme', key: 'theme',
value: val value: val
}) })
this.theme = val; this.theme = val
}, },
handleTheme(val) { handleTheme (val) {
this.$store.dispatch('settings/changeSetting', { this.$store.dispatch('settings/changeSetting', {
key: 'sideTheme', key: 'sideTheme',
value: val value: val
}) })
this.sideTheme = val; this.sideTheme = val
}, },
saveSetting() { saveSetting () {
const loading = this.$loading({ const loading = this.$loading({
lock: true, lock: true,
fullscreen: false, fullscreen: false,
text: "正在保存到本地,请稍后...", text: '正在保存到本地,请稍后...',
spinner: "el-icon-loading", spinner: 'el-icon-loading',
background: "rgba(0, 0, 0, 0.7)" background: 'rgba(0, 0, 0, 0.7)'
}); })
localStorage.setItem( localStorage.setItem(
"layout-setting", 'layout-setting',
`{ `{
"topNav":${this.topNav}, "topNav":${this.topNav},
"tagsView":${this.tagsView}, "tagsView":${this.tagsView},
"fixedHeader":${this.fixedHeader}, "fixedHeader":${this.fixedHeader},
"sidebarLogo":${this.sidebarLogo}, "sidebarLogo":${this.sidebarLogo},
"dynamicTitle":${this.dynamicTitle}, "dynamicTitle":${this.dynamicTitle},
"sideTheme":"${this.sideTheme}", "sideTheme":"${this.sideTheme}",
"theme":"${this.theme}" "theme":"${this.theme}"
}` }`
); )
setTimeout(loading.close(), 1000) setTimeout(loading.close(), 1000)
}, },
resetSetting() { resetSetting () {
this.$loading({ this.$loading({
lock: true, lock: true,
fullscreen: false, fullscreen: false,
text: "正在清除设置缓存并刷新,请稍后...", text: '正在清除设置缓存并刷新,请稍后...',
spinner: "el-icon-loading", spinner: 'el-icon-loading',
background: "rgba(0, 0, 0, 0.7)" background: 'rgba(0, 0, 0, 0.7)'
}); })
localStorage.removeItem("layout-setting") localStorage.removeItem('layout-setting')
setTimeout("window.location.reload()", 1000) setTimeout(window.location.reload(), 1000)
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.setting-drawer-content { .setting-drawer-content {
.setting-drawer-title { .setting-drawer-title {
margin-bottom: 12px; margin-bottom: 12px;
color: rgba(0, 0, 0, .85); color: rgba(0, 0, 0, .85);
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
font-weight: bold; font-weight: bold;
} }
.setting-drawer-block-checbox { .setting-drawer-block-checbox {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
margin-top: 10px; margin-top: 10px;
margin-bottom: 20px; margin-bottom: 20px;
.setting-drawer-block-checbox-item { .setting-drawer-block-checbox-item {
position: relative; position: relative;
margin-right: 16px; margin-right: 16px;
border-radius: 2px; border-radius: 2px;
cursor: pointer; cursor: pointer;
img { img {
width: 48px; width: 48px;
height: 48px; height: 48px;
} }
.setting-drawer-block-checbox-selectIcon { .setting-drawer-block-checbox-selectIcon {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-top: 15px; padding-top: 15px;
padding-left: 24px; padding-left: 24px;
color: #1890ff; color: #1890ff;
font-weight: 700; font-weight: 700;
font-size: 14px; font-size: 14px;
} }
} }
} }
} }
.drawer-container { .drawer-container {
padding: 24px; padding: 24px;
font-size: 14px; font-size: 14px;
line-height: 1.5; line-height: 1.5;
word-wrap: break-word; word-wrap: break-word;
.drawer-title { .drawer-title {
margin-bottom: 12px; margin-bottom: 12px;
color: rgba(0, 0, 0, .85); color: rgba(0, 0, 0, .85);
font-size: 14px; font-size: 14px;
line-height: 22px; line-height: 22px;
} }
.drawer-item { .drawer-item {
color: rgba(0, 0, 0, .65); color: rgba(0, 0, 0, .65);
font-size: 14px; font-size: 14px;
padding: 12px 0; padding: 12px 0;
} }
.drawer-switch { .drawer-switch {
float: right float: right
} }
} }
</style> </style>

View File

@ -1,25 +1,25 @@
export default { export default {
computed: { computed: {
device() { device () {
return this.$store.state.app.device return this.$store.state.app.device
} }
}, },
mounted() { mounted () {
// In order to fix the click on menu on the ios device will trigger the mouseleave bug // In order to fix the click on menu on the ios device will trigger the mouseleave bug
this.fixBugIniOS() this.fixBugIniOS()
}, },
methods: { methods: {
fixBugIniOS() { fixBugIniOS () {
const $subMenu = this.$refs.subMenu const $subMenu = this.$refs.subMenu
if ($subMenu) { if ($subMenu) {
const handleMouseleave = $subMenu.handleMouseleave const handleMouseleave = $subMenu.handleMouseleave
$subMenu.handleMouseleave = (e) => { $subMenu.handleMouseleave = (e) => {
if (this.device === 'mobile') { if (this.device === 'mobile') {
return return
} }
handleMouseleave(e) handleMouseleave(e)
} }
} }
} }
} }
} }

View File

@ -1,29 +1,29 @@
<script> <script>
export default { export default {
name: 'MenuItem', name: 'MenuItem',
functional: true, functional: true,
props: { props: {
icon: { icon: {
type: String, type: String,
default: '' default: ''
}, },
title: { title: {
type: String, type: String,
default: '' default: ''
} }
}, },
render(h, context) { render (h, context) {
const { icon, title } = context.props const { icon, title } = context.props
const vnodes = [] const vnodes = []
if (icon) { if (icon) {
vnodes.push(<svg-icon icon-class={icon}/>) vnodes.push(<svg-icon icon-class={icon}/>)
} }
if (title) { if (title) {
vnodes.push(<span slot='title'>{(title)}</span>) vnodes.push(<span slot='title'>{(title)}</span>)
} }
return vnodes return vnodes
} }
} }
</script> </script>

View File

@ -1,43 +1,43 @@
<template> <template>
<component :is="type" v-bind="linkProps(to)"> <component :is="type" v-bind="linkProps(to)">
<slot /> <slot />
</component> </component>
</template> </template>
<script> <script>
import { isExternal } from '@/utils/validate' import { isExternal } from '@/utils/validate'
export default { export default {
props: { props: {
to: { to: {
type: String, type: String,
required: true required: true
} }
}, },
computed: { computed: {
isExternal() { isExternal () {
return isExternal(this.to) return isExternal(this.to)
}, },
type() { type () {
if (this.isExternal) { if (this.isExternal) {
return 'a' return 'a'
} }
return 'router-link' return 'router-link'
} }
}, },
methods: { methods: {
linkProps(to) { linkProps (to) {
if (this.isExternal) { if (this.isExternal) {
return { return {
href: to, href: to,
target: '_blank', target: '_blank',
rel: 'noopener' rel: 'noopener'
} }
} }
return { return {
to: to to: to
} }
} }
} }
} }
</script> </script>

View File

@ -1,93 +1,93 @@
<template> <template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }"> <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }">
<transition name="sidebarLogoFade"> <transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1>
</router-link> </router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/"> <router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1>
</router-link> </router-link>
</transition> </transition>
</div> </div>
</template> </template>
<script> <script>
import logoImg from '@/assets/logo/logo.png' import logoImg from '@/assets/logo/logo.png'
import variables from '@/assets/styles/variables.scss' import variables from '@/assets/styles/variables.scss'
export default { export default {
name: 'SidebarLogo', name: 'SidebarLogo',
props: { props: {
collapse: { collapse: {
type: Boolean, type: Boolean,
required: true required: true
} }
}, },
computed: { computed: {
variables() { variables () {
return variables; return variables
}, },
sideTheme() { sideTheme () {
return this.$store.state.settings.sideTheme return this.$store.state.settings.sideTheme
} }
}, },
data() { data () {
return { return {
title: '若依管理系统', title: '若依管理系统',
logo: logoImg logo: logoImg
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.sidebarLogoFade-enter-active { .sidebarLogoFade-enter-active {
transition: opacity 1.5s; transition: opacity 1.5s;
} }
.sidebarLogoFade-enter, .sidebarLogoFade-enter,
.sidebarLogoFade-leave-to { .sidebarLogoFade-leave-to {
opacity: 0; opacity: 0;
} }
.sidebar-logo-container { .sidebar-logo-container {
position: relative; position: relative;
width: 100%; width: 100%;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
background: #2b2f3a; background: #2b2f3a;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
& .sidebar-logo-link { & .sidebar-logo-link {
height: 100%; height: 100%;
width: 100%; width: 100%;
& .sidebar-logo { & .sidebar-logo {
width: 32px; width: 32px;
height: 32px; height: 32px;
vertical-align: middle; vertical-align: middle;
margin-right: 12px; margin-right: 12px;
} }
& .sidebar-title { & .sidebar-title {
display: inline-block; display: inline-block;
margin: 0; margin: 0;
color: #fff; color: #fff;
font-weight: 600; font-weight: 600;
line-height: 50px; line-height: 50px;
font-size: 14px; font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle; vertical-align: middle;
} }
} }
&.collapse { &.collapse {
.sidebar-logo { .sidebar-logo {
margin-right: 0px; margin-right: 0px;
} }
} }
} }
</style> </style>

View File

@ -1,96 +1,96 @@
<template> <template>
<div v-if="!item.hidden"> <div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"> <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title"> <template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template> </template>
<sidebar-item <sidebar-item
v-for="child in item.children" v-for="child in item.children"
:key="child.path" :key="child.path"
:is-nest="true" :is-nest="true"
:item="child" :item="child"
:base-path="resolvePath(child.path)" :base-path="resolvePath(child.path)"
class="nest-menu" class="nest-menu"
/> />
</el-submenu> </el-submenu>
</div> </div>
</template> </template>
<script> <script>
import path from 'path' import path from 'path'
import { isExternal } from '@/utils/validate' import { isExternal } from '@/utils/validate'
import Item from './Item' import Item from './Item'
import AppLink from './Link' import AppLink from './Link'
import FixiOSBug from './FixiOSBug' import FixiOSBug from './FixiOSBug'
export default { export default {
name: 'SidebarItem', name: 'SidebarItem',
components: { Item, AppLink }, components: { Item, AppLink },
mixins: [FixiOSBug], mixins: [FixiOSBug],
props: { props: {
// route object // route object
item: { item: {
type: Object, type: Object,
required: true required: true
}, },
isNest: { isNest: {
type: Boolean, type: Boolean,
default: false default: false
}, },
basePath: { basePath: {
type: String, type: String,
default: '' default: ''
} }
}, },
data() { data () {
this.onlyOneChild = null this.onlyOneChild = null
return {} return {}
}, },
methods: { methods: {
hasOneShowingChild(children = [], parent) { hasOneShowingChild (children = [], parent) {
if (!children) { if (!children) {
children = []; children = []
} }
const showingChildren = children.filter(item => { const showingChildren = children.filter(item => {
if (item.hidden) { if (item.hidden) {
return false return false
} else { } else {
// Temp set(will be used if only has one showing child) // Temp set(will be used if only has one showing child)
this.onlyOneChild = item this.onlyOneChild = item
return true return true
} }
}) })
// When there is only one child router, the child router is displayed by default // When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) { if (showingChildren.length === 1) {
return true return true
} }
// Show parent if there are no child router to display // Show parent if there are no child router to display
if (showingChildren.length === 0) { if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true } this.onlyOneChild = { ...parent, path: '', noShowingChildren: true }
return true return true
} }
return false return false
}, },
resolvePath(routePath) { resolvePath (routePath) {
if (isExternal(routePath)) { if (isExternal(routePath)) {
return routePath return routePath
} }
if (isExternal(this.basePath)) { if (isExternal(this.basePath)) {
return this.basePath return this.basePath
} }
return path.resolve(this.basePath, routePath) return path.resolve(this.basePath, routePath)
} }
} }
} }
</script> </script>

View File

@ -1,57 +1,57 @@
<template> <template>
<div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }"> <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }">
<logo v-if="showLogo" :collapse="isCollapse" /> <logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper"> <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
<el-menu <el-menu
:default-active="activeMenu" :default-active="activeMenu"
:collapse="isCollapse" :collapse="isCollapse"
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg" :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg"
:text-color="settings.sideTheme === 'theme-dark' ? variables.menuText : 'rgba(0,0,0,.65)'" :text-color="settings.sideTheme === 'theme-dark' ? variables.menuText : 'rgba(0,0,0,.65)'"
:unique-opened="true" :unique-opened="true"
:active-text-color="settings.theme" :active-text-color="settings.theme"
:collapse-transition="false" :collapse-transition="false"
mode="vertical" mode="vertical"
> >
<sidebar-item <sidebar-item
v-for="(route, index) in sidebarRouters" v-for="(route, index) in sidebarRouters"
:key="route.path + index" :key="route.path + index"
:item="route" :item="route"
:base-path="route.path" :base-path="route.path"
/> />
</el-menu> </el-menu>
</el-scrollbar> </el-scrollbar>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters, mapState } from "vuex"; import { mapGetters, mapState } from 'vuex'
import Logo from "./Logo"; import Logo from './Logo'
import SidebarItem from "./SidebarItem"; import SidebarItem from './SidebarItem'
import variables from "@/assets/styles/variables.scss"; import variables from '@/assets/styles/variables.scss'
export default { export default {
components: { SidebarItem, Logo }, components: { SidebarItem, Logo },
computed: { computed: {
...mapState(["settings"]), ...mapState(['settings']),
...mapGetters(["sidebarRouters", "sidebar"]), ...mapGetters(['sidebarRouters', 'sidebar']),
activeMenu() { activeMenu () {
const route = this.$route; const route = this.$route
const { meta, path } = route; const { meta, path } = route
// if set path, the sidebar will highlight the path you set // if set path, the sidebar will highlight the path you set
if (meta.activeMenu) { if (meta.activeMenu) {
return meta.activeMenu; return meta.activeMenu
} }
return path; return path
}, },
showLogo() { showLogo () {
return this.$store.state.settings.sidebarLogo; return this.$store.state.settings.sidebarLogo
}, },
variables() { variables () {
return variables; return variables
}, },
isCollapse() { isCollapse () {
return !this.sidebar.opened; return !this.sidebar.opened
} }
} }
}; }
</script> </script>

View File

@ -1,94 +1,94 @@
<template> <template>
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll"> <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
<slot /> <slot />
</el-scrollbar> </el-scrollbar>
</template> </template>
<script> <script>
const tagAndTagSpacing = 4 // tagAndTagSpacing const tagAndTagSpacing = 4 // tagAndTagSpacing
export default { export default {
name: 'ScrollPane', name: 'ScrollPane',
data() { data () {
return { return {
left: 0 left: 0
} }
}, },
computed: { computed: {
scrollWrapper() { scrollWrapper () {
return this.$refs.scrollContainer.$refs.wrap return this.$refs.scrollContainer.$refs.wrap
} }
}, },
mounted() { mounted () {
this.scrollWrapper.addEventListener('scroll', this.emitScroll, true) this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
}, },
beforeDestroy() { beforeDestroy () {
this.scrollWrapper.removeEventListener('scroll', this.emitScroll) this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
}, },
methods: { methods: {
handleScroll(e) { handleScroll (e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40 const eventDelta = e.wheelDelta || -e.deltaY * 40
const $scrollWrapper = this.scrollWrapper const $scrollWrapper = this.scrollWrapper
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4 $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
}, },
emitScroll() { emitScroll () {
this.$emit('scroll') this.$emit('scroll')
}, },
moveToTarget(currentTag) { moveToTarget (currentTag) {
const $container = this.$refs.scrollContainer.$el const $container = this.$refs.scrollContainer.$el
const $containerWidth = $container.offsetWidth const $containerWidth = $container.offsetWidth
const $scrollWrapper = this.scrollWrapper const $scrollWrapper = this.scrollWrapper
const tagList = this.$parent.$refs.tag const tagList = this.$parent.$refs.tag
let firstTag = null let firstTag = null
let lastTag = null let lastTag = null
// find first tag and last tag // find first tag and last tag
if (tagList.length > 0) { if (tagList.length > 0) {
firstTag = tagList[0] firstTag = tagList[0]
lastTag = tagList[tagList.length - 1] lastTag = tagList[tagList.length - 1]
} }
if (firstTag === currentTag) { if (firstTag === currentTag) {
$scrollWrapper.scrollLeft = 0 $scrollWrapper.scrollLeft = 0
} else if (lastTag === currentTag) { } else if (lastTag === currentTag) {
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
} else { } else {
// find preTag and nextTag // find preTag and nextTag
const currentIndex = tagList.findIndex(item => item === currentTag) const currentIndex = tagList.findIndex(item => item === currentTag)
const prevTag = tagList[currentIndex - 1] const prevTag = tagList[currentIndex - 1]
const nextTag = tagList[currentIndex + 1] const nextTag = tagList[currentIndex + 1]
// the tag's offsetLeft after of nextTag // the tag's offsetLeft after of nextTag
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
// the tag's offsetLeft before of prevTag // the tag's offsetLeft before of prevTag
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) { if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
} }
} }
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.scroll-container { .scroll-container {
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
::v-deep { ::v-deep {
.el-scrollbar__bar { .el-scrollbar__bar {
bottom: 0px; bottom: 0px;
} }
.el-scrollbar__wrap { .el-scrollbar__wrap {
height: 49px; height: 49px;
} }
} }
} }
</style> </style>

View File

@ -1,318 +1,318 @@
<template> <template>
<div id="tags-view-container" class="tags-view-container"> <div id="tags-view-container" class="tags-view-container">
<scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll"> <scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll">
<router-link <router-link
v-for="tag in visitedViews" v-for="tag in visitedViews"
ref="tag" ref="tag"
:key="tag.path" :key="tag.path"
:class="isActive(tag)?'active':''" :class="isActive(tag)?'active':''"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
tag="span" tag="span"
class="tags-view-item" class="tags-view-item"
:style="activeStyle(tag)" :style="activeStyle(tag)"
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''" @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
@contextmenu.prevent.native="openMenu(tag,$event)" @contextmenu.prevent.native="openMenu(tag,$event)"
> >
{{ tag.title }} {{ tag.title }}
<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" /> <span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
</router-link> </router-link>
</scroll-pane> </scroll-pane>
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu"> <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
<li @click="refreshSelectedTag(selectedTag)">刷新页面</li> <li @click="refreshSelectedTag(selectedTag)">刷新页面</li>
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭当前</li> <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭当前</li>
<li @click="closeOthersTags">关闭其他</li> <li @click="closeOthersTags">关闭其他</li>
<li v-if="!isLastView()" @click="closeRightTags">关闭右侧</li> <li v-if="!isLastView()" @click="closeRightTags">关闭右侧</li>
<li @click="closeAllTags(selectedTag)">关闭所有</li> <li @click="closeAllTags(selectedTag)">关闭所有</li>
</ul> </ul>
</div> </div>
</template> </template>
<script> <script>
import ScrollPane from './ScrollPane' import ScrollPane from './ScrollPane'
import path from 'path' import path from 'path'
export default { export default {
components: { ScrollPane }, components: { ScrollPane },
data() { data () {
return { return {
visible: false, visible: false,
top: 0, top: 0,
left: 0, left: 0,
selectedTag: {}, selectedTag: {},
affixTags: [] affixTags: []
} }
}, },
computed: { computed: {
visitedViews() { visitedViews () {
return this.$store.state.tagsView.visitedViews return this.$store.state.tagsView.visitedViews
}, },
routes() { routes () {
return this.$store.state.permission.routes return this.$store.state.permission.routes
}, },
theme() { theme () {
return this.$store.state.settings.theme; return this.$store.state.settings.theme
} }
}, },
watch: { watch: {
$route() { $route () {
this.addTags() this.addTags()
this.moveToCurrentTag() this.moveToCurrentTag()
}, },
visible(value) { visible (value) {
if (value) { if (value) {
document.body.addEventListener('click', this.closeMenu) document.body.addEventListener('click', this.closeMenu)
} else { } else {
document.body.removeEventListener('click', this.closeMenu) document.body.removeEventListener('click', this.closeMenu)
} }
} }
}, },
mounted() { mounted () {
this.initTags() this.initTags()
this.addTags() this.addTags()
}, },
methods: { methods: {
isActive(route) { isActive (route) {
return route.path === this.$route.path return route.path === this.$route.path
}, },
activeStyle(tag) { activeStyle (tag) {
if (!this.isActive(tag)) return {}; if (!this.isActive(tag)) return {}
return { return {
"background-color": this.theme, 'background-color': this.theme,
"border-color": this.theme 'border-color': this.theme
}; }
}, },
isAffix(tag) { isAffix (tag) {
return tag.meta && tag.meta.affix return tag.meta && tag.meta.affix
}, },
isLastView() { isLastView () {
try { try {
return this.selectedTag.fullPath === this.visitedViews[this.visitedViews.length - 1].fullPath return this.selectedTag.fullPath === this.visitedViews[this.visitedViews.length - 1].fullPath
} catch (err) { } catch (err) {
return false return false
} }
}, },
filterAffixTags(routes, basePath = '/') { filterAffixTags (routes, basePath = '/') {
let tags = [] let tags = []
routes.forEach(route => { routes.forEach(route => {
if (route.meta && route.meta.affix) { if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path) const tagPath = path.resolve(basePath, route.path)
tags.push({ tags.push({
fullPath: tagPath, fullPath: tagPath,
path: tagPath, path: tagPath,
name: route.name, name: route.name,
meta: { ...route.meta } meta: { ...route.meta }
}) })
} }
if (route.children) { if (route.children) {
const tempTags = this.filterAffixTags(route.children, route.path) const tempTags = this.filterAffixTags(route.children, route.path)
if (tempTags.length >= 1) { if (tempTags.length >= 1) {
tags = [...tags, ...tempTags] tags = [...tags, ...tempTags]
} }
} }
}) })
return tags return tags
}, },
initTags() { initTags () {
const affixTags = this.affixTags = this.filterAffixTags(this.routes) const affixTags = this.affixTags = this.filterAffixTags(this.routes)
for (const tag of affixTags) { for (const tag of affixTags) {
// Must have tag name // Must have tag name
if (tag.name) { if (tag.name) {
this.$store.dispatch('tagsView/addVisitedView', tag) this.$store.dispatch('tagsView/addVisitedView', tag)
} }
} }
}, },
addTags() { addTags () {
const { name } = this.$route const { name } = this.$route
if (name) { if (name) {
this.$store.dispatch('tagsView/addView', this.$route) this.$store.dispatch('tagsView/addView', this.$route)
} }
return false return false
}, },
moveToCurrentTag() { moveToCurrentTag () {
const tags = this.$refs.tag const tags = this.$refs.tag
this.$nextTick(() => { this.$nextTick(() => {
for (const tag of tags) { for (const tag of tags) {
if (tag.to.path === this.$route.path) { if (tag.to.path === this.$route.path) {
this.$refs.scrollPane.moveToTarget(tag) this.$refs.scrollPane.moveToTarget(tag)
// when query is different then update // when query is different then update
if (tag.to.fullPath !== this.$route.fullPath) { if (tag.to.fullPath !== this.$route.fullPath) {
this.$store.dispatch('tagsView/updateVisitedView', this.$route) this.$store.dispatch('tagsView/updateVisitedView', this.$route)
} }
break break
} }
} }
}) })
}, },
refreshSelectedTag(view) { refreshSelectedTag (view) {
this.$store.dispatch('tagsView/delCachedView', view).then(() => { this.$store.dispatch('tagsView/delCachedView', view).then(() => {
const { fullPath } = view const { fullPath } = view
this.$nextTick(() => { this.$nextTick(() => {
this.$router.replace({ this.$router.replace({
path: '/redirect' + fullPath path: '/redirect' + fullPath
}) })
}) })
}) })
}, },
closeSelectedTag(view) { closeSelectedTag (view) {
this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => { this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
if (this.isActive(view)) { if (this.isActive(view)) {
this.toLastView(visitedViews, view) this.toLastView(visitedViews, view)
} }
}) })
}, },
closeRightTags() { closeRightTags () {
this.$store.dispatch('tagsView/delRightTags', this.selectedTag).then(visitedViews => { this.$store.dispatch('tagsView/delRightTags', this.selectedTag).then(visitedViews => {
if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) { if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) {
this.toLastView(visitedViews) this.toLastView(visitedViews)
} }
}) })
}, },
closeOthersTags() { closeOthersTags () {
this.$router.push(this.selectedTag).catch(()=>{}); this.$router.push(this.selectedTag).catch(() => {})
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => { this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
this.moveToCurrentTag() this.moveToCurrentTag()
}) })
}, },
closeAllTags(view) { closeAllTags (view) {
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => { this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
if (this.affixTags.some(tag => tag.path === this.$route.path)) { if (this.affixTags.some(tag => tag.path === this.$route.path)) {
return return
} }
this.toLastView(visitedViews, view) this.toLastView(visitedViews, view)
}) })
}, },
toLastView(visitedViews, view) { toLastView (visitedViews, view) {
const latestView = visitedViews.slice(-1)[0] const latestView = visitedViews.slice(-1)[0]
if (latestView) { if (latestView) {
this.$router.push(latestView.fullPath) this.$router.push(latestView.fullPath)
} else { } else {
// now the default is to redirect to the home page if there is no tags-view, // now the default is to redirect to the home page if there is no tags-view,
// you can adjust it according to your needs. // you can adjust it according to your needs.
if (view.name === 'Dashboard') { if (view.name === 'Dashboard') {
// to reload home page // to reload home page
this.$router.replace({ path: '/redirect' + view.fullPath }) this.$router.replace({ path: '/redirect' + view.fullPath })
} else { } else {
this.$router.push('/') this.$router.push('/')
} }
} }
}, },
openMenu(tag, e) { openMenu (tag, e) {
const menuMinWidth = 105 const menuMinWidth = 105
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
const offsetWidth = this.$el.offsetWidth // container width const offsetWidth = this.$el.offsetWidth // container width
const maxLeft = offsetWidth - menuMinWidth // left boundary const maxLeft = offsetWidth - menuMinWidth // left boundary
const left = e.clientX - offsetLeft + 15 // 15: margin right const left = e.clientX - offsetLeft + 15 // 15: margin right
if (left > maxLeft) { if (left > maxLeft) {
this.left = maxLeft this.left = maxLeft
} else { } else {
this.left = left this.left = left
} }
this.top = e.clientY this.top = e.clientY
this.visible = true this.visible = true
this.selectedTag = tag this.selectedTag = tag
}, },
closeMenu() { closeMenu () {
this.visible = false this.visible = false
}, },
handleScroll() { handleScroll () {
this.closeMenu() this.closeMenu()
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.tags-view-container { .tags-view-container {
height: 34px; height: 34px;
width: 100%; width: 100%;
background: #fff; background: #fff;
border-bottom: 1px solid #d8dce5; border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04); box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
.tags-view-wrapper { .tags-view-wrapper {
.tags-view-item { .tags-view-item {
display: inline-block; display: inline-block;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
height: 26px; height: 26px;
line-height: 26px; line-height: 26px;
border: 1px solid #d8dce5; border: 1px solid #d8dce5;
color: #495060; color: #495060;
background: #fff; background: #fff;
padding: 0 8px; padding: 0 8px;
font-size: 12px; font-size: 12px;
margin-left: 5px; margin-left: 5px;
margin-top: 4px; margin-top: 4px;
&:first-of-type { &:first-of-type {
margin-left: 15px; margin-left: 15px;
} }
&:last-of-type { &:last-of-type {
margin-right: 15px; margin-right: 15px;
} }
&.active { &.active {
background-color: #42b983; background-color: #42b983;
color: #fff; color: #fff;
border-color: #42b983; border-color: #42b983;
&::before { &::before {
content: ''; content: '';
background: #fff; background: #fff;
display: inline-block; display: inline-block;
width: 8px; width: 8px;
height: 8px; height: 8px;
border-radius: 50%; border-radius: 50%;
position: relative; position: relative;
margin-right: 2px; margin-right: 2px;
} }
} }
} }
} }
.contextmenu { .contextmenu {
margin: 0; margin: 0;
background: #fff; background: #fff;
z-index: 3000; z-index: 3000;
position: absolute; position: absolute;
list-style-type: none; list-style-type: none;
padding: 5px 0; padding: 5px 0;
border-radius: 4px; border-radius: 4px;
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
color: #333; color: #333;
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3); box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
li { li {
margin: 0; margin: 0;
padding: 7px 16px; padding: 7px 16px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: #eee; background: #eee;
} }
} }
} }
} }
</style> </style>
<style lang="scss"> <style lang="scss">
//reset element css of el-icon-close //reset element css of el-icon-close
.tags-view-wrapper { .tags-view-wrapper {
.tags-view-item { .tags-view-item {
.el-icon-close { .el-icon-close {
width: 16px; width: 16px;
height: 16px; height: 16px;
vertical-align: 2px; vertical-align: 2px;
border-radius: 50%; border-radius: 50%;
text-align: center; text-align: center;
transition: all .3s cubic-bezier(.645, .045, .355, 1); transition: all .3s cubic-bezier(.645, .045, .355, 1);
transform-origin: 100% 50%; transform-origin: 100% 50%;
&:before { &:before {
transform: scale(.6); transform: scale(.6);
display: inline-block; display: inline-block;
vertical-align: -3px; vertical-align: -3px;
} }
&:hover { &:hover {
background-color: #b4bccc; background-color: #b4bccc;
color: #fff; color: #fff;
} }
} }
} }
} }
</style> </style>

View File

@ -1,5 +1,5 @@
export { default as AppMain } from './AppMain' export { default as AppMain } from './AppMain'
export { default as Navbar } from './Navbar' export { default as Navbar } from './Navbar'
export { default as Settings } from './Settings' export { default as Settings } from './Settings'
export { default as Sidebar } from './Sidebar/index.vue' export { default as Sidebar } from './Sidebar/index.vue'
export { default as TagsView } from './TagsView/index.vue' export { default as TagsView } from './TagsView/index.vue'

View File

@ -1,108 +1,108 @@
<template> <template>
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}"> <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/> <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<sidebar class="sidebar-container" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }" /> <sidebar class="sidebar-container" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }" />
<div :class="{hasTagsView:needTagsView}" class="main-container"> <div :class="{hasTagsView:needTagsView}" class="main-container">
<div :class="{'fixed-header':fixedHeader}"> <div :class="{'fixed-header':fixedHeader}">
<navbar /> <navbar />
<tags-view v-if="needTagsView" /> <tags-view v-if="needTagsView" />
</div> </div>
<app-main /> <app-main />
<right-panel v-if="showSettings"> <right-panel v-if="showSettings">
<settings /> <settings />
</right-panel> </right-panel>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import RightPanel from '@/components/RightPanel' import RightPanel from '@/components/RightPanel'
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler' import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import variables from '@/assets/styles/variables.scss' import variables from '@/assets/styles/variables.scss'
export default { export default {
name: 'Layout', name: 'Layout',
components: { components: {
AppMain, AppMain,
Navbar, Navbar,
RightPanel, RightPanel,
Settings, Settings,
Sidebar, Sidebar,
TagsView TagsView
}, },
mixins: [ResizeMixin], mixins: [ResizeMixin],
computed: { computed: {
...mapState({ ...mapState({
theme: state => state.settings.theme, theme: state => state.settings.theme,
sideTheme: state => state.settings.sideTheme, sideTheme: state => state.settings.sideTheme,
sidebar: state => state.app.sidebar, sidebar: state => state.app.sidebar,
device: state => state.app.device, device: state => state.app.device,
showSettings: state => state.settings.showSettings, showSettings: state => state.settings.showSettings,
needTagsView: state => state.settings.tagsView, needTagsView: state => state.settings.tagsView,
fixedHeader: state => state.settings.fixedHeader fixedHeader: state => state.settings.fixedHeader
}), }),
classObj() { classObj () {
return { return {
hideSidebar: !this.sidebar.opened, hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened, openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation, withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile' mobile: this.device === 'mobile'
} }
}, },
variables() { variables () {
return variables; return variables
} }
}, },
methods: { methods: {
handleClickOutside() { handleClickOutside () {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~@/assets/styles/mixin.scss"; @import "~@/assets/styles/mixin.scss";
@import "~@/assets/styles/variables.scss"; @import "~@/assets/styles/variables.scss";
.app-wrapper { .app-wrapper {
@include clearfix; @include clearfix;
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
&.mobile.openSidebar { &.mobile.openSidebar {
position: fixed; position: fixed;
top: 0; top: 0;
} }
} }
.drawer-bg { .drawer-bg {
background: #000; background: #000;
opacity: 0.3; opacity: 0.3;
width: 100%; width: 100%;
top: 0; top: 0;
height: 100%; height: 100%;
position: absolute; position: absolute;
z-index: 999; z-index: 999;
} }
.fixed-header { .fixed-header {
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
z-index: 9; z-index: 9;
width: calc(100% - #{$sideBarWidth}); width: calc(100% - #{$sideBarWidth});
transition: width 0.28s; transition: width 0.28s;
} }
.hideSidebar .fixed-header { .hideSidebar .fixed-header {
width: calc(100% - 54px) width: calc(100% - 54px)
} }
.mobile .fixed-header { .mobile .fixed-header {
width: 100%; width: 100%;
} }
</style> </style>

View File

@ -1,45 +1,45 @@
import store from '@/store' import store from '@/store'
const { body } = document const { body } = document
const WIDTH = 992 // refer to Bootstrap's responsive design const WIDTH = 992 // refer to Bootstrap's responsive design
export default { export default {
watch: { watch: {
$route(route) { $route (route) {
if (this.device === 'mobile' && this.sidebar.opened) { if (this.device === 'mobile' && this.sidebar.opened) {
store.dispatch('app/closeSideBar', { withoutAnimation: false }) store.dispatch('app/closeSideBar', { withoutAnimation: false })
} }
} }
}, },
beforeMount() { beforeMount () {
window.addEventListener('resize', this.$_resizeHandler) window.addEventListener('resize', this.$_resizeHandler)
}, },
beforeDestroy() { beforeDestroy () {
window.removeEventListener('resize', this.$_resizeHandler) window.removeEventListener('resize', this.$_resizeHandler)
}, },
mounted() { mounted () {
const isMobile = this.$_isMobile() const isMobile = this.$_isMobile()
if (isMobile) { if (isMobile) {
store.dispatch('app/toggleDevice', 'mobile') store.dispatch('app/toggleDevice', 'mobile')
store.dispatch('app/closeSideBar', { withoutAnimation: true }) store.dispatch('app/closeSideBar', { withoutAnimation: true })
} }
}, },
methods: { methods: {
// use $_ for mixins properties // use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_isMobile() { $_isMobile () {
const rect = body.getBoundingClientRect() const rect = body.getBoundingClientRect()
return rect.width - 1 < WIDTH return rect.width - 1 < WIDTH
}, },
$_resizeHandler() { $_resizeHandler () {
if (!document.hidden) { if (!document.hidden) {
const isMobile = this.$_isMobile() const isMobile = this.$_isMobile()
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
if (isMobile) { if (isMobile) {
store.dispatch('app/closeSideBar', { withoutAnimation: true }) store.dispatch('app/closeSideBar', { withoutAnimation: true })
} }
} }
} }
} }
} }

View File

@ -1,88 +1,89 @@
import Vue from 'vue' import Vue from 'vue'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import Element from 'element-ui' import Element from 'element-ui'
import './assets/styles/element-variables.scss' import './assets/styles/element-variables.scss'
import '@/assets/styles/index.scss' // global css import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css import '@/assets/styles/ruoyi.scss' // ruoyi css
import App from './App' import App from './App'
import store from './store' import store from './store'
import router from './router' import router from './router'
import directive from './directive' //directive import directive from './directive' // directive
import './assets/icons' // icon import './assets/icons' // icon
import './permission' // permission control import './permission' // permission control
import { getDicts } from "@/api/system/dict/data"; import { getDicts } from '@/api/system/dict/data'
import { getConfigKey } from "@/api/system/config"; import { getConfigKey } from '@/api/system/config'
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree } from "@/utils/ruoyi"; import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree } from '@/utils/ruoyi'
import Pagination from "@/components/Pagination"; import Pagination from '@/components/Pagination'
// 自定义表格工具组件 // 自定义表格工具组件
import RightToolbar from "@/components/RightToolbar" import RightToolbar from '@/components/RightToolbar'
// 富文本组件 // 富文本组件
import Editor from "@/components/Editor" import Editor from '@/components/Editor'
// 文件上传组件 // 文件上传组件
import FileUpload from "@/components/FileUpload" import FileUpload from '@/components/FileUpload'
// 图片上传组件 // 图片上传组件
import ImageUpload from "@/components/ImageUpload" import ImageUpload from '@/components/ImageUpload'
// 字典标签组件 // 字典标签组件
import DictTag from '@/components/DictTag' import DictTag from '@/components/DictTag'
// 头部标签组件 // 头部标签组件
import VueMeta from 'vue-meta' import VueMeta from 'vue-meta'
// 全局方法挂载 // 全局方法挂载
Vue.prototype.getDicts = getDicts Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download Vue.prototype.download = download
Vue.prototype.handleTree = handleTree Vue.prototype.handleTree = handleTree
Vue.prototype.msgSuccess = function (msg) { Vue.prototype.msgSuccess = function (msg) {
this.$message({ showClose: true, message: msg, type: "success" }); this.$message({ showClose: true, message: msg, type: 'success' })
} }
Vue.prototype.msgError = function (msg) { Vue.prototype.msgError = function (msg) {
this.$message({ showClose: true, message: msg, type: "error" }); this.$message({ showClose: true, message: msg, type: 'error' })
} }
Vue.prototype.msgInfo = function (msg) { Vue.prototype.msgInfo = function (msg) {
this.$message.info(msg); this.$message.info(msg)
} }
// 全局组件挂载 // 全局组件挂载
Vue.component('DictTag', DictTag) Vue.component('DictTag', DictTag)
Vue.component('Pagination', Pagination) Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar) Vue.component('RightToolbar', RightToolbar)
Vue.component('Editor', Editor) Vue.component('Editor', Editor)
Vue.component('FileUpload', FileUpload) Vue.component('FileUpload', FileUpload)
Vue.component('ImageUpload', ImageUpload) Vue.component('ImageUpload', ImageUpload)
Vue.use(directive) Vue.use(directive)
Vue.use(VueMeta) Vue.use(VueMeta)
/** /**
* If you don't want to use mock-server * If you don't want to use mock-server
* you want to use MockJs for mock api * you want to use MockJs for mock api
* you can execute: mockXHR() * you can execute: mockXHR()
* *
* Currently MockJs will be used in the production environment, * Currently MockJs will be used in the production environment,
* please remove it before going online! ! ! * please remove it before going online! ! !
*/ */
Vue.use(Element, { Vue.use(Element, {
size: Cookies.get('size') || 'medium' // set element-ui default size size: Cookies.get('size') || 'medium' // set element-ui default size
}) })
Vue.config.productionTip = false Vue.config.productionTip = false
new Vue({ // eslint-disable-next-line no-new
el: '#app', new Vue({
router, el: '#app',
store, router,
render: h => h(App) store,
}) render: h => h(App)
})

View File

@ -1,53 +1,53 @@
import router from './router' import router from './router'
import store from './store' import store from './store'
import { Message } from 'element-ui' import { Message } from 'element-ui'
import NProgress from 'nprogress' import NProgress from 'nprogress'
import 'nprogress/nprogress.css' import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.start() NProgress.start()
if (getToken()) { if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title) to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/ /* has token */
if (to.path === '/login') { if (to.path === '/login') {
next({ path: '/' }) next({ path: '/' })
NProgress.done() NProgress.done()
} else { } else {
if (store.getters.roles.length === 0) { if (store.getters.roles.length === 0) {
// 判断当前用户是否已拉取完user_info信息 // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => { store.dispatch('GetInfo').then(() => {
store.dispatch('GenerateRoutes').then(accessRoutes => { store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表 // 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表 router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
}) })
}).catch(err => { }).catch(err => {
store.dispatch('LogOut').then(() => { store.dispatch('LogOut').then(() => {
Message.error(err) Message.error(err)
next({ path: '/' }) next({ path: '/' })
}) })
}) })
} else { } else {
next() next()
} }
} }
} else { } else {
// 没有token // 没有token
if (whiteList.indexOf(to.path) !== -1) { if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入 // 在免登录白名单,直接进入
next() next()
} else { } else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done() NProgress.done()
} }
} }
}) })
router.afterEach(() => { router.afterEach(() => {
NProgress.done() NProgress.done()
}) })

View File

@ -1,159 +1,159 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
Vue.use(Router) /* Layout */
import Layout from '@/layout'
/* Layout */
import Layout from '@/layout' Vue.use(Router)
/** /**
* Note: 路由配置项 * Note: 路由配置项
* *
* hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401login等页面或者如一些编辑页面/edit/1 * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401login等页面或者如一些编辑页面/edit/1
* alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时自动会变成嵌套的模式--如组件页面 * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时自动会变成嵌套的模式--如组件页面
* // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面 * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
* // 若你想不管路由下面的 children 声明的个数都显示你的根路由 * // 若你想不管路由下面的 children 声明的个数都显示你的根路由
* // 你可以设置 alwaysShow: true这样它就会忽略之前定义的规则一直显示根路由 * // 你可以设置 alwaysShow: true这样它就会忽略之前定义的规则一直显示根路由
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
* name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题 * name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
* meta : { * meta : {
noCache: true // 如果设置为true则不会被 <keep-alive> 缓存(默认 false) noCache: true // 如果设置为true则不会被 <keep-alive> 缓存(默认 false)
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
icon: 'svg-name' // 设置该路由的图标对应路径src/assets/icons/svg icon: 'svg-name' // 设置该路由的图标对应路径src/assets/icons/svg
breadcrumb: false // 如果设置为false则不会在breadcrumb面包屑中显示 breadcrumb: false // 如果设置为false则不会在breadcrumb面包屑中显示
activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。
} }
*/ */
// 公共路由 // 公共路由
export const constantRoutes = [ export const constantRoutes = [
{ {
path: '/redirect', path: '/redirect',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: '/redirect/:path(.*)', path: '/redirect/:path(.*)',
component: (resolve) => require(['@/views/redirect'], resolve) component: (resolve) => require(['@/views/redirect'], resolve)
} }
] ]
}, },
{ {
path: '/login', path: '/login',
component: (resolve) => require(['@/views/login'], resolve), component: (resolve) => require(['@/views/login'], resolve),
hidden: true hidden: true
}, },
{ {
path: '/register', path: '/register',
component: (resolve) => require(['@/views/register'], resolve), component: (resolve) => require(['@/views/register'], resolve),
hidden: true hidden: true
}, },
{ {
path: '/404', path: '/404',
component: (resolve) => require(['@/views/error/404'], resolve), component: (resolve) => require(['@/views/error/404'], resolve),
hidden: true hidden: true
}, },
{ {
path: '/401', path: '/401',
component: (resolve) => require(['@/views/error/401'], resolve), component: (resolve) => require(['@/views/error/401'], resolve),
hidden: true hidden: true
}, },
{ {
path: '', path: '',
component: Layout, component: Layout,
redirect: 'index', redirect: 'index',
children: [ children: [
{ {
path: 'index', path: 'index',
component: (resolve) => require(['@/views/index'], resolve), component: (resolve) => require(['@/views/index'], resolve),
name: 'Index', name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true } meta: { title: '首页', icon: 'dashboard', affix: true }
} }
] ]
}, },
{ {
path: '/user', path: '/user',
component: Layout, component: Layout,
hidden: true, hidden: true,
redirect: 'noredirect', redirect: 'noredirect',
children: [ children: [
{ {
path: 'profile', path: 'profile',
component: (resolve) => require(['@/views/system/user/profile/index'], resolve), component: (resolve) => require(['@/views/system/user/profile/index'], resolve),
name: 'Profile', name: 'Profile',
meta: { title: '个人中心', icon: 'user' } meta: { title: '个人中心', icon: 'user' }
} }
] ]
}, },
{ {
path: '/system/user-auth', path: '/system/user-auth',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'role/:userId(\\d+)', path: 'role/:userId(\\d+)',
component: (resolve) => require(['@/views/system/user/authRole'], resolve), component: (resolve) => require(['@/views/system/user/authRole'], resolve),
name: 'AuthRole', name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user'} meta: { title: '分配角色', activeMenu: '/system/user' }
} }
] ]
}, },
{ {
path: '/system/role-auth', path: '/system/role-auth',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'user/:roleId(\\d+)', path: 'user/:roleId(\\d+)',
component: (resolve) => require(['@/views/system/role/authUser'], resolve), component: (resolve) => require(['@/views/system/role/authUser'], resolve),
name: 'AuthUser', name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role'} meta: { title: '分配用户', activeMenu: '/system/role' }
} }
] ]
}, },
{ {
path: '/system/dict-data', path: '/system/dict-data',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'index/:dictId(\\d+)', path: 'index/:dictId(\\d+)',
component: (resolve) => require(['@/views/system/dict/data'], resolve), component: (resolve) => require(['@/views/system/dict/data'], resolve),
name: 'Data', name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict'} meta: { title: '字典数据', activeMenu: '/system/dict' }
} }
] ]
}, },
{ {
path: '/monitor/job-log', path: '/monitor/job-log',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'index', path: 'index',
component: (resolve) => require(['@/views/monitor/job/log'], resolve), component: (resolve) => require(['@/views/monitor/job/log'], resolve),
name: 'JobLog', name: 'JobLog',
meta: { title: '调度日志', activeMenu: '/monitor/job'} meta: { title: '调度日志', activeMenu: '/monitor/job' }
} }
] ]
}, },
{ {
path: '/tool/gen-edit', path: '/tool/gen-edit',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: 'index/:tableId(\\d+)', path: 'index/:tableId(\\d+)',
component: (resolve) => require(['@/views/tool/gen/editTable'], resolve), component: (resolve) => require(['@/views/tool/gen/editTable'], resolve),
name: 'GenEdit', name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen'} meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
} }
] ]
} }
] ]
export default new Router({ export default new Router({
mode: 'history', // 去掉url中的# mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }), scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes routes: constantRoutes
}) })

View File

@ -1,44 +1,44 @@
module.exports = { module.exports = {
/** /**
* 侧边栏主题 深色主题theme-dark浅色主题theme-light * 侧边栏主题 深色主题theme-dark浅色主题theme-light
*/ */
sideTheme: 'theme-dark', sideTheme: 'theme-dark',
/** /**
* 是否系统布局配置 * 是否系统布局配置
*/ */
showSettings: false, showSettings: false,
/** /**
* 是否显示顶部导航 * 是否显示顶部导航
*/ */
topNav: false, topNav: false,
/** /**
* 是否显示 tagsView * 是否显示 tagsView
*/ */
tagsView: true, tagsView: true,
/** /**
* 是否固定头部 * 是否固定头部
*/ */
fixedHeader: false, fixedHeader: false,
/** /**
* 是否显示logo * 是否显示logo
*/ */
sidebarLogo: true, sidebarLogo: true,
/** /**
* 是否显示动态标题 * 是否显示动态标题
*/ */
dynamicTitle: false, dynamicTitle: false,
/** /**
* @type {string | array} 'production' | ['production', 'development'] * @type {string | array} 'production' | ['production', 'development']
* @description Need show err logs component. * @description Need show err logs component.
* The default is only used in the production env * The default is only used in the production env
* If you want to also use it in dev, you can pass ['production', 'development'] * If you want to also use it in dev, you can pass ['production', 'development']
*/ */
errorLog: 'production' errorLog: 'production'
} }

View File

@ -1,18 +1,18 @@
const getters = { const getters = {
sidebar: state => state.app.sidebar, sidebar: state => state.app.sidebar,
size: state => state.app.size, size: state => state.app.size,
device: state => state.app.device, device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews, visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews, cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token, token: state => state.user.token,
avatar: state => state.user.avatar, avatar: state => state.user.avatar,
name: state => state.user.name, name: state => state.user.name,
introduction: state => state.user.introduction, introduction: state => state.user.introduction,
roles: state => state.user.roles, roles: state => state.user.roles,
permissions: state => state.user.permissions, permissions: state => state.user.permissions,
permission_routes: state => state.permission.routes, permission_routes: state => state.permission.routes,
topbarRouters:state => state.permission.topbarRouters, topbarRouters: state => state.permission.topbarRouters,
defaultRoutes:state => state.permission.defaultRoutes, defaultRoutes: state => state.permission.defaultRoutes,
sidebarRouters:state => state.permission.sidebarRouters, sidebarRouters: state => state.permission.sidebarRouters
} }
export default getters export default getters

View File

@ -1,23 +1,23 @@
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import app from './modules/app' import app from './modules/app'
import user from './modules/user' import user from './modules/user'
import tagsView from './modules/tagsView' import tagsView from './modules/tagsView'
import permission from './modules/permission' import permission from './modules/permission'
import settings from './modules/settings' import settings from './modules/settings'
import getters from './getters' import getters from './getters'
Vue.use(Vuex) Vue.use(Vuex)
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: { modules: {
app, app,
user, user,
tagsView, tagsView,
permission, permission,
settings settings
}, },
getters getters
}) })
export default store export default store

View File

@ -1,56 +1,56 @@
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
const state = { const state = {
sidebar: { sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false withoutAnimation: false
}, },
device: 'desktop', device: 'desktop',
size: Cookies.get('size') || 'medium' size: Cookies.get('size') || 'medium'
} }
const mutations = { const mutations = {
TOGGLE_SIDEBAR: state => { TOGGLE_SIDEBAR: state => {
state.sidebar.opened = !state.sidebar.opened state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false state.sidebar.withoutAnimation = false
if (state.sidebar.opened) { if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1) Cookies.set('sidebarStatus', 1)
} else { } else {
Cookies.set('sidebarStatus', 0) Cookies.set('sidebarStatus', 0)
} }
}, },
CLOSE_SIDEBAR: (state, withoutAnimation) => { CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 0) Cookies.set('sidebarStatus', 0)
state.sidebar.opened = false state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation state.sidebar.withoutAnimation = withoutAnimation
}, },
TOGGLE_DEVICE: (state, device) => { TOGGLE_DEVICE: (state, device) => {
state.device = device state.device = device
}, },
SET_SIZE: (state, size) => { SET_SIZE: (state, size) => {
state.size = size state.size = size
Cookies.set('size', size) Cookies.set('size', size)
} }
} }
const actions = { const actions = {
toggleSideBar({ commit }) { toggleSideBar ({ commit }) {
commit('TOGGLE_SIDEBAR') commit('TOGGLE_SIDEBAR')
}, },
closeSideBar({ commit }, { withoutAnimation }) { closeSideBar ({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation) commit('CLOSE_SIDEBAR', withoutAnimation)
}, },
toggleDevice({ commit }, device) { toggleDevice ({ commit }, device) {
commit('TOGGLE_DEVICE', device) commit('TOGGLE_DEVICE', device)
}, },
setSize({ commit }, size) { setSize ({ commit }, size) {
commit('SET_SIZE', size) commit('SET_SIZE', size)
} }
} }
export default { export default {
namespaced: true, namespaced: true,
state, state,
mutations, mutations,
actions actions
} }

View File

@ -1,113 +1,113 @@
import { constantRoutes } from '@/router' import { constantRoutes } from '@/router'
import { getRouters } from '@/api/menu' import { getRouters } from '@/api/menu'
import Layout from '@/layout/index' import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'; import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink' import InnerLink from '@/layout/components/InnerLink'
const permission = { const permission = {
state: { state: {
routes: [], routes: [],
addRoutes: [], addRoutes: [],
defaultRoutes: [], defaultRoutes: [],
topbarRouters: [], topbarRouters: [],
sidebarRouters: [] sidebarRouters: []
}, },
mutations: { mutations: {
SET_ROUTES: (state, routes) => { SET_ROUTES: (state, routes) => {
state.addRoutes = routes state.addRoutes = routes
state.routes = constantRoutes.concat(routes) state.routes = constantRoutes.concat(routes)
}, },
SET_DEFAULT_ROUTES: (state, routes) => { SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes) state.defaultRoutes = constantRoutes.concat(routes)
}, },
SET_TOPBAR_ROUTES: (state, routes) => { SET_TOPBAR_ROUTES: (state, routes) => {
// 顶部导航菜单默认添加统计报表栏指向首页 // 顶部导航菜单默认添加统计报表栏指向首页
const index = [{ const index = [{
path: 'index', path: 'index',
meta: { title: '统计报表', icon: 'dashboard'} meta: { title: '统计报表', icon: 'dashboard' }
}] }]
state.topbarRouters = routes.concat(index); state.topbarRouters = routes.concat(index)
}, },
SET_SIDEBAR_ROUTERS: (state, routes) => { SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes state.sidebarRouters = routes
}, }
}, },
actions: { actions: {
// 生成路由 // 生成路由
GenerateRoutes({ commit }) { GenerateRoutes ({ commit }) {
return new Promise(resolve => { return new Promise(resolve => {
// 向后端请求路由数据 // 向后端请求路由数据
getRouters().then(res => { getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data)) const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data)) const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata) const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true) const rewriteRoutes = filterAsyncRouter(rdata, false, true)
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
commit('SET_ROUTES', rewriteRoutes) commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes) commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes) commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes) resolve(rewriteRoutes)
}) })
}) })
} }
} }
} }
// 遍历后台传来的路由字符串,转换为组件对象 // 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { function filterAsyncRouter (asyncRouterMap, lastRouter = false, type = false) {
return asyncRouterMap.filter(route => { return asyncRouterMap.filter(route => {
if (type && route.children) { if (type && route.children) {
route.children = filterChildren(route.children) route.children = filterChildren(route.children)
} }
if (route.component) { if (route.component) {
// Layout ParentView 组件特殊处理 // Layout ParentView 组件特殊处理
if (route.component === 'Layout') { if (route.component === 'Layout') {
route.component = Layout route.component = Layout
} else if (route.component === 'ParentView') { } else if (route.component === 'ParentView') {
route.component = ParentView route.component = ParentView
} else if (route.component === 'InnerLink') { } else if (route.component === 'InnerLink') {
route.component = InnerLink route.component = InnerLink
} else { } else {
route.component = loadView(route.component) route.component = loadView(route.component)
} }
} }
if (route.children != null && route.children && route.children.length) { if (route.children !== null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type) route.children = filterAsyncRouter(route.children, route, type)
} else { } else {
delete route['children'] delete route.children
delete route['redirect'] delete route.redirect
} }
return true return true
}) })
} }
function filterChildren(childrenMap, lastRouter = false) { function filterChildren (childrenMap, lastRouter = false) {
var children = [] let children = []
childrenMap.forEach((el, index) => { childrenMap.forEach((el, index) => {
if (el.children && el.children.length) { if (el.children && el.children.length) {
if (el.component === 'ParentView') { if (el.component === 'ParentView') {
el.children.forEach(c => { el.children.forEach(c => {
c.path = el.path + '/' + c.path c.path = el.path + '/' + c.path
if (c.children && c.children.length) { if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c)) children = children.concat(filterChildren(c.children, c))
return return
} }
children.push(c) children.push(c)
}) })
return return
} }
} }
if (lastRouter) { if (lastRouter) {
el.path = lastRouter.path + '/' + el.path el.path = lastRouter.path + '/' + el.path
} }
children = children.concat(el) children = children.concat(el)
}) })
return children return children
} }
export const loadView = (view) => { // 路由懒加载 export const loadView = (view) => { // 路由懒加载
return (resolve) => require([`@/views/${view}`], resolve) return (resolve) => require([`@/views/${view}`], resolve)
} }
export default permission export default permission

View File

@ -1,43 +1,42 @@
import variables from '@/assets/styles/element-variables.scss' import variables from '@/assets/styles/element-variables.scss'
import defaultSettings from '@/settings' import defaultSettings from '@/settings'
const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
const state = { const state = {
title: '', title: '',
theme: storageSetting.theme || variables.theme, theme: storageSetting.theme || variables.theme,
sideTheme: storageSetting.sideTheme || sideTheme, sideTheme: storageSetting.sideTheme || sideTheme,
showSettings: showSettings, showSettings: showSettings,
topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
} }
const mutations = { const mutations = {
CHANGE_SETTING: (state, { key, value }) => { CHANGE_SETTING: (state, { key, value }) => {
if (state.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(state, key)) {
state[key] = value state[key] = value
} }
} }
} }
const actions = { const actions = {
// 修改布局设置 // <EFBFBD>޸IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
changeSetting({ commit }, data) { changeSetting ({ commit }, data) {
commit('CHANGE_SETTING', data) commit('CHANGE_SETTING', data)
}, },
// 设置网页标题 // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
setTitle({ commit }, title) { setTitle ({ commit }, title) {
state.title = title state.title = title
} }
} }
export default { export default {
namespaced: true, namespaced: true,
state, state,
mutations, mutations,
actions actions
} }

Some files were not shown because too many files have changed in this diff Show More