This commit is contained in:
chenxiaoxi
2021-04-20 15:25:46 +08:00
parent b2620a08a1
commit 2eb52eec59
161 changed files with 141 additions and 11301 deletions
-2
View File
@@ -1,5 +1,3 @@
# 支持浏览器配置
> 1%
last 2 versions
not dead
+3 -12
View File
@@ -1,14 +1,5 @@
# 编辑器配置
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
insert_final_newline = true
indent_size = 2
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
insert_final_newline = true
-1
View File
@@ -1,5 +1,4 @@
/**
* @description .eslintrc.js
*/
-12
View File
@@ -1,12 +0,0 @@
# .gitattributes
*.html text eol=lf
*.css text eol=lf
*.js text eol=lf
*.scss text eol=lf
*.vue text eol=lf
*.hbs text eol=lf
*.sh text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.js linguist-language=vue
+10 -13
View File
@@ -1,26 +1,23 @@
# .gitignore
.DS_Store
node_modules
dist
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn.lock
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
public/video
*.zip
*.7z
/src/layouts/components/zx-layouts
/zx-templates
/package-lock.json
/src/styles/themes/green.scss
/src/styles/themes/dark.scss
/src/styles/themes/glory.scss
-7
View File
@@ -1,7 +0,0 @@
/**
* @description stylelint
*/
module.exports = {
extends: ['stylelint-config-recess-order', 'stylelint-config-prettier'],
}
+23 -2
View File
@@ -1,3 +1,24 @@
![](public/static/images/logo.png)
# futian
### 法规智库-福田
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
-1
View File
@@ -1,5 +1,4 @@
/**
* @description babel.config
*/
module.exports = {
+19 -78
View File
@@ -1,96 +1,37 @@
{
"name": "laws-system-front-FOTON",
"name": "FOTON",
"version": "1.0.0",
"author": "rongchuangruantong",
"participants": [],
"homepage": "http://103.249.252.28:90/LAWS/laws-system-front-FOTON.git",
"author": "91isoft",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"repository": {
"type": "git",
"url": "git+http://103.249.252.28:90/LAWS/laws-system-front-FOTON.git"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"clipboard": "^2.0.8",
"core-js": "^3.10.1",
"core-js": "^3.6.5",
"dayjs": "^1.10.4",
"echarts": "^5.1.0",
"echarts-wordcloud": "^2.0.0",
"element-ui": "^2.15.1",
"jsencrypt": "^3.1.0",
"jquery": "^3.6.0",
"lodash": "^4.17.21",
"maptalks": "^0.49.3",
"mapv": "^2.0.62",
"mockjs": "^1.1.0",
"moment": "^2.29.1",
"nprogress": "^0.2.0",
"qs": "^6.10.1",
"screenfull": "^5.1.0",
"sortablejs": "^1.13.0",
"vab-icon": "^0.0.1",
"vue": "^2.6.12",
"vue-echarts": "5.0.0-beta.0",
"vue-router": "^3.5.1",
"vuex": "^3.6.2",
"zx-count": "^0.3.7",
"zx-layouts": "^0.6.24",
"zx-magnifie": "^0.4.0",
"zx-markdown-editor": "^0.0.2",
"zx-player": "^1.0.2",
"zx-quill": "^0.0.3",
"zx-templates": "^0.0.26",
"zx-verify": "^0.0.2"
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.12",
"@vue/cli-plugin-eslint": "^4.5.12",
"@vue/cli-service": "^4.5.12",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.1.0",
"body-parser": "^1.19.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"chalk": "^4.1.0",
"chokidar": "^3.5.1",
"eslint": "^7.24.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-vue": "^7.9.0",
"filemanager-webpack-plugin": "^4.0.0",
"image-webpack-loader": "^7.0.1",
"lint-staged": "^10.5.4",
"plop": "^2.7.4",
"prettier": "^2.2.1",
"sass": "^1.32.10",
"sass-loader": "^10.1.1",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.2",
"stylelint": "^13.12.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-recess-order": "^2.3.0",
"svg-sprite-loader": "^6.0.5",
"vue-template-compiler": "^2.6.12",
"webpackbar": "^4.0.0"
},
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"vue-admin",
"element-admin",
"boilerplate",
"admin-template",
"management-system"
],
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
"stylelint-config-recess-order": "^2.4.0",
"vue-template-compiler": "^2.6.11"
}
}
-16
View File
@@ -1,16 +0,0 @@
/**
* @description 代码生成机
*/
const viewGenerator = require('zx-templates/view/prompt')
const curdGenerator = require('zx-templates/curd/prompt')
const componentGenerator = require('zx-templates/component/prompt')
const mockGenerator = require('zx-templates/mock/prompt')
const vuexGenerator = require('zx-templates/vuex/prompt')
module.exports = (plop) => {
plop.setGenerator('view', viewGenerator)
plop.setGenerator('curd', curdGenerator)
plop.setGenerator('component', componentGenerator)
plop.setGenerator('mock&api', mockGenerator)
plop.setGenerator('vuex', vuexGenerator)
}
-21
View File
@@ -1,21 +0,0 @@
/**
* @description 代码规范
*/
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
quoteProps: 'as-needed',
jsxSingleQuote: false,
trailingComma: 'es5',
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: 'always',
htmlWhitespaceSensitivity: 'ignore',
vueIndentScriptAndStyle: true,
endOfLine: 'lf',
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

+24 -35
View File
@@ -1,41 +1,30 @@
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= VUE_APP_TITLE %></title>
<link rel="stylesheet" href="<%= BASE_URL %>static/css/loading.css" />
</head>
<body>
<noscript>
非常抱歉鉴于安全考量,您无法查看<%= VUE_APP_TITLE %>
源代码,该系统基于vue-admin-beautiful开发
</noscript>
<div id="vue-admin-beautiful">
<div class="first-loading-wrp">
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="<%= BASE_URL %>static/css/loading.css"/>
<title>全球标准法规系统-福田</title>
</head>
<body>
<noscript>
<strong>您的浏览器不支持该系统使用,请更换或升级浏览器</strong>
</noscript>
<div id="foton">
<div class="first-loading-wrp">
<div class="loading-wrp">
<span class="dot dot-spin">
<i></i>
<i></i>
<i></i>
<i></i>
</span>
<span class="dot dot-spin">
<i></i>
<i></i>
<i></i>
<i></i>
</span>
</div>
<h1><%= VUE_APP_TITLE %></h1>
</div>
</div>
<script>
if (window.location.hostname !== 'localhost') {
var _hmt = _hmt || []
;(function () {
var hm = document.createElement('script')
hm.src = 'https://hm.baidu.com/hm.js?7174bade1219f9cc272e7978f9523fc8'
var s = document.getElementsByTagName('script')[0]
s.parentNode.insertBefore(hm, s)
})()
}
</script>
</body>
</div>
<!-- built files will be auto injected -->
</body>
</html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 KiB

+5 -8
View File
@@ -1,12 +1,9 @@
<template>
<div id="vue-admin-beautiful">
<router-view />
<div id="foton">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
mounted() {},
}
</script>
<style lang="scss">
</style>
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/ad/getList',
method: 'get',
data,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/changeLog/getList',
method: 'post',
data,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getIconList(data) {
return request({
url: '/colorfulIcon/getList',
method: 'post',
data,
})
}
-20
View File
@@ -1,20 +0,0 @@
import request from 'axios'
export function getRepos(params) {
return request({
url: 'https://api.github.com/repos/chuzhixin/vue-admin-beautiful',
method: 'get',
params,
timeout: 10000,
})
}
export function getStargazers(params) {
return request({
url:
'https://api.github.com/repos/chuzhixin/vue-admin-beautiful/stargazers',
method: 'get',
params,
timeout: 10000,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/goodsList/getList',
method: 'post',
data,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getIconList(data) {
return request({
url: '/icon/getList',
method: 'post',
data,
})
}
-8
View File
@@ -1,8 +0,0 @@
import request from 'axios'
export function getList() {
return request({
url: 'https://cdn.jsdelivr.net/gh/prettier/prettier@master/docs/options.md',
method: 'get',
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getTree(data) {
return request({
url: '/menuManagement/getTree',
method: 'post',
data,
})
}
export function doEdit(data) {
return request({
url: '/menuManagement/doEdit',
method: 'post',
data,
})
}
export function doDelete(data) {
return request({
url: '/menuManagement/doDelete',
method: 'post',
data,
})
}
-8
View File
@@ -1,8 +0,0 @@
import request from '@/utils/request'
export function getNoticeList() {
return request({
url: '/notice/getList',
method: 'post',
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/personalCenter/getList',
method: 'post',
data,
})
}
export function doEdit(data) {
return request({
url: '/personalCenter/doEdit',
method: 'post',
data,
})
}
export function doDelete(data) {
return request({
url: '/personalCenter/doDelete',
method: 'post',
data,
})
}
-8
View File
@@ -1,8 +0,0 @@
import request from '@/utils/request'
export function getPublicKey() {
return request({
url: '/publicKey',
method: 'post',
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getIconList(data) {
return request({
url: '/remixIcon/getList',
method: 'post',
data,
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/roleManagement/getList',
method: 'post',
data,
})
}
export function doEdit(data) {
return request({
url: '/roleManagement/doEdit',
method: 'post',
data,
})
}
export function doDelete(data) {
return request({
url: '/roleManagement/doDelete',
method: 'post',
data,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getRouterList(data) {
return request({
url: '/menu/navigate',
method: 'post',
data,
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/table/getList',
method: 'post',
data,
})
}
export function doEdit(data) {
return request({
url: '/table/doEdit',
method: 'post',
data,
})
}
export function doDelete(data) {
return request({
url: '/table/doDelete',
method: 'post',
data,
})
}
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getTreeList(data) {
return request({
url: '/tree/list',
method: 'post',
data,
})
}
-38
View File
@@ -1,38 +0,0 @@
import request from '@/utils/request'
import { encryptedData } from '@/utils/encrypt'
import { loginRSA, tokenName } from '@/config'
export async function login(data) {
if (loginRSA) {
data = await encryptedData(data)
}
return request({
url: '/login',
method: 'post',
data,
})
}
export function getUserInfo(accessToken) {
return request({
url: '/userInfo',
method: 'post',
data: {
[tokenName]: accessToken,
},
})
}
export function logout() {
return request({
url: '/logout',
method: 'post',
})
}
export function register() {
return request({
url: '/register',
method: 'post',
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getList(data) {
return request({
url: '/userManagement/getList',
method: 'post',
data,
})
}
export function doEdit(data) {
return request({
url: '/userManagement/doEdit',
method: 'post',
data,
})
}
export function doDelete(data) {
return request({
url: '/userManagement/doDelete',
method: 'post',
data,
})
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

@@ -1,5 +1,5 @@
/**
* @author chuzhixin 1204505056@qq.com 不想保留author可删除
* @description 全局加载动画
*/
@@ -1,5 +1,5 @@
/**
* @author chuzhixin 1204505056@qq.com 不想保留author可删除
* @description vue过渡动画
*/
@@ -1,5 +1,5 @@
/**
* @author chuzhixin 1204505056@qq.com 不想保留author可删除
* @description 全局样式
*/
@@ -1,5 +1,5 @@
/**
* @author chuzhixin 1204505056@qq.com 不想保留author可删除
* @description 全局主题变量配置
*/
/* stylelint-disable */
Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

-13
View File
@@ -1,13 +0,0 @@
const req = require.context('./svg', false, /\.svg$/),
requireAll = (requireContext) => {
/*let a = requireContext.keys().map(requireContext);
let arr = [];
for (let i = 0; i < a.length; i++) {
console.log();
let icon = a[i].default.id;
arr.push(icon);
}
console.log(JSON.stringify(arr));*/
return requireContext.keys().map(requireContext)
}
requireAll(req)
@@ -1 +0,0 @@
<svg class="icon" width="128" height="128" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M358.4 853.333H245.333l-23.466 64H147.2l121.6-324.266h61.867l119.466 324.266h-68.266l-23.467-64zm-98.133-57.6h81.066l-40.533-121.6-40.533 121.6zm4.266-418.133h162.134v53.333H179.2V390.4L341.333 160H179.2v-53.333h243.2v36.266L264.533 377.6z" fill="#2196F3"/><path d="M810.667 704V106.667h-85.334V704h-128L768 917.333 938.667 704z" fill="#546E7A"/></svg>

Before

Width:  |  Height:  |  Size: 463 B

-21
View File
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
width="550px" height="400px"
xml:space="preserve">
<g id="PathID_1" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
<path style="fill: #41b882; fill-opacity: 1;" d="M3.75 -36.65L18.4 -36.65Q22.75 -36.65 24.85 -36.25Q27 -35.9 28.7 -34.75Q30.4 -33.6 31.5 -31.7Q32.65 -29.8 32.65 -27.4Q32.65 -24.85 31.25 -22.7Q29.85 -20.55 27.5 -19.5Q30.85 -18.5 32.65 -16.15Q34.45 -13.8 34.45 -10.6Q34.45 -8.1 33.25 -5.75Q32.1 -3.4 30.1 -1.95Q28.1 -0.55 25.15 -0.25Q23.3 -0.05 16.2 0L3.75 0L3.75 -36.65M11.15 -30.55L11.15 -22.1L16 -22.1Q20.3 -22.1 21.35 -22.2Q23.25 -22.4 24.35 -23.5Q25.45 -24.6 25.45 -26.35Q25.45 -28.05 24.5 -29.1Q23.55 -30.2 21.7 -30.4Q20.6 -30.55 15.4 -30.55L11.15 -30.55M11.15 -16L11.15 -6.2L18 -6.2Q22 -6.2 23.05 -6.4Q24.7 -6.7 25.75 -7.85Q26.8 -9.05 26.8 -11Q26.8 -12.65 26 -13.8Q25.2 -14.95 23.65 -15.45Q22.15 -16 17.1 -16L11.15 -16" />
</g>
<g id="PathID_2" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
</g>
<g id="PathID_3" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
</g>
<g id="PathID_4" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
</g>
<g id="PathID_5" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
</g>
<g id="PathID_6" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

-201
View File
@@ -1,201 +0,0 @@
<template>
<div class="select-tree-template">
<el-select
v-model="selectValue"
:clearable="clearable"
:collapse-tags="selectType == 'multiple'"
:multiple="selectType == 'multiple'"
class="vab-tree-select"
value-key="id"
@clear="clearHandle"
@remove-tag="removeTag"
>
<el-option :value="selectKey">
<el-tree
id="treeOption"
ref="treeOption"
:current-node-key="currentNodeKey"
:data="treeOptions"
:default-checked-keys="defaultSelectedKeys"
:default-expanded-keys="defaultSelectedKeys"
:highlight-current="true"
:props="defaultProps"
:show-checkbox="selectType == 'multiple'"
node-key="id"
@check="checkNode"
@node-click="nodeClick"
></el-tree>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
name: 'SelectTreeTemplate',
props: {
/* 树形结构数据 */
treeOptions: {
type: Array,
default: () => {
return []
},
},
/* 单选/多选 */
selectType: {
type: String,
default: () => {
return 'single'
},
},
/* 初始选中值key */
selectedKey: {
type: String,
default: () => {
return ''
},
},
/* 初始选中值name */
selectedValue: {
type: String,
default: () => {
return ''
},
},
/* 可做选择的层级 */
selectLevel: {
type: [String, Number],
default: () => {
return ''
},
},
/* 可清空选项 */
clearable: {
type: Boolean,
default: () => {
return true
},
},
},
data() {
return {
defaultProps: {
children: 'children',
label: 'name',
},
defaultSelectedKeys: [], //初始选中值数组
currentNodeKey: this.selectedKey,
selectValue:
this.selectType == 'multiple'
? this.selectedValue.split(',')
: this.selectedValue, //下拉框选中值label
selectKey:
this.selectType == 'multiple'
? this.selectedKey.split(',')
: this.selectedKey, //下拉框选中值value
}
},
mounted() {
const that = this
this.initTree()
},
methods: {
// 初始化树的值
initTree() {
const that = this
if (that.selectedKey) {
that.defaultSelectedKeys = that.selectedKey.split(',') // 设置默认展开
if (that.selectType == 'single') {
that.$refs.treeOption.setCurrentKey(that.selectedKey) // 设置默认选中
} else {
that.$refs.treeOption.setCheckedKeys(that.defaultSelectedKeys)
}
}
},
// 清除选中
clearHandle() {
const that = this
this.selectValue = ''
this.selectKey = ''
this.defaultSelectedKeys = []
this.currentNodeKey = ''
this.clearSelected()
if (that.selectType == 'single') {
that.$refs.treeOption.setCurrentKey('') // 设置默认选中
} else {
that.$refs.treeOption.setCheckedKeys([])
}
},
/* 清空选中样式 */
clearSelected() {
const allNode = document.querySelectorAll('#treeOption .el-tree-node')
allNode.forEach((element) => element.classList.remove('is-current'))
},
// select多选时移除某项操作
removeTag(val) {
this.$refs.treeOption.setCheckedKeys([])
},
// 点击叶子节点
nodeClick(data, node, el) {
if (data.rank >= this.selectLevel) {
this.selectValue = data.name
this.selectKey = data.id
}
},
// 节点选中操作
checkNode(data, node, el) {
const checkedNodes = this.$refs.treeOption.getCheckedNodes()
const keyArr = []
const valueArr = []
checkedNodes.forEach((item) => {
if (item.rank >= this.selectLevel) {
keyArr.push(item.id)
valueArr.push(item.name)
}
})
this.selectValue = valueArr
this.selectKey = keyArr
},
},
}
</script>
<style lang="scss" scoped>
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
height: auto;
max-height: 274px;
padding: 0;
overflow-y: auto;
}
.el-select-dropdown__item.selected {
font-weight: normal;
}
ul li > .el-tree .el-tree-node__content {
height: auto;
padding: 0 20px;
}
.el-tree-node__label {
font-weight: normal;
}
.el-tree > .is-current .el-tree-node__label {
font-weight: 700;
color: #409eff;
}
.el-tree > .is-current .el-tree-node__children .el-tree-node__label {
font-weight: normal;
color: #606266;
}
</style>
<style lang="scss">
/* .vab-tree-select{
.el-tag__close.el-icon-close{
width:0;
overflow:hidden;
}
} */
</style>
-191
View File
@@ -1,191 +0,0 @@
<template>
<div class="content">
<div class="g-container" :style="styleObj">
<div class="g-number">
<vab-count
:start-val="startVal"
:end-val="endVal"
:duration="duration"
:separator="separator"
:prefix="prefix"
:suffix="suffix"
:decimals="decimals"
/>
</div>
<div class="g-contrast">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li v-for="(item, index) in 15" :key="index"></li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'VabCharge',
props: {
styleObj: {
type: Object,
default: () => {
return {}
},
},
startVal: {
type: Number,
default: 0,
},
endVal: {
type: Number,
default: 100,
},
},
data() {
return {
decimals: 2,
prefix: '',
suffix: '%',
separator: ',',
duration: 3000,
}
},
created() {},
mounted() {},
methods: {},
}
</script>
<style lang="scss" scoped>
.content {
position: relative;
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
width: 100%;
background: #000;
.g-number {
position: absolute;
top: 27%;
z-index: 99;
width: 300px;
font-size: 32px;
color: #fff;
text-align: center;
}
.g-container {
position: relative;
width: 300px;
height: 400px;
margin: auto;
}
.g-contrast {
width: 300px;
height: 400px;
overflow: hidden;
background-color: #000;
filter: contrast(15) hue-rotate(0);
animation: hueRotate 10s infinite linear;
}
.g-circle {
position: relative;
box-sizing: border-box;
width: 300px;
height: 300px;
filter: blur(8px);
&::after {
position: absolute;
top: 40%;
left: 50%;
width: 200px;
height: 200px;
content: '';
background-color: #00ff6f;
border-radius: 42% 38% 62% 49% / 45%;
transform: translate(-50%, -50%) rotate(0);
animation: rotate 10s infinite linear;
}
&::before {
position: absolute;
top: 40%;
left: 50%;
z-index: 99;
width: 176px;
height: 176px;
content: '';
background-color: #000;
border-radius: 50%;
transform: translate(-50%, -50%);
}
}
.g-bubbles {
position: absolute;
bottom: 0;
left: 50%;
width: 100px;
height: 40px;
background-color: #00ff6f;
filter: blur(5px);
border-radius: 100px 100px 0 0;
transform: translate(-50%, 0);
}
li {
position: absolute;
background: #00ff6f;
border-radius: 50%;
}
@for $i from 0 through 15 {
li:nth-child(#{$i}) {
$width: 15 + random(15) + px;
top: 50%;
left: 15 + random(70) + px;
width: $width;
height: $width;
transform: translate(-50%, -50%);
animation: moveToTop
#{random(6) +
3}s
ease-in-out -#{random(5000) /
1000}s
infinite;
}
}
@keyframes rotate {
50% {
border-radius: 45% / 42% 38% 58% 49%;
}
100% {
transform: translate(-50%, -50%) rotate(720deg);
}
}
@keyframes moveToTop {
90% {
opacity: 1;
}
100% {
opacity: 0.1;
transform: translate(-50%, -180px);
}
}
@keyframes hueRotate {
100% {
filter: contrast(15) hue-rotate(360deg);
}
}
}
</style>
-313
View File
@@ -1,313 +0,0 @@
<template>
<div class="card" :style="styleObj">
<div class="card-borders">
<div class="border-top"></div>
<div class="border-right"></div>
<div class="border-bottom"></div>
<div class="border-left"></div>
</div>
<div class="card-content">
<el-image :src="avatar" class="avatar"></el-image>
<div class="username">{{ username }}</div>
<div class="social-icons">
<a
v-for="(item, index) in iconArray"
:key="index"
class="social-icon"
:href="item.url"
target="_blank"
>
<vab-icon :icon="['fas', item.icon]" />
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'VabProfile',
props: {
styleObj: {
type: Object,
default: () => {
return {}
},
},
username: {
type: String,
default: '',
},
avatar: {
type: String,
default: '',
},
iconArray: {
type: Array,
default: () => {
return [
{ icon: 'bell', url: '' },
{ icon: 'bookmark', url: '' },
{ icon: 'cloud-sun', url: '' },
]
},
},
},
data() {
return {}
},
created() {},
mounted() {},
methods: {},
}
</script>
<style lang="scss" scoped>
.card {
--card-bg-color: hsl(240, 31%, 25%);
--card-bg-color-transparent: hsla(240, 31%, 25%, 0.7);
position: relative;
width: 100%;
height: 100%;
.card-borders {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
.border-top {
position: absolute;
top: 0;
width: 100%;
height: 2px;
background: var(--card-bg-color);
transform: translateX(-100%);
animation: slide-in-horizontal 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
forwards;
}
.border-right {
position: absolute;
right: 0;
width: 2px;
height: 100%;
background: var(--card-bg-color);
transform: translateY(100%);
animation: slide-in-vertical 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
forwards;
}
.border-bottom {
position: absolute;
bottom: 0;
width: 100%;
height: 2px;
background: var(--card-bg-color);
transform: translateX(100%);
animation: slide-in-horizontal-reverse 0.8s
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
}
.border-left {
position: absolute;
top: 0;
width: 2px;
height: 100%;
background: var(--card-bg-color);
transform: translateY(-100%);
animation: slide-in-vertical-reverse 0.8s
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
}
}
.card-content {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
padding: 40px 0 40px 0;
background: var(--card-bg-color-transparent);
opacity: 0;
transform: scale(0.6);
animation: bump-in 0.5s 0.8s forwards;
.avatar {
width: 80px;
height: 80px;
border: 1px solid $base-color-white;
border-radius: 50%;
opacity: 0;
transform: scale(0.6);
animation: bump-in 0.5s 1s forwards;
}
.username {
position: relative;
margin-top: 20px;
margin-bottom: 20px;
font-size: 26px;
color: transparent;
letter-spacing: 2px;
animation: fill-text-white 1.2s 2s forwards;
&::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: black;
content: '';
background: #35b9f1;
transform: scaleX(0);
transform-origin: left;
animation: slide-in-out 1.2s 1.2s cubic-bezier(0.75, 0, 0, 1) forwards;
}
}
.social-icons {
display: flex;
.social-icon {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 2.5em;
height: 2.5em;
margin: 0 15px;
color: white;
text-decoration: none;
border-radius: 50%;
@for $i from 1 through 3 {
&:nth-child(#{$i}) {
&::before {
animation-delay: 2s + 0.1s * $i;
}
&::after {
animation-delay: 2.1s + 0.1s * $i;
}
svg {
animation-delay: 2.2s + 0.1s * $i;
}
}
}
&::before,
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
border-radius: inherit;
transform: scale(0);
}
&::before {
background: #f7f1e3;
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
&::after {
background: #2c3e50;
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
svg {
z-index: 99;
transform: scale(0);
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
}
}
}
}
}
@keyframes bump-in {
50% {
transform: scale(1.05);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes slide-in-horizontal {
50% {
transform: translateX(0);
}
to {
transform: translateX(100%);
}
}
@keyframes slide-in-horizontal-reverse {
50% {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
@keyframes slide-in-vertical {
50% {
transform: translateY(0);
}
to {
transform: translateY(-100%);
}
}
@keyframes slide-in-vertical-reverse {
50% {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
@keyframes slide-in-out {
50% {
transform: scaleX(1);
transform-origin: left;
}
50.1% {
transform-origin: right;
}
100% {
transform: scaleX(0);
transform-origin: right;
}
}
@keyframes fill-text-white {
to {
color: white;
}
}
@keyframes scale-in {
to {
transform: scale(1);
}
}
</style>
-82
View File
@@ -1,82 +0,0 @@
<template>
<div class="content" :style="styleObj">
<div v-for="(item, index) in 200" :key="index" class="snow"></div>
</div>
</template>
<script>
export default {
name: 'VabSnow',
props: {
styleObj: {
type: Object,
default: () => {
return {}
},
},
},
data() {
return {}
},
created() {},
mounted() {},
methods: {},
}
</script>
<style lang="scss" scoped>
.content {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
filter: drop-shadow(0 0 10px white);
}
@function random_range($min, $max) {
$rand: random();
$random_range: $min + floor($rand * (($max - $min) + 1));
@return $random_range;
}
.snow {
$total: 200;
position: absolute;
width: 10px;
height: 10px;
background: white;
border-radius: 50%;
@for $i from 1 through $total {
$random-x: random(1000000) * 0.0001vw;
$random-offset: random_range(-100000, 100000) * 0.0001vw;
$random-x-end: $random-x + $random-offset;
$random-x-end-yoyo: $random-x + ($random-offset / 2);
$random-yoyo-time: random_range(30000, 80000) / 100000;
$random-yoyo-y: $random-yoyo-time * 100vh;
$random-scale: random(10000) * 0.0001;
$fall-duration: random_range(10, 30) * 1s;
$fall-delay: random(30) * -1s;
&:nth-child(#{$i}) {
opacity: random(10000) * 0.0001;
transform: translate($random-x, -10px) scale($random-scale);
animation: fall-#{$i} $fall-duration $fall-delay linear infinite;
}
@keyframes fall-#{$i} {
#{percentage($random-yoyo-time)} {
transform: translate($random-x-end, $random-yoyo-y)
scale($random-scale);
}
to {
transform: translate($random-x-end-yoyo, 100vh) scale($random-scale);
}
}
}
}
</style>
-255
View File
@@ -1,255 +0,0 @@
<template>
<el-dialog
:before-close="handleClose"
:close-on-click-modal="false"
:title="title"
:visible.sync="dialogFormVisible"
width="909px"
>
<div class="upload">
<el-alert
:closable="false"
:title="`支持jpg、jpeg、png格式,单次可最多选择${limit}张图片,每张不可大于${size}M,如果大于${size}M会自动为您过滤`"
type="info"
></el-alert>
<br />
<el-upload
ref="upload"
:action="action"
:auto-upload="false"
:close-on-click-modal="false"
:data="data"
:file-list="fileList"
:headers="headers"
:limit="limit"
:multiple="true"
:name="name"
:on-change="handleChange"
:on-error="handleError"
:on-exceed="handleExceed"
:on-preview="handlePreview"
:on-progress="handleProgress"
:on-remove="handleRemove"
:on-success="handleSuccess"
accept="image/png, image/jpeg"
class="upload-content"
list-type="picture-card"
>
<i slot="trigger" class="el-icon-plus"></i>
<el-dialog
:visible.sync="dialogVisible"
append-to-body
title="查看大图"
>
<div>
<img :src="dialogImageUrl" alt="" width="100%" />
</div>
</el-dialog>
</el-upload>
</div>
<div
slot="footer"
class="dialog-footer"
style="position: relative; padding-right: 15px; text-align: right"
>
<div
v-if="show"
style="position: absolute; top: 10px; left: 15px; color: #999"
>
正在上传中... 当前上传成功数:{{ imgSuccessNum }} 当前上传失败数:{{
imgErrorNum
}}
</div>
<el-button type="primary" @click="handleClose">关闭</el-button>
<el-button
:loading="loading"
size="small"
style="margin-left: 10px"
type="success"
@click="submitUpload"
>
开始上传
</el-button>
</div>
</el-dialog>
</template>
<script>
import { baseURL, tokenName } from '@/config'
export default {
name: 'VabUpload',
props: {
url: {
type: String,
default: '/upload',
required: true,
},
name: {
type: String,
default: 'file',
required: true,
},
limit: {
type: Number,
default: 50,
required: true,
},
size: {
type: Number,
default: 1,
required: true,
},
},
data() {
return {
show: false,
loading: false,
dialogVisible: false,
dialogImageUrl: '',
action: 'https://vab-unicloud-3a9da9.service.tcloudbase.com/upload',
headers: {},
fileList: [],
picture: 'picture',
imgNum: 0,
imgSuccessNum: 0,
imgErrorNum: 0,
typeList: null,
title: '上传',
dialogFormVisible: false,
data: {},
}
},
computed: {
percentage() {
if (this.allImgNum == 0) return 0
return this.$baseLodash.round(this.imgNum / this.allImgNum, 2) * 100
},
},
methods: {
submitUpload() {
this.$refs.upload.submit()
},
handleProgress(event, file, fileList) {
this.loading = true
this.show = true
},
handleChange(file, fileList) {
if (file.size > 1048576 * this.size) {
fileList.map((item, index) => {
if (item === file) {
fileList.splice(index, 1)
}
})
this.fileList = fileList
} else {
this.allImgNum = fileList.length
}
},
handleSuccess(response, file, fileList) {
this.imgNum = this.imgNum + 1
this.imgSuccessNum = this.imgSuccessNum + 1
if (fileList.length === this.imgNum) {
setTimeout(() => {
this.$baseMessage(
`上传完成! 共上传${fileList.length}张图片`,
'success'
)
}, 1000)
}
setTimeout(() => {
this.loading = false
this.show = false
}, 1000)
},
handleError(err, file, fileList) {
this.imgNum = this.imgNum + 1
this.imgErrorNum = this.imgErrorNum + 1
this.$baseMessage(
`文件[${file.raw.name}]上传失败,文件大小为${this.$baseLodash.round(
file.raw.size / 1024,
0
)}KB`,
'error'
)
setTimeout(() => {
this.loading = false
this.show = false
}, 1000)
},
handleRemove(file, fileList) {
this.imgNum = this.imgNum - 1
this.allNum = this.allNum - 1
},
handlePreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
handleExceed(files, fileList) {
this.$baseMessage(
`当前限制选择 ${this.limit} 个文件,本次选择了
${files.length}
个文件`,
'error'
)
},
handleShow(data) {
this.title = '上传'
this.data = data
this.dialogFormVisible = true
},
handleClose() {
this.fileList = []
this.picture = 'picture'
this.allImgNum = 0
this.imgNum = 0
this.imgSuccessNum = 0
this.imgErrorNum = 0
/* if ("development" === process.env.NODE_ENV) {
this.api = process.env.VUE_APP_BASE_API;
} else {
this.api = `${window.location.protocol}//${window.location.host}`;
}
this.action = this.api + this.url; */
this.dialogFormVisible = false
},
},
}
</script>
<style lang="scss" scoped>
.upload {
height: 500px;
.upload-content {
.el-upload__tip {
display: block;
height: 30px;
line-height: 30px;
}
::v-deep {
.el-upload--picture-card {
width: 128px;
height: 128px;
margin: 3px 8px 8px 8px;
border: 2px dashed #c0ccda;
}
.el-upload-list--picture {
margin-bottom: 20px;
}
.el-upload-list--picture-card {
.el-upload-list__item {
width: 128px;
height: 128px;
margin: 3px 8px 8px 8px;
}
}
}
}
}
</style>
+1 -5
View File
@@ -1,7 +1,3 @@
/**
* @description 3个子配置,通用配置|主题配置|网络配置导出
*/
const setting = require('./setting.config')
const theme = require('./theme.config')
const network = require('./net.config')
module.exports = Object.assign({}, setting, theme, network)
module.exports = Object.assign({}, setting, theme)
-18
View File
@@ -1,18 +0,0 @@
/**
* @description 导出默认网路配置
**/
const network = {
//配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: 'application/json;charset=UTF-8',
//消息框消失时间
messageDuration: 3000,
//最长请求时间
requestTimeout: 5000,
//操作正常code,支持String、Array、int多种类型
successCode: [200, 0],
//登录失效code
invalidCode: 402,
//无权限code
noPermissionCode: 401,
}
module.exports = network
-78
View File
@@ -1,78 +0,0 @@
import router from '@/router'
import store from '@/store'
import VabProgress from 'nprogress'
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/pageTitle'
import {
authentication,
loginInterception,
progressBar,
recordRoute,
routesWhiteList,
} from '@/config'
VabProgress.configure({
easing: 'ease',
speed: 500,
trickleSpeed: 200,
showSpinner: false,
})
router.beforeResolve(async (to, from, next) => {
if (progressBar) VabProgress.start()
let hasToken = store.getters['user/accessToken']
if (!loginInterception) hasToken = true
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
if (progressBar) VabProgress.done()
} else {
const hasPermissions =
store.getters['user/permissions'] &&
store.getters['user/permissions'].length > 0
if (hasPermissions) {
next()
} else {
try {
let permissions
if (!loginInterception) {
//settings.js loginInterception为false时,创建虚拟权限
await store.dispatch('user/setPermissions', ['admin'])
permissions = ['admin']
} else {
permissions = await store.dispatch('user/getUserInfo')
}
let accessRoutes = []
if (authentication === 'intelligence') {
accessRoutes = await store.dispatch('routes/setRoutes', permissions)
} else if (authentication === 'all') {
accessRoutes = await store.dispatch('routes/setAllRoutes')
}
router.addRoute(accessRoutes)
next({ ...to, replace: true })
} catch {
await store.dispatch('user/resetAccessToken')
if (progressBar) VabProgress.done()
}
}
}
} else {
if (routesWhiteList.indexOf(to.path) !== -1) {
next()
} else {
if (recordRoute) {
next(`/login?redirect=${to.path}`)
} else {
next('/login')
}
if (progressBar) VabProgress.done()
}
}
document.title = getPageTitle(to.meta.title)
})
router.afterEach(() => {
if (progressBar) VabProgress.done()
})
+9 -58
View File
@@ -8,68 +8,19 @@ const setting = {
outputDir: 'dist',
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
assetsDir: 'static',
// 开发环境每次保存时是否输出为eslint编译警告
lintOnSave: true,
// 进行编译的依赖
transpileDependencies: [],
// 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址
baseURL:
process.env.NODE_ENV === 'development'
? 'vab-mock-server'
: 'vab-mock-server',
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
title: 'vue-admin-beautiful-pro',
//简写
abbreviation: 'vab',
//开发环境端口
devPort: '80',
//版本号
? '/'
: '/',
// 标题
title: 'FOTON',
// 开发环境端口号
devPort: '8888',
// 版本
version: process.env.VUE_APP_VERSION,
//这一项非常重要!请务必保留MIT协议下package.json及copyright作者信息 即可免费商用,不遵守此项约定你将无法使用该框架,如需自定义版权信息请联系QQ1204505056
copyright: 'vab',
//是否显示页面底部自定义版权信息
footerCopyright: true,
//是否显示顶部进度条
progressBar: true,
//缓存路由的最大数量
keepAliveMaxNum: 99,
// 路由模式,可选值为 history 或 hash
routerMode: 'hash',
//不经过token校验的路由
routesWhiteList: ['/login', '/register', '/404', '/401'],
//加载时显示文字
loadingText: '正在加载中...',
//token名称
tokenName: 'accessToken',
//token在localStorage、sessionStorage存储的key的名称
tokenTableName: 'vue-admin-beautiful-2021',
//token存储位置localStorage sessionStorage
storage: 'localStorage',
//token失效回退到登录页时是否记录本次的路由
recordRoute: true,
//是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon
logo: 'vuejs-fill',
//是否显示在页面高亮错误
errorLog: ['development', 'production'],
//是否开启登录拦截
loginInterception: true,
//是否开启登录RSA加密
loginRSA: true,
//intelligence和all两种方式,前者后端权限只控制permissions不控制view文件的import(前后端配合,减轻后端工作量),all方式完全交给后端前端只负责加载
authentication: 'intelligence',
//vertical布局时是否只保持一个子菜单的展开
uniqueOpened: true,
//vertical布局时默认展开的菜单path,使用逗号隔开建议只展开一个
defaultOopeneds: ['/vab'],
//需要加loading层的请求,防止重复提交
debounce: ['doEdit'],
//需要自动注入并加载的模块
providePlugin: { maptalks: 'maptalks', 'window.maptalks': 'maptalks' },
//npm run build时是否自动生成7z压缩包
build7z: false,
//代码生成机生成在view下的文件夹名称
templateFolder: 'project',
//是否显示终端donation打印
donation: true,
// 需要自动注入并加载的模块
providePlugin: { maptalks: 'maptalks', 'window.maptalks': 'maptalks' }
}
module.exports = setting
-6
View File
@@ -1,6 +0,0 @@
/**
* @description 3个子配置,通用配置|主题配置|网络配置
*/
//默认配置
const { setting, theme, network } = require('./')
module.exports = Object.assign({}, setting, theme, network)
-3
View File
@@ -1,3 +0,0 @@
<template>
<router-view />
</template>
-52
View File
@@ -1,52 +0,0 @@
<template>
<div class="vab-ad">
<el-carousel
v-if="adList"
height="30px"
direction="vertical"
:autoplay="true"
:interval="3000"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in adList" :key="index">
<el-tag type="warning">Ad</el-tag>
<a target="_blank" :href="item.url">{{ item.title }}</a>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
import { getList } from '@/api/ad'
export default {
name: 'VabAd',
data() {
return {
nodeEnv: process.env.NODE_ENV,
adList: [],
}
},
created() {
this.fetchData()
},
methods: {
async fetchData() {
const { data } = await getList()
this.adList = data
},
},
}
</script>
<style lang="scss" scoped>
.vab-ad {
height: 30px;
padding-right: $base-padding;
padding-left: $base-padding;
margin-bottom: -20px;
line-height: 30px;
cursor: pointer;
a {
color: #999;
}
}
</style>
@@ -1,98 +0,0 @@
<template>
<div v-if="routerView" class="app-main-container">
<vab-github-corner />
<transition mode="out-in" name="fade-transform">
<keep-alive :include="cachedRoutes" :max="keepAliveMaxNum">
<router-view :key="key" class="app-main-height" />
</keep-alive>
</transition>
<footer v-show="footerCopyright" class="footer-copyright">
Copyright
<vab-icon :icon="['fas', 'copyright']"></vab-icon>
vue-admin-beautiful-pro 开源免费版 {{ fullYear }}
</footer>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { copyright, footerCopyright, keepAliveMaxNum, title } from '@/config'
export default {
name: 'VabAppMain',
data() {
return {
show: false,
fullYear: new Date().getFullYear(),
copyright,
title,
keepAliveMaxNum,
routerView: true,
footerCopyright,
}
},
computed: {
...mapGetters({
visitedRoutes: 'tabsBar/visitedRoutes',
device: 'settings/device',
}),
cachedRoutes() {
const cachedRoutesArr = []
this.visitedRoutes.forEach((item) => {
if (!item.meta.noKeepAlive) {
cachedRoutesArr.push(item.name)
}
})
return cachedRoutesArr
},
key() {
return this.$route.path
},
},
watch: {
$route: {
handler(route) {
if ('mobile' === this.device) this.foldSideBar()
},
immediate: true,
},
},
created() {
//重载所有路由
this.$baseEventBus.$on('reload-router-view', () => {
this.routerView = false
this.$nextTick(() => {
this.routerView = true
})
})
},
mounted() {},
methods: {
...mapActions({
foldSideBar: 'settings/foldSideBar',
}),
},
}
</script>
<style lang="scss" scoped>
.app-main-container {
position: relative;
width: 100%;
overflow: hidden;
.vab-keel {
margin: $base-padding;
}
.app-main-height {
min-height: $base-app-main-height;
}
.footer-copyright {
min-height: 55px;
line-height: 55px;
color: rgba(0, 0, 0, 0.45);
text-align: center;
border-top: 1px dashed $base-border-color;
}
}
</style>
-105
View File
@@ -1,105 +0,0 @@
<template>
<el-dropdown @command="handleCommand">
<span class="avatar-dropdown">
<!--<el-avatar class="user-avatar" :src="avatar"></el-avatar>-->
<img class="user-avatar" :src="avatar" alt="" />
<div class="user-name">
{{ username }}
<i class="el-icon-arrow-down el-icon--right"></i>
</div>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="github">github地址</el-dropdown-item>
<el-dropdown-item command="gitee" divided>码云地址</el-dropdown-item>
<el-dropdown-item command="pro" divided>pro付费版地址</el-dropdown-item>
<el-dropdown-item command="plus" divided>plus付费版地址</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
import { mapGetters } from 'vuex'
import { recordRoute } from '@/config'
export default {
name: 'VabAvatar',
computed: {
...mapGetters({
avatar: 'user/avatar',
username: 'user/username',
}),
},
methods: {
handleCommand(command) {
switch (command) {
case 'logout':
this.logout()
break
case 'personalCenter':
this.personalCenter()
break
case 'github':
window.open('https://github.com/chuzhixin/vue-admin-beautiful')
break
case 'gitee':
window.open('https://gitee.com/chu1204505056/vue-admin-beautiful')
break
case 'pro':
window.open(
'https://chu1204505056.gitee.io/admin-pro/?hmsr=homeAd&hmpl=&hmcu=&hmkw=&hmci='
)
break
case 'plus':
window.open(
'https://chu1204505056.gitee.io/admin-plus/?hmsr=homeAd&hmpl=&hmcu=&hmkw=&hmci='
)
}
},
personalCenter() {
this.$router.push('/personalCenter/personalCenter')
},
logout() {
this.$baseConfirm(
'您确定要退出' + this.$baseTitle + '吗?',
null,
async () => {
await this.$store.dispatch('user/logout')
if (recordRoute) {
const fullPath = this.$route.fullPath
this.$router.push(`/login?redirect=${fullPath}`)
} else {
this.$router.push('/login')
}
}
)
},
},
}
</script>
<style lang="scss" scoped>
.avatar-dropdown {
display: flex;
align-content: center;
align-items: center;
justify-content: center;
justify-items: center;
height: 50px;
padding: 0;
.user-avatar {
width: 40px;
height: 40px;
cursor: pointer;
border-radius: 50%;
}
.user-name {
position: relative;
margin-left: 5px;
margin-left: 5px;
cursor: pointer;
}
}
</style>
@@ -1,63 +0,0 @@
<template>
<el-breadcrumb class="breadcrumb-container" separator=">">
<el-breadcrumb-item v-for="item in list" :key="item.path">
{{ item.meta.title }}
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
name: 'VabBreadcrumb',
data() {
return {
list: this.getBreadcrumb(),
}
},
watch: {
$route() {
this.list = this.getBreadcrumb()
},
},
methods: {
getBreadcrumb() {
return this.$route.matched.filter(
(item) => item.name && item.meta.title
)
},
},
}
</script>
<style lang="scss" scoped>
.breadcrumb-container {
height: $base-nav-bar-height;
font-size: $base-font-size-default;
line-height: $base-nav-bar-height;
::v-deep {
.el-breadcrumb__item {
.el-breadcrumb__inner {
a {
display: flex;
float: left;
font-weight: normal;
color: #515a6e;
i {
margin-right: 3px;
}
}
}
&:last-child {
.el-breadcrumb__inner {
a {
color: #999;
}
}
}
}
}
}
</style>
-92
View File
@@ -1,92 +0,0 @@
<template>
<div :class="'logo-container-' + layout">
<router-link to="/">
<!-- 这里是logo变更的位置 -->
<vab-remix-icon v-if="logo" class="logo" :icon-class="logo" />
<span
class="title"
:class="{ 'hidden-xs-only': layout === 'horizontal' }"
:title="title"
>
{{ title }}
</span>
</router-link>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'VabLogo',
data() {
return {
title: this.$baseTitle,
}
},
computed: {
...mapGetters({
logo: 'settings/logo',
layout: 'settings/layout',
}),
},
}
</script>
<style lang="scss" scoped>
@mixin container {
position: relative;
height: $base-top-bar-height;
overflow: hidden;
line-height: $base-top-bar-height;
background: $base-menu-background;
}
@mixin logo {
display: inline-block;
width: 28px;
height: 28px;
margin-right: 3px;
color: $base-title-color;
vertical-align: middle;
}
@mixin title {
display: inline-block;
overflow: hidden;
font-size: 18px;
line-height: 55px;
color: $base-title-color;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
.logo-container-horizontal {
@include container;
.logo {
@include logo;
}
.title {
@include title;
}
}
.logo-container-vertical {
@include container;
height: $base-logo-height;
line-height: $base-logo-height;
text-align: center;
.logo {
@include logo;
}
.title {
@include title;
max-width: calc(#{$base-left-menu-width} - 60px);
}
}
</style>
-136
View File
@@ -1,136 +0,0 @@
<template>
<div class="nav-bar-container">
<el-row :gutter="15">
<el-col :xs="4" :sm="12" :md="12" :lg="12" :xl="12">
<div class="left-panel">
<i
:class="collapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
:title="collapse ? '展开' : '收起'"
class="fold-unfold"
@click="handleCollapse"
></i>
<vab-breadcrumb class="hidden-xs-only" />
</div>
</el-col>
<el-col :xs="20" :sm="12" :md="12" :lg="12" :xl="12">
<div class="right-panel">
<vab-error-log />
<vab-full-screen-bar @refresh="refreshRoute" />
<vab-theme-bar class="hidden-xs-only" />
<vab-icon
title="重载所有路由"
:pulse="pulse"
:icon="['fas', 'redo']"
@click="refreshRoute"
/>
<vab-avatar />
<!-- <vab-icon
title="退出系统"
:icon="['fas', 'sign-out-alt']"
@click="logout"
/>-->
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'VabNavBar',
data() {
return {
pulse: false,
}
},
computed: {
...mapGetters({
collapse: 'settings/collapse',
visitedRoutes: 'tabsBar/visitedRoutes',
device: 'settings/device',
routes: 'routes/routes',
}),
},
methods: {
...mapActions({
changeCollapse: 'settings/changeCollapse',
}),
handleCollapse() {
this.changeCollapse()
},
async refreshRoute() {
this.$baseEventBus.$emit('reload-router-view')
this.pulse = true
setTimeout(() => {
this.pulse = false
}, 1000)
},
},
}
</script>
<style lang="scss" scoped>
.nav-bar-container {
position: relative;
height: $base-nav-bar-height;
padding-right: $base-padding;
padding-left: $base-padding;
overflow: hidden;
user-select: none;
background: $base-color-white;
box-shadow: $base-box-shadow;
.left-panel {
display: flex;
align-items: center;
justify-items: center;
height: $base-nav-bar-height;
.fold-unfold {
color: $base-color-gray;
cursor: pointer;
}
::v-deep {
.breadcrumb-container {
margin-left: 10px;
}
}
}
.right-panel {
display: flex;
align-content: center;
align-items: center;
justify-content: flex-end;
height: $base-nav-bar-height;
::v-deep {
svg {
width: 1em;
height: 1em;
margin-right: 15px;
font-size: $base-font-size-small;
color: $base-color-gray;
cursor: pointer;
fill: $base-color-gray;
}
button {
svg {
margin-right: 0;
color: $base-color-white;
cursor: pointer;
fill: $base-color-white;
}
}
.el-badge {
margin-right: 15px;
}
}
}
}
</style>
@@ -1,259 +0,0 @@
<template>
<span v-if="themeBar">
<vab-icon
title="主题配置"
:icon="['fas', 'palette']"
@click="handleOpenThemeBar"
/>
<div class="theme-bar-setting">
<div @click="handleOpenThemeBar">
<vab-icon :icon="['fas', 'palette']" />
<p>主题配置</p>
</div>
<div @click="handleGetCode">
<vab-icon :icon="['fas', 'laptop-code']"></vab-icon>
<p>拷贝源码</p>
</div>
</div>
<el-drawer
title="主题配置"
:visible.sync="drawerVisible"
direction="rtl"
append-to-body
size="470px"
>
<el-scrollbar style="height: 94vh; overflow: hidden">
<div class="el-drawer__body">
<el-form ref="form" :model="theme" label-position="top">
<el-form-item label="主题">
<el-radio-group v-model="theme.name">
<el-radio-button label="default">默认</el-radio-button>
<el-radio-button label="green">绿荫草场</el-radio-button>
<el-radio-button label="glory">荣耀典藏</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="布局">
<el-radio-group v-model="theme.layout">
<el-radio-button label="vertical">纵向布局</el-radio-button>
<el-radio-button label="horizontal">横向布局</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="头部">
<el-radio-group v-model="theme.header">
<el-radio-button label="fixed">固定头部</el-radio-button>
<el-radio-button label="noFixed">不固定头部</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="多标签">
<el-radio-group v-model="theme.tabsBar">
<el-radio-button label="true">开启</el-radio-button>
<el-radio-button label="false">不开启</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSaveTheme">
保存
</el-button>
</el-form-item>
</el-form>
</div>
</el-scrollbar>
</el-drawer>
</span>
</template>
<script>
import variables from '@/styles/variables.scss'
import { mapActions, mapGetters } from 'vuex'
import { layout as defaultLayout } from '@/config'
export default {
name: 'VabThemeBar',
data() {
return {
drawerVisible: false,
theme: {
name: 'default',
layout: '',
header: 'fixed',
tabsBar: '',
},
}
},
computed: {
...mapGetters({
layout: 'settings/layout',
header: 'settings/header',
tabsBar: 'settings/tabsBar',
themeBar: 'settings/themeBar',
}),
},
created() {
this.$baseEventBus.$on('theme', () => {
this.handleOpenThemeBar()
})
const theme = localStorage.getItem('vue-admin-beautiful-theme')
if (null !== theme) {
this.theme = JSON.parse(theme)
this.handleSetTheme()
} else {
this.theme.layout = this.layout
this.theme.header = this.header
this.theme.tabsBar = this.tabsBar
}
},
methods: {
...mapActions({
changeLayout: 'settings/changeLayout',
changeHeader: 'settings/changeHeader',
changeTabsBar: 'settings/changeTabsBar',
}),
handleIsMobile() {
return document.body.getBoundingClientRect().width - 1 < 992
},
handleOpenThemeBar() {
this.drawerVisible = true
},
handleSetTheme() {
let { name, layout, header, tabsBar } = this.theme
localStorage.setItem(
'vue-admin-beautiful-theme',
`{
"name":"${name}",
"layout":"${layout}",
"header":"${header}",
"tabsBar":"${tabsBar}"
}`
)
if (!this.handleIsMobile()) this.changeLayout(layout)
this.changeHeader(header)
this.changeTabsBar(tabsBar)
document.getElementsByTagName(
'body'
)[0].className = `vue-admin-beautiful-theme-${name}`
this.drawerVisible = false
},
handleSaveTheme() {
this.handleSetTheme()
},
handleSetDfaultTheme() {
let { name } = this.theme
document
.getElementsByTagName('body')[0]
.classList.remove(`vue-admin-beautiful-theme-${name}`)
localStorage.removeItem('vue-admin-beautiful-theme')
this.$refs['form'].resetFields()
Object.assign(this.$data, this.$options.data())
this.changeHeader(defaultLayout)
this.theme.name = 'default'
this.theme.layout = this.layout
this.theme.header = this.header
this.theme.tabsBar = this.tabsBar
this.drawerVisible = false
location.reload()
},
handleGetCode() {
const url =
'https://github.com/chuzhixin/vue-admin-beautiful/tree/master/src/views'
let path = this.$route.path + '/index.vue'
if (path === '/vab/menu1/menu1-1/menu1-1-1/index.vue') {
path = '/vab/nested/menu1/menu1-1/menu1-1-1/index.vue'
}
if (path === '/vab/icon/awesomeIcon/index.vue') {
path = '/vab/icon/index.vue'
}
if (path === '/vab/icon/remixIcon/index.vue') {
path = '/vab/icon/remixIcon.vue'
}
if (path === '/vab/icon/colorfulIcon/index.vue') {
path = '/vab/icon/colorfulIcon.vue'
}
if (path === '/vab/table/comprehensiveTable/index.vue') {
path = '/vab/table/index.vue'
}
if (path === '/vab/table/inlineEditTable/index.vue') {
path = '/vab/table/inlineEditTable.vue'
}
window.open(url + path)
},
},
}
</script>
<style lang="scss" scoped>
@mixin right-bar {
position: fixed;
right: 0;
z-index: $base-z-index;
width: 60px;
min-height: 60px;
text-align: center;
cursor: pointer;
background: $base-color-blue;
border-radius: $base-border-radius;
> div {
padding-top: 10px;
border-bottom: 0 !important;
&:hover {
opacity: 0.9;
}
& + div {
border-top: 1px solid $base-color-white;
}
p {
padding: 0;
margin: 0;
font-size: $base-font-size-small;
line-height: 30px;
color: $base-color-white;
}
}
}
.theme-bar-setting {
@include right-bar;
top: calc((100vh - 110px) / 2);
::v-deep {
svg:not(:root).svg-inline--fa {
display: block;
margin-right: auto;
margin-left: auto;
color: $base-color-white;
}
.svg-icon {
display: block;
margin-right: auto;
margin-left: auto;
font-size: 20px;
color: $base-color-white;
fill: $base-color-white;
}
}
}
.el-drawer__body {
padding: 20px;
}
</style>
<style lang="scss">
.el-drawer__wrapper {
outline: none !important;
* {
outline: none !important;
}
}
.vab-color-picker {
.el-color-dropdown__link-btn {
display: none;
}
}
</style>
-25
View File
@@ -1,25 +0,0 @@
/**
* @description 公共布局及样式自动引入
*/
import Vue from 'vue'
const requireComponents = require.context('./components', true, /\.vue$/)
requireComponents.keys().forEach((fileName) => {
const componentConfig = requireComponents(fileName)
const componentName = componentConfig.default.name
Vue.component(componentName, componentConfig.default || componentConfig)
})
const requireZxLayouts = require.context('zx-layouts', true, /\.vue$/)
requireZxLayouts.keys().forEach((fileName) => {
const componentConfig = requireZxLayouts(fileName)
const componentName = componentConfig.default.name
Vue.component(componentName, componentConfig.default || componentConfig)
})
const requireThemes = require.context('@/styles/themes', true, /\.scss$/)
requireThemes.keys().forEach((fileName) => {
require(`@/styles/themes/${fileName.slice(2)}`)
})
-304
View File
@@ -1,304 +0,0 @@
<template>
<div class="vue-admin-beautiful-wrapper" :class="classObj">
<div
v-if="'horizontal' === layout"
class="layout-container-horizontal"
:class="{
fixed: header === 'fixed',
'no-tabs-bar': tabsBar === 'false' || tabsBar === false,
}"
>
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<vab-top-bar />
<div
v-if="tabsBar === 'true' || tabsBar === true"
:class="{ 'tag-view-show': tabsBar }"
>
<div class="vab-main">
<vab-tabs-bar />
</div>
</div>
</div>
<div class="vab-main main-padding">
<vab-ad />
<vab-app-main />
</div>
</div>
<div
v-else
class="layout-container-vertical"
:class="{
fixed: header === 'fixed',
'no-tabs-bar': tabsBar === 'false' || tabsBar === false,
}"
>
<div
v-if="device === 'mobile' && collapse === false"
class="mask"
@click="handleFoldSideBar"
/>
<vab-side-bar />
<div class="vab-main" :class="collapse ? 'is-collapse-main' : ''">
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<vab-nav-bar />
<vab-tabs-bar v-if="tabsBar === 'true' || tabsBar === true" />
</div>
<vab-ad />
<vab-app-main />
</div>
</div>
<el-backtop />
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { tokenName } from '@/config'
export default {
name: 'Layout',
data() {
return { oldLayout: '' }
},
computed: {
...mapGetters({
layout: 'settings/layout',
tabsBar: 'settings/tabsBar',
collapse: 'settings/collapse',
header: 'settings/header',
device: 'settings/device',
}),
classObj() {
return {
mobile: this.device === 'mobile',
}
},
},
beforeMount() {
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
},
mounted() {
this.oldLayout = this.layout
const userAgent = navigator.userAgent
if (userAgent.includes('Juejin')) {
this.$baseAlert(
'vue-admin-beautiful不支持在掘金内置浏览器演示,请手动复制以下地址到浏览器中查看http://mpfhrd48.sanxing.uz7.cn/vue-admin-beautiful'
)
}
const isMobile = this.handleIsMobile()
if (isMobile) {
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch('settings/changeLayout', 'vertical')
} else {
this.$store.dispatch('settings/changeLayout', this.oldLayout)
}
this.$store.dispatch('settings/toggleDevice', 'mobile')
setTimeout(() => {
this.$store.dispatch('settings/foldSideBar')
}, 2000)
} else {
this.$store.dispatch('settings/openSideBar')
}
this.$nextTick(() => {
window.addEventListener(
'storage',
(e) => {
if (e.key === tokenName || e.key === null) window.location.reload()
if (e.key === tokenName && e.value === null)
window.location.reload()
},
false
)
})
},
methods: {
...mapActions({
handleFoldSideBar: 'settings/foldSideBar',
}),
handleIsMobile() {
return document.body.getBoundingClientRect().width - 1 < 992
},
handleResize() {
if (!document.hidden) {
const isMobile = this.handleIsMobile()
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch('settings/changeLayout', 'vertical')
} else {
this.$store.dispatch('settings/changeLayout', this.oldLayout)
}
this.$store.dispatch(
'settings/toggleDevice',
isMobile ? 'mobile' : 'desktop'
)
}
},
},
}
</script>
<style lang="scss" scoped>
@mixin fix-header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: $base-z-index - 2;
width: 100%;
overflow: hidden;
}
.vue-admin-beautiful-wrapper {
position: relative;
width: 100%;
height: 100%;
.layout-container-horizontal {
position: relative;
&.fixed {
padding-top: calc(#{$base-top-bar-height} + #{$base-tabs-bar-height});
}
&.fixed.no-tabs-bar {
padding-top: $base-top-bar-height;
}
::v-deep {
.vab-main {
width: 88%;
margin: auto;
}
.fixed-header {
@include fix-header;
}
.tag-view-show {
background: $base-color-white;
box-shadow: $base-box-shadow;
}
.nav-bar-container {
.fold-unfold {
display: none;
}
}
.main-padding {
.app-main-container {
margin-top: $base-padding;
margin-bottom: $base-padding;
background: $base-color-white;
}
}
}
}
.layout-container-vertical {
position: relative;
.mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: $base-z-index - 1;
width: 100%;
height: 100vh;
overflow: hidden;
background: #000;
opacity: 0.5;
}
&.fixed {
padding-top: calc(#{$base-nav-bar-height} + #{$base-tabs-bar-height});
}
&.fixed.no-tabs-bar {
padding-top: $base-nav-bar-height;
}
.vab-main {
position: relative;
min-height: 100%;
margin-left: $base-left-menu-width;
background: #f6f8f9;
transition: $base-transition;
::v-deep {
.fixed-header {
@include fix-header;
left: $base-left-menu-width;
width: $base-right-content-width;
box-shadow: $base-box-shadow;
transition: $base-transition;
}
.nav-bar-container {
position: relative;
box-sizing: border-box;
}
.tabs-bar-container {
box-sizing: border-box;
}
.app-main-container {
width: calc(100% - #{$base-padding} - #{$base-padding});
margin: $base-padding auto;
background: $base-color-white;
border-radius: $base-border-radius;
}
}
&.is-collapse-main {
margin-left: $base-left-menu-width-min;
::v-deep {
.fixed-header {
left: $base-left-menu-width-min;
width: calc(100% - 65px);
}
}
}
}
}
/* 手机端开始 */
&.mobile {
::v-deep {
.el-pager,
.el-pagination__jump {
display: none;
}
.layout-container-vertical {
.el-scrollbar.side-bar-container.is-collapse {
width: 0;
}
.vab-main {
width: 100%;
margin-left: 0;
}
}
.vab-main {
.fixed-header {
left: 0 !important;
width: 100% !important;
}
}
}
}
/* 手机端结束 */
}
</style>
+4 -12
View File
@@ -1,20 +1,12 @@
import Vue from 'vue'
import App from './App'
import store from './store'
import App from './App.vue'
import router from './router'
import './plugins'
import '@/layouts/export'
if (process.env.NODE_ENV === 'production') {
const { mockXHR } = require('@/utils/static')
mockXHR()
}
import store from './store'
Vue.config.productionTip = false
new Vue({
el: '#vue-admin-beautiful',
router,
store,
render: (h) => h(App),
})
render: h => h(App)
}).$mount('#foton')
-4
View File
@@ -1,4 +0,0 @@
import 'echarts'
import VabChart from 'vue-echarts'
export default VabChart
-9
View File
@@ -1,9 +0,0 @@
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/display.css'
import '@/styles/element-variables.scss'
Vue.use(ElementUI, {
size: 'small',
})
-17
View File
@@ -1,17 +0,0 @@
/* 公共引入,勿随意修改,修改时需经过确认 */
import Vue from 'vue'
import './element'
import './support'
import '@/styles/vab.scss'
import '@/remixIcon'
import '@/colorfulIcon'
import '@/config/permission'
import '@/utils/errorLog'
import './vabIcon'
import VabPermissions from 'zx-layouts/Permissions'
import Vab from '@/utils/vab'
import VabCount from 'zx-count'
Vue.use(Vab)
Vue.use(VabPermissions)
Vue.use(VabCount)
-20
View File
@@ -1,20 +0,0 @@
import { MessageBox } from 'element-ui'
import { donation } from '@/config'
import { dependencies, repository } from '../../package.json'
if (!!window.ActiveXObject || 'ActiveXObject' in window) {
MessageBox({
title: '温馨提示',
message:
'自2015年3月起,微软已宣布弃用IE,且不再对IE提供任何更新维护,请<a target="_blank" style="color:blue" href="https://www.microsoft.com/zh-cn/edge/">点击此处</a>访问微软官网更新浏览器,如果您使用的是双核浏览器,请您切换浏览器内核为极速模式',
type: 'warning',
showClose: false,
showConfirmButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
closeOnHashChange: false,
dangerouslyUseHTMLString: true,
})
}
if (!dependencies['vab-icon'] || !dependencies['zx-layouts'])
document.body.innerHTML = ''
-4
View File
@@ -1,4 +0,0 @@
import Vue from 'vue'
import VabIcon from 'vab-icon'
Vue.component('VabIcon', VabIcon)
-3
View File
@@ -1,3 +0,0 @@
import VabMagnifier from 'zx-magnifie'
export default VabMagnifier
-5
View File
@@ -1,5 +0,0 @@
import ZxMarkdownEditor from 'zx-markdown-editor'
import 'zx-markdown-editor/dist/zx-markdown-editor.css'
const VabMarkdownEditor = ZxMarkdownEditor
export default VabMarkdownEditor
-3
View File
@@ -1,3 +0,0 @@
import { VabPlayerMp4, VabPlayerHls, VabPlayerFlv } from 'zx-player'
export { VabPlayerMp4, VabPlayerHls, VabPlayerFlv }
-4
View File
@@ -1,4 +0,0 @@
import 'zx-quill/dist/zx-quill.css'
import VabQuill from 'zx-quill'
export default VabQuill
-4
View File
@@ -1,4 +0,0 @@
import VabVerify from 'zx-verify'
import 'zx-verify/dist/zx-verify.css'
export default VabVerify
-13
View File
@@ -1,13 +0,0 @@
const req = require.context('./svg', false, /\.svg$/),
requireAll = (requireContext) => {
/*let a = requireContext.keys().map(requireContext);
let arr = [];
for (let i = 0; i < a.length; i++) {
console.log();
let icon = a[i].default.id;
arr.push(icon);
}
console.log(JSON.stringify(arr));*/
return requireContext.keys().map(requireContext)
}
requireAll(req)
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M19.913 14.529a31.977 31.977 0 00-.675-1.886l-.91-2.246c0-.026.012-.468.012-.696C18.34 5.86 16.507 2 12 2S5.66 5.86 5.66 9.7c0 .229.011.671.012.697l-.91 2.246a32.777 32.777 0 00-.675 1.886c-.86 2.737-.581 3.87-.369 3.895.455.054 1.771-2.06 1.771-2.06 0 1.224.637 2.822 2.016 3.976-.515.157-1.147.399-1.554.695-.365.267-.319.54-.253.65.289.481 4.955.307 6.303.157 1.347.15 6.014.324 6.302-.158.066-.11.112-.382-.253-.649-.407-.296-1.039-.538-1.555-.696 1.379-1.153 2.016-2.751 2.016-3.976 0 0 1.316 2.115 1.771 2.06.212-.025.49-1.157-.37-3.894"/></svg>

Before

Width:  |  Height:  |  Size: 657 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M1 3h4l7 12 7-12h4L12 22 1 3zm8.667 0L12 7l2.333-4h4.035L12 14 5.632 3h4.035z"/></svg>

Before

Width:  |  Height:  |  Size: 193 B

+12 -367
View File
@@ -1,382 +1,27 @@
/**
* @description router全局配置
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/layouts'
import EmptyLayout from '@/layouts/EmptyLayout'
import { publicPath, routerMode } from '@/config'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true,
},
{
path: '/register',
component: () => import('@/views/register/index'),
hidden: true,
},
{
path: '/401',
name: '401',
component: () => import('@/views/401'),
hidden: true,
},
{
path: '/404',
name: '404',
component: () => import('@/views/404'),
hidden: true,
},
]
export const asyncRoutes = [
const routes = [
{
path: '/',
component: Layout,
redirect: 'index',
children: [
{
path: 'index',
name: 'Index',
component: () => import('@/views/index/index'),
meta: {
title: '首页',
icon: 'home',
affix: true,
},
},
],
},
{
path: '/vab',
component: Layout,
redirect: 'noRedirect',
name: 'Vab',
alwaysShow: true,
meta: { title: '组件', icon: 'box-open' },
children: [
{
path: 'permissions',
name: 'Permission',
component: () => import('@/views/vab/permissions/index'),
meta: {
title: '角色权限',
permissions: ['admin', 'editor'],
},
},
{
path: 'icon',
component: EmptyLayout,
redirect: 'noRedirect',
name: 'Icon',
meta: {
title: '图标',
permissions: ['admin'],
},
children: [
{
path: 'awesomeIcon',
name: 'AwesomeIcon',
component: () => import('@/views/vab/icon/index'),
meta: { title: '常规图标' },
},
{
path: 'remixIcon',
name: 'RemixIcon',
component: () => import('@/views/vab/icon/remixIcon'),
meta: { title: '小清新图标' },
},
{
path: 'colorfulIcon',
name: 'ColorfulIcon',
component: () => import('@/views/vab/icon/colorfulIcon'),
meta: { title: '多彩图标' },
},
],
},
{
path: 'table',
component: () => import('@/views/vab/table/index'),
name: 'Table',
meta: {
title: '表格',
permissions: ['admin'],
},
},
{
path: 'map',
component: () => import('@/views/vab/map/index'),
name: 'Map',
meta: {
title: '地图',
permissions: ['admin'],
},
},
{
path: 'webSocket',
name: 'WebSocket',
component: () => import('@/views/vab/webSocket/index'),
meta: { title: 'webSocket', permissions: ['admin'] },
},
{
path: 'form',
name: 'Form',
component: () => import('@/views/vab/form/index'),
meta: { title: '表单', permissions: ['admin'] },
},
{
path: 'element',
name: 'Element',
component: () => import('@/views/vab/element/index'),
meta: { title: '常用组件', permissions: ['admin'] },
},
{
path: 'tree',
name: 'Tree',
component: () => import('@/views/vab/tree/index'),
meta: { title: '树', permissions: ['admin'] },
},
{
path: 'verify',
name: 'Verify',
component: () => import('@/views/vab/verify/index'),
meta: { title: '验证码', permissions: ['admin'] },
},
{
path: 'menu1',
component: () => import('@/views/vab/nested/menu1/index'),
name: 'Menu1',
alwaysShow: true,
meta: {
title: '嵌套路由 1',
permissions: ['admin'],
},
children: [
{
path: 'menu1-1',
name: 'Menu1-1',
alwaysShow: true,
meta: { title: '嵌套路由 1-1' },
component: () => import('@/views/vab/nested/menu1/menu1-1/index'),
children: [
{
path: 'menu1-1-1',
name: 'Menu1-1-1',
meta: { title: '嵌套路由 1-1-1' },
component: () =>
import('@/views/vab/nested/menu1/menu1-1/menu1-1-1/index'),
},
],
},
],
},
{
path: 'magnifier',
name: 'Magnifier',
component: () => import('@/views/vab/magnifier/index'),
meta: { title: '放大镜', permissions: ['admin'] },
},
{
path: 'loading',
name: 'Loading',
component: () => import('@/views/vab/loading/index'),
meta: { title: 'loading', permissions: ['admin'] },
},
{
path: 'player',
name: 'Player',
component: () => import('@/views/vab/player/index'),
meta: { title: '视频播放器', permissions: ['admin'] },
},
{
path: 'markdownEditor',
name: 'MarkdownEditor',
component: () => import('@/views/vab/markdownEditor/index'),
meta: { title: 'markdown编辑器', permissions: ['admin'] },
},
{
path: 'editor',
name: 'Editor',
component: () => import('@/views/vab/editor/index'),
meta: {
title: '富文本编辑器',
permissions: ['admin'],
badge: 'New',
},
},
{
path: 'backToTop',
name: 'BackToTop',
component: () => import('@/views/vab/backToTop/index'),
meta: { title: '返回顶部', permissions: ['admin'] },
},
{
path: 'lodash',
name: 'Lodash',
component: () => import('@/views/vab/lodash/index'),
meta: { title: 'lodash', permissions: ['admin'] },
},
{
path: 'smallComponents',
name: 'SmallComponents',
component: () => import('@/views/vab/smallComponents/index'),
meta: { title: '小组件', permissions: ['admin'] },
},
{
path: 'upload',
name: 'Upload',
component: () => import('@/views/vab/upload/index'),
meta: { title: '上传', permissions: ['admin'] },
},
{
path: 'log',
name: 'Log',
component: () => import('@/views/vab/errorLog/index'),
meta: { title: '错误日志模拟', permissions: ['admin'] },
},
{
path:
'https://github.com/chuzhixin/vue-admin-beautiful?utm_source=gold_browser_extension',
name: 'ExternalLink',
meta: {
title: '外链',
target: '_blank',
permissions: ['admin', 'editor'],
badge: 'New',
},
},
{
path: 'more',
name: 'More',
component: () => import('@/views/vab/more/index'),
meta: { title: '关于', permissions: ['admin'] },
},
],
name: 'Home',
component: Home
},
{
path: '/personnelManagement',
component: Layout,
redirect: 'noRedirect',
name: 'PersonnelManagement',
meta: { title: '配置', icon: 'users-cog', permissions: ['admin'] },
children: [
{
path: 'userManagement',
name: 'UserManagement',
component: () =>
import('@/views/personnelManagement/userManagement/index'),
meta: { title: '用户管理' },
},
{
path: 'roleManagement',
name: 'RoleManagement',
component: () =>
import('@/views/personnelManagement/roleManagement/index'),
meta: { title: '角色管理' },
},
{
path: 'menuManagement',
name: 'MenuManagement',
component: () =>
import('@/views/personnelManagement/menuManagement/index'),
meta: { title: '菜单管理', badge: 'New' },
},
],
},
{
path: '/mall',
component: Layout,
redirect: 'noRedirect',
name: 'Mall',
meta: {
title: '商城',
icon: 'shopping-cart',
permissions: ['admin'],
},
children: [
{
path: 'pay',
name: 'Pay',
component: () => import('@/views/mall/pay/index'),
meta: {
title: '支付',
noKeepAlive: true,
},
children: null,
},
{
path: 'goodsList',
name: 'GoodsList',
component: () => import('@/views/mall/goodsList/index'),
meta: {
title: '商品列表',
},
},
],
},
{
path: '/error',
component: EmptyLayout,
redirect: 'noRedirect',
name: 'Error',
meta: { title: '错误页', icon: 'bug' },
children: [
{
path: '401',
name: 'Error401',
component: () => import('@/views/401'),
meta: { title: '401' },
},
{
path: '404',
name: 'Error404',
component: () => import('@/views/404'),
meta: { title: '404' },
},
],
},
{
path: '*',
redirect: '/404',
hidden: true,
},
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
base: publicPath,
mode: routerMode,
scrollBehavior: () => ({
y: 0,
}),
routes: constantRoutes,
routes
})
//注释的地方是允许路由重复点击,如果你觉得框架路由跳转规范太过严格可选择放开
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch((err) => err)
}
export function resetRouter() {
router.matcher = new VueRouter({
base: publicPath,
mode: routerMode,
scrollBehavior: () => ({
y: 0,
}),
routes: constantRoutes,
}).matcher
}
export default router
+1 -1
View File
@@ -16,6 +16,6 @@ Object.keys(modules).forEach((key) => {
modules[key]['namespaced'] = true
})
const store = new Vuex.Store({
modules,
modules
})
export default store
-28
View File
@@ -1,28 +0,0 @@
/**
* @description 异常捕获的状态拦截,请勿修改
*/
const state = () => ({
errorLogs: [],
})
const getters = {
errorLogs: (state) => state.errorLogs,
}
const mutations = {
addErrorLog(state, errorLog) {
state.errorLogs.push(errorLog)
},
clearErrorLog: (state) => {
state.errorLogs.splice(0)
},
}
const actions = {
addErrorLog({ commit }, errorLog) {
commit('addErrorLog', errorLog)
},
clearErrorLog({ commit }) {
commit('clearErrorLog')
},
}
export default { state, getters, mutations, actions }
-50
View File
@@ -1,50 +0,0 @@
/**
* @description 路由拦截状态管理,目前两种模式:all模式与intelligence模式,其中partialRoutes是菜单暂未使用
*/
import { asyncRoutes, constantRoutes } from '@/router'
import { getRouterList } from '@/api/router'
import { convertRouter, filterAsyncRoutes } from '@/utils/handleRoutes'
const state = () => ({
routes: [],
partialRoutes: [],
})
const getters = {
routes: (state) => state.routes,
partialRoutes: (state) => state.partialRoutes,
}
const mutations = {
setRoutes(state, routes) {
state.routes = constantRoutes.concat(routes)
},
setAllRoutes(state, routes) {
state.routes = constantRoutes.concat(routes)
},
setPartialRoutes(state, routes) {
state.partialRoutes = constantRoutes.concat(routes)
},
}
const actions = {
async setRoutes({ commit }, permissions) {
//开源版只过滤动态路由permissions,admin不再默认拥有全部权限
const finallyAsyncRoutes = await filterAsyncRoutes(
[...asyncRoutes],
permissions
)
commit('setRoutes', finallyAsyncRoutes)
return finallyAsyncRoutes
},
async setAllRoutes({ commit }) {
let { data } = await getRouterList()
data.push({ path: '*', redirect: '/404', hidden: true })
let accessRoutes = convertRouter(data)
commit('setAllRoutes', accessRoutes)
return accessRoutes
},
setPartialRoutes({ commit }, accessRoutes) {
commit('setPartialRoutes', accessRoutes)
return accessRoutes
},
}
export default { state, getters, mutations, actions }
-75
View File
@@ -1,75 +0,0 @@
/**
* @description 所有全局配置的状态管理,如无必要请勿修改
*/
import defaultSettings from '@/config'
const { tabsBar, logo, layout, header, themeBar } = defaultSettings
const theme =
JSON.parse(localStorage.getItem('vue-admin-beautiful-theme')) || ''
const state = () => ({
tabsBar: theme.tabsBar || tabsBar,
logo,
collapse: false,
layout: theme.layout || layout,
header: theme.header || header,
device: 'desktop',
themeBar,
})
const getters = {
collapse: (state) => state.collapse,
device: (state) => state.device,
header: (state) => state.header,
layout: (state) => state.layout,
logo: (state) => state.logo,
tabsBar: (state) => state.tabsBar,
themeBar: (state) => state.themeBar,
}
const mutations = {
changeLayout: (state, layout) => {
if (layout) state.layout = layout
},
changeHeader: (state, header) => {
if (header) state.header = header
},
changeTabsBar: (state, tabsBar) => {
if (tabsBar) state.tabsBar = tabsBar
},
changeCollapse: (state) => {
state.collapse = !state.collapse
},
foldSideBar: (state) => {
state.collapse = true
},
openSideBar: (state) => {
state.collapse = false
},
toggleDevice: (state, device) => {
state.device = device
},
}
const actions = {
changeLayout({ commit }, layout) {
commit('changeLayout', layout)
},
changeHeader({ commit }, header) {
commit('changeHeader', header)
},
changeTabsBar({ commit }, tabsBar) {
commit('changeTabsBar', tabsBar)
},
changeCollapse({ commit }) {
commit('changeCollapse')
},
foldSideBar({ commit }) {
commit('foldSideBar')
},
openSideBar({ commit }) {
commit('openSideBar')
},
toggleDevice({ commit }, device) {
commit('toggleDevice', device)
},
}
export default { state, getters, mutations, actions }
-23
View File
@@ -1,23 +0,0 @@
/**
* @description 代码生成机状态管理
*/
const state = () => ({
srcCode: '',
})
const getters = {
srcTableCode: (state) => state.srcCode,
}
const mutations = {
setTableCode(state, srcCode) {
state.srcCode = srcCode
},
}
const actions = {
setTableCode({ commit }, srcCode) {
commit('setTableCode', srcCode)
},
}
export default { state, getters, mutations, actions }
-112
View File
@@ -1,112 +0,0 @@
/**
* @description tabsBar多标签页逻辑,前期借鉴了很多开源项目发现都有个共同的特点很繁琐并不符合框架设计的初衷,后来在github用户hipi的启发下完成了重构,请勿修改
*/
const state = () => ({
visitedRoutes: [],
})
const getters = {
visitedRoutes: (state) => state.visitedRoutes,
}
const mutations = {
addVisitedRoute(state, route) {
let target = state.visitedRoutes.find((item) => item.path === route.path)
if (target) {
if (route.fullPath !== target.fullPath) Object.assign(target, route)
return
}
state.visitedRoutes.push(Object.assign({}, route))
},
delVisitedRoute(state, route) {
state.visitedRoutes.forEach((item, index) => {
if (item.path === route.path) state.visitedRoutes.splice(index, 1)
})
},
delOthersVisitedRoute(state, route) {
state.visitedRoutes = state.visitedRoutes.filter(
(item) => item.meta.affix || item.path === route.path
)
},
delLeftVisitedRoute(state, route) {
let index = state.visitedRoutes.length
state.visitedRoutes = state.visitedRoutes.filter((item) => {
if (item.name === route.name) index = state.visitedRoutes.indexOf(item)
return item.meta.affix || index <= state.visitedRoutes.indexOf(item)
})
},
delRightVisitedRoute(state, route) {
let index = state.visitedRoutes.length
state.visitedRoutes = state.visitedRoutes.filter((item) => {
if (item.name === route.name) index = state.visitedRoutes.indexOf(item)
return item.meta.affix || index >= state.visitedRoutes.indexOf(item)
})
},
delAllVisitedRoutes(state) {
state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix)
},
updateVisitedRoute(state, route) {
state.visitedRoutes.forEach((item) => {
if (item.path === route.path) item = Object.assign(item, route)
})
},
}
const actions = {
addVisitedRoute({ commit }, route) {
commit('addVisitedRoute', route)
},
async delRoute({ dispatch, state }, route) {
await dispatch('delVisitedRoute', route)
return {
visitedRoutes: [...state.visitedRoutes],
}
},
delVisitedRoute({ commit, state }, route) {
commit('delVisitedRoute', route)
return [...state.visitedRoutes]
},
async delOthersRoutes({ dispatch, state }, route) {
await dispatch('delOthersVisitedRoute', route)
return {
visitedRoutes: [...state.visitedRoutes],
}
},
async delLeftRoutes({ dispatch, state }, route) {
await dispatch('delLeftVisitedRoute', route)
return {
visitedRoutes: [...state.visitedRoutes],
}
},
async delRightRoutes({ dispatch, state }, route) {
await dispatch('delRightVisitedRoute', route)
return {
visitedRoutes: [...state.visitedRoutes],
}
},
delOthersVisitedRoute({ commit, state }, route) {
commit('delOthersVisitedRoute', route)
return [...state.visitedRoutes]
},
delLeftVisitedRoute({ commit, state }, route) {
commit('delLeftVisitedRoute', route)
return [...state.visitedRoutes]
},
delRightVisitedRoute({ commit, state }, route) {
commit('delRightVisitedRoute', route)
return [...state.visitedRoutes]
},
async delAllRoutes({ dispatch, state }, route) {
await dispatch('delAllVisitedRoutes', route)
return {
visitedRoutes: [...state.visitedRoutes],
}
},
delAllVisitedRoutes({ commit, state }) {
commit('delAllVisitedRoutes')
return [...state.visitedRoutes]
},
updateVisitedRoute({ commit }, route) {
commit('updateVisitedRoute', route)
},
}
export default { state, getters, mutations, actions }

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