update to 1.2.0

This commit is contained in:
zhigang.li 2017-11-15 22:59:51 +08:00
parent d7166d785e
commit dedefa5c24
242 changed files with 1224 additions and 3263 deletions

View File

@ -1,2 +1,3 @@
src/vendors.js
src/libs/table2excel.js
src/vendors
src/libs/table2excel.js
build

3
.gitignore vendored
View File

@ -5,4 +5,5 @@ node_modules
.history
.DS_Store
\.settings/
src/config/env.js
src/config/env.js
dist

View File

@ -65,7 +65,7 @@ npm run build
- 导出为Xls文件
- 表格转图片
- 错误页面
- 401页面
- 403页面
- 404页面
- 500页面
- 高级路由

1
build/env.js Normal file
View File

@ -0,0 +1 @@
export default "production";

View File

@ -1,6 +1,9 @@
const path = require('path');
const os = require('os');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HappyPack = require('happypack');
var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
function resolve (dir) {
return path.join(__dirname, dir);
@ -8,24 +11,24 @@ function resolve (dir) {
module.exports = {
entry: {
main: './src/main',
vendors: './src/vendors'
main: '@/main',
'vender-base': '@/vendors/vendors.base.js',
'vender-exten': '@/vendors/vendors.exten.js'
},
output: {
path: path.join(__dirname, '../dist')
path: path.resolve(__dirname, '../dist/dist')
},
module: {
rules: [{
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
less: ExtractTextPlugin.extract({
use: ['css-loader?minimize', 'autoprefixer-loader', 'less-loader'],
fallback: 'vue-style-loader'
}),
css: ExtractTextPlugin.extract({
use: ['css-loader', 'autoprefixer-loader'],
fallback: 'vue-style-loader'
@ -42,6 +45,12 @@ module.exports = {
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.js[x]?$/,
include: [resolve('src')],
exclude: /node_modules/,
loader: 'happypack/loader?id=happybabel'
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
@ -49,13 +58,12 @@ module.exports = {
fallback: 'style-loader'
})
},
{
test: /\.less/,
test: /\.less$/,
use: ExtractTextPlugin.extract({
use: ['autoprefixer-loader', 'less-loader'],
use: ['css-hot-loader', 'autoprefixer-loader', 'less-loader'],
fallback: 'style-loader'
})
}),
},
{
@ -68,11 +76,20 @@ module.exports = {
}
]
},
plugins: [
new HappyPack({
id: 'happybabel',
loaders: ['babel-loader'],
threadPool: happyThreadPool,
cache: true,
verbose: true
})
],
resolve: {
extensions: ['.js', '.vue'],
alias: {
'vue': 'vue/dist/vue.esm.js',
'@': resolve('../src')
'@': resolve('../src'),
}
}
};

View File

@ -1,11 +1,13 @@
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const merge = require('webpack-merge');
const webpackBaseConfig = require('./webpack.base.config.js');
const fs = require('fs');
const package = require('../package.json');
fs.open('./src/config/env.js', 'w', function(err, fd) {
fs.open('./env.js', 'w', function(err, fd) {
const buf = 'export default "development";';
fs.write(fd, buf, 0, buf.length, 0, function(err, written, buffer) {});
});
@ -23,13 +25,26 @@ module.exports = merge(webpackBaseConfig, {
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.js'
name: ['vender-exten', 'vender-base'],
minChunks: Infinity
}),
new HtmlWebpackPlugin({
title: 'iView admin v' + package.version,
filename: '../index.html',
template: './src/template/index.ejs',
inject: false
}),
new CopyWebpackPlugin([
{
from: 'src/views/main_components/theme-switch/theme'
},
{
from: 'src/views/my_components/text-editor/tinymce'
}
], {
ignore: [
'text-editor.vue'
]
})
]
});

View File

@ -1,29 +1,38 @@
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const merge = require('webpack-merge');
const webpackBaseConfig = require('./webpack.base.config.js');
const fs = require('fs');
const path = require('path');
const package = require('../package.json');
fs.open('./src/config/env.js', 'w', function(err, fd) {
fs.open('./build/env.js', 'w', function(err, fd) {
const buf = 'export default "production";';
fs.write(fd, buf, 0, buf.length, 0, function(err, written, buffer) {});
});
module.exports = merge(webpackBaseConfig, {
output: {
publicPath: 'https://iview.github.io/iview-admin/dist/',
publicPath: 'https://lison16.github.io/test-iva-gh-page/dist/',
filename: '[name].[hash].js',
chunkFilename: '[name].[hash].chunk.js'
},
plugins: [
new cleanWebpackPlugin(['dist/*'], {
root: path.resolve(__dirname, '../')
}),
new ExtractTextPlugin({
filename: '[name].[hash].css',
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.[hash].js'
// name: 'vendors',
// filename: 'vendors.[hash].js'
name: ['vender-exten', 'vender-base'],
minChunks: Infinity
}),
new webpack.DefinePlugin({
'process.env': {
@ -35,8 +44,35 @@ module.exports = merge(webpackBaseConfig, {
warnings: false
}
}),
new CopyWebpackPlugin([
{
from: 'src/styles/simplemde.min.css'
},
{
from: 'src/styles/cropper.min.css'
},
{
from: 'td_icon.ico'
},
{
from: 'src/styles/fonts',
to: 'fonts'
},
{
from: 'src/views/main_components/theme-switch/theme'
},
{
from: 'src/views/my_components/text-editor/tinymce'
}
], {
ignore: [
'text-editor.vue'
]
}),
new HtmlWebpackPlugin({
filename: '../index_prod.html',
title: 'iView admin v' + package.version,
favicon: './td_icon.ico',
filename: '../index.html',
template: './src/template/index.ejs',
inject: false
})

Binary file not shown.

2230
dist/fonts/ionicons.svg vendored

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Binary file not shown.

1
dist/g.css vendored

File diff suppressed because one or more lines are too long

1
dist/r.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/y.css vendored

File diff suppressed because one or more lines are too long

1
env.js Normal file
View File

@ -0,0 +1 @@
export default "development";

View File

@ -7,15 +7,13 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<link rel="stylesheet" href="/dist/main.css">
<link rel="stylesheet" name="theme" href="">
<link rel="icon" href="/td_icon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/dist/simplemde.min.css">
<link rel="stylesheet" href="/dist/cropper.min.css">
<link rel="icon" href="./td_icon.ico" type="image/x-icon" />
</head>
<body>
<div id="app"></div>
<div class="lock-screen-back" id="lock_screen_back"></div>
<script type="text/javascript" src="/dist/vendors.js"></script>
<script type="text/javascript" src="/dist/vender-base.js"></script>
<script type="text/javascript" src="/dist/vender-exten.js"></script>
<script type="text/javascript" src="/dist/main.js"></script>
</body>

188
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "iview-admin",
"version": "1.1.4",
"version": "1.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1749,6 +1749,15 @@
}
}
},
"clean-webpack-plugin": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-0.1.17.tgz",
"integrity": "sha512-Bts/V725v8Ijosp4K1cqppQXgXcrohxoMsg0CV2xL4y/vua1G5pAfHEW/eJIiKF+GNNG72mdjbipxMRFEms7yg==",
"dev": true,
"requires": {
"rimraf": "2.6.2"
}
},
"cli": {
"version": "0.6.6",
"resolved": "http://r.cnpmjs.org/cli/download/cli-0.6.6.tgz",
@ -1973,25 +1982,6 @@
}
}
},
"compression-webpack-plugin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-1.0.1.tgz",
"integrity": "sha512-ABF2AFb31gpIBeEy/w6Ct0u+K+jY8jFRfGwjUWGxVTidA9pf7iH/JzjcVBQ+KB1gNMycujMxA56/PznMPUV5jw==",
"requires": {
"async": "2.4.1",
"webpack-sources": "1.0.1"
},
"dependencies": {
"async": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
"integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
"requires": {
"lodash": "4.17.4"
}
}
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "http://r.cnpmjs.org/concat-map/download/concat-map-0.0.1.tgz",
@ -2095,6 +2085,45 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
"dev": true
},
"copy-webpack-plugin": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.2.0.tgz",
"integrity": "sha512-eZERim02YjJcepLjrToQMapOoRLfiXewJi9zJON6xXNNJSUhkGzL1L/yFjOufS0KxsnWUzc2szg9t8ZaZKJXAg==",
"dev": true,
"requires": {
"bluebird": "3.5.1",
"fs-extra": "4.0.2",
"glob": "7.1.2",
"is-glob": "4.0.0",
"loader-utils": "0.2.17",
"lodash": "4.17.4",
"minimatch": "3.0.4",
"node-dir": "0.1.17"
},
"dependencies": {
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
"dev": true
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-glob": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
"integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
"dev": true,
"requires": {
"is-extglob": "2.1.1"
}
}
}
},
"core-js": {
"version": "2.5.1",
"resolved": "http://r.cnpmjs.org/core-js/download/core-js-2.5.1.tgz",
@ -2226,6 +2255,29 @@
"resolved": "http://r.cnpmjs.org/css-font-face-src/download/css-font-face-src-0.2.2.tgz",
"integrity": "sha1-Cb2q73MblS3Hwpab/ehlWblP/64="
},
"css-hot-loader": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/css-hot-loader/-/css-hot-loader-1.3.3.tgz",
"integrity": "sha512-QmDp/kSKNEhGO7acUl52V9zhPkr86o1ODL1ZL5wsStABO+1Nz0PAfi096Bdw+ywAnzxSjmE4tXMfxiw0Tvergw==",
"dev": true,
"requires": {
"loader-utils": "1.1.0",
"normalize-url": "1.9.1"
},
"dependencies": {
"loader-utils": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
"dev": true,
"requires": {
"big.js": "3.2.0",
"emojis-list": "2.1.0",
"json5": "0.5.1"
}
}
}
},
"css-loader": {
"version": "0.23.1",
"resolved": "http://r.cnpmjs.org/css-loader/download/css-loader-0.23.1.tgz",
@ -3519,6 +3571,17 @@
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
"dev": true
},
"fs-extra": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz",
"integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"jsonfile": "4.0.0",
"universalify": "0.1.1"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "http://r.cnpmjs.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
@ -4546,6 +4609,37 @@
"integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
"dev": true
},
"happypack": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/happypack/-/happypack-4.0.0.tgz",
"integrity": "sha1-3hdw1HLasz4/MXgqPttOd8xlhjE=",
"dev": true,
"requires": {
"async": "1.5.0",
"json-stringify-safe": "5.0.1",
"loader-utils": "1.1.0",
"serialize-error": "2.1.0"
},
"dependencies": {
"async": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.0.tgz",
"integrity": "sha1-J5ZkJyNXOFlWVjP8YnRES+4vjOM=",
"dev": true
},
"loader-utils": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
"dev": true,
"requires": {
"big.js": "3.2.0",
"emojis-list": "2.1.0",
"json5": "0.5.1"
}
}
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "http://r.cnpmjs.org/har-schema/download/har-schema-2.0.0.tgz",
@ -5413,12 +5507,11 @@
"optional": true
},
"iview": {
"version": "2.5.0-beta.1",
"resolved": "https://registry.npmjs.org/iview/-/iview-2.5.0-beta.1.tgz",
"integrity": "sha512-HV+I4+5ncRlBs4r9zqZcRcMJ1Gy+P45IKf6H2uHrq9bVu0FTlUJ3X8B58USK36iUogH/bK4oTXVTOemST6SECg==",
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/iview/-/iview-2.7.2.tgz",
"integrity": "sha512-jftB5yOYWcgL1iTLUj1sjrA+T37JOWlbtO328FkgfciT9PL2LB6MOE+OSWbPDMh6UCPg7lRAa5SM1o7qLW5NnA==",
"requires": {
"async-validator": "1.8.1",
"compression-webpack-plugin": "1.0.1",
"core-js": "2.5.1",
"deepmerge": "1.5.2",
"element-resize-detector": "1.1.12",
@ -5537,8 +5630,7 @@
"version": "5.0.1",
"resolved": "http://r.cnpmjs.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true,
"optional": true
"dev": true
},
"json3": {
"version": "3.3.2",
@ -5552,6 +5644,15 @@
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11"
}
},
"jsonify": {
"version": "0.0.0",
"resolved": "http://r.cnpmjs.org/jsonify/download/jsonify-0.0.0.tgz",
@ -5708,7 +5809,8 @@
"lodash": {
"version": "4.17.4",
"resolved": "http://r.cnpmjs.org/lodash/download/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
"dev": true
},
"lodash._createcompounder": {
"version": "3.0.0",
@ -6085,6 +6187,15 @@
"lower-case": "1.1.4"
}
},
"node-dir": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
"integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=",
"dev": true,
"requires": {
"minimatch": "3.0.4"
}
},
"node-forge": {
"version": "0.6.33",
"resolved": "http://r.cnpmjs.org/node-forge/download/node-forge-0.6.33.tgz",
@ -7962,8 +8073,8 @@
},
"semver": {
"version": "5.4.1",
"resolved": "http://r.cnpmjs.org/semver/download/semver-5.4.1.tgz",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
},
"send": {
@ -8013,6 +8124,12 @@
"lower-case": "1.1.4"
}
},
"serialize-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
"integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=",
"dev": true
},
"serve-index": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
@ -8733,6 +8850,12 @@
"integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
"dev": true
},
"universalify": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
"dev": true
},
"unpipe": {
"version": "1.0.0",
"resolved": "http://r.cnpmjs.org/unpipe/download/unpipe-1.0.0.tgz",
@ -9526,6 +9649,7 @@
"version": "1.0.1",
"resolved": "http://r.cnpmjs.org/webpack-sources/download/webpack-sources-1.0.1.tgz",
"integrity": "sha1-xzVkNqTRMSO+LiQmoF0drZy+Zc8=",
"dev": true,
"requires": {
"source-list-map": "2.0.0",
"source-map": "0.5.7"
@ -9534,12 +9658,14 @@
"source-list-map": {
"version": "2.0.0",
"resolved": "http://r.cnpmjs.org/source-list-map/download/source-list-map-2.0.0.tgz",
"integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU="
"integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU=",
"dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "http://r.cnpmjs.org/source-map/download/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},

View File

@ -1,6 +1,6 @@
{
"name": "iview-admin",
"version": "1.1.4",
"version": "1.2.0",
"description": "a management bases on iview",
"main": "index.js",
"scripts": {
@ -24,7 +24,7 @@
"cropperjs": "^1.1.2",
"echarts": "^3.7.2",
"html2canvas": "^0.5.0-beta4",
"iview": "^2.5.0-beta.1",
"iview": "^2.7.2",
"iview-area": "^1.5.5",
"js-cookie": "^2.1.3",
"rasterizehtml": "^1.2.4",
@ -47,6 +47,9 @@
"babel-preset-es2015": "^6.9.0",
"babel-preset-stage-3": "^6.24.1",
"babel-runtime": "^6.11.6",
"clean-webpack-plugin": "^0.1.17",
"copy-webpack-plugin": "^4.2.0",
"css-hot-loader": "^1.3.3",
"css-loader": "^0.23.1",
"eslint": "^3.19.0",
"eslint-config-google": "^0.9.1",
@ -58,10 +61,12 @@
"eslint-plugin-standard": "^3.0.1",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.8.5",
"happypack": "^4.0.0",
"html-loader": "^0.3.0",
"html-webpack-plugin": "^2.28.0",
"less": "^2.7.1",
"less-loader": "^2.2.3",
"semver": "^5.4.1",
"style-loader": "^0.13.1",
"unsupported": "^1.1.0",
"url-loader": "^0.5.7",

View File

@ -8,7 +8,7 @@
export default {
data () {
return {
theme: this.$store.state.theme
theme: this.$store.state.app.themeColor
};
},
mounted () {

View File

@ -1,3 +0,0 @@
export default {
switchLangTitle: 'Switch Lang'
};

View File

@ -1,7 +0,0 @@
import enLang from './en';
import zhLang from './zh';
import zhTradLang from './zh_trad';
export const en = enLang;
export const zh = zhLang;
export const zhT = zhTradLang;

View File

@ -1,3 +0,0 @@
export default {
switchLangTitle: '切换语言'
};

View File

@ -1,3 +0,0 @@
export default {
switchLangTitle: '切換語言'
};

View File

@ -1,5 +1,7 @@
import axios from 'axios';
import env from '../config/env';
import env from '../../build/env';
import semver from 'semver';
import packjson from '../../package.json';
let util = {
@ -83,7 +85,7 @@ util.handleTitle = function (vm, item) {
util.setCurrentPath = function (vm, name) {
let title = '';
let isOtherRouter = false;
vm.$store.state.routers.forEach(item => {
vm.$store.state.app.routers.forEach(item => {
if (item.children.length === 1) {
if (item.children[0].name === name) {
title = util.handleTitle(vm, item);
@ -106,7 +108,7 @@ util.setCurrentPath = function (vm, name) {
if (name === 'home_index') {
currentPathArr = [
{
title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.routers, 'home_index')),
title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.app.routers, 'home_index')),
path: '',
name: 'home_index'
}
@ -114,7 +116,7 @@ util.setCurrentPath = function (vm, name) {
} else if ((name.indexOf('_index') >= 0 || isOtherRouter) && name !== 'home_index') {
currentPathArr = [
{
title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.routers, 'home_index')),
title: util.handleTitle(vm, util.getRouterObjByName(vm.$store.state.app.routers, 'home_index')),
path: '/home',
name: 'home_index'
},
@ -125,7 +127,7 @@ util.setCurrentPath = function (vm, name) {
}
];
} else {
let currentPathObj = vm.$store.state.routers.filter(item => {
let currentPathObj = vm.$store.state.app.routers.filter(item => {
if (item.children.length <= 1) {
return item.children[0].name === name;
} else {
@ -191,7 +193,7 @@ util.setCurrentPath = function (vm, name) {
};
util.openNewPage = function (vm, name, argu, query) {
let pageOpenedList = vm.$store.state.pageOpenedList;
let pageOpenedList = vm.$store.state.app.pageOpenedList;
let openedPageLen = pageOpenedList.length;
let i = 0;
let tagHasOpened = false;
@ -208,7 +210,7 @@ util.openNewPage = function (vm, name, argu, query) {
i++;
}
if (!tagHasOpened) {
let tag = vm.$store.state.tagsList.filter((item) => {
let tag = vm.$store.state.app.tagsList.filter((item) => {
if (item.children) {
return name === item.children[0].name;
} else {
@ -248,4 +250,26 @@ util.toDefaultPage = function (routers, name, route, next) {
}
};
util.fullscreenEvent = function (vm) {
vm.$store.commit('initCachepage');
// 权限菜单过滤相关
vm.$store.commit('updateMenulist');
// 全屏相关
};
util.checkUpdate = function (vm) {
axios.get('https://api.github.com/repos/iview/iview-admin/releases/latest').then(res => {
let version = res.data.name;
vm.$Notice.config({
duration: 0
});
if (semver.lt(packjson.version, version)) {
vm.$Notice.info({
title: 'iview-admin更新啦',
desc: '<p>iView-admin更新到了' + version + '了,去看看有哪些变化吧</p><a style="font-size:13px;" href="https://github.com/iview/iview-admin/releases" target="_blank">前往github查看</a>'
});
}
});
}
export default util;

21
src/locale/index.js Normal file
View File

@ -0,0 +1,21 @@
import Vue from 'vue';
import Locales from './locale';
import zhLocale from 'iview/src/locale/lang/zh-CN';
import enLocale from 'iview/src/locale/lang/en-US';
import zhTLocale from 'iview/src/locale/lang/zh-TW';
// 自动设置语言
const navLang = navigator.language;
const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false;
const lang = window.localStorage.lang || localLang || 'zh-CN';
Vue.config.lang = lang;
// 多语言配置
const locales = Locales;
const mergeZH = Object.assign(zhLocale, locales['zh-CN']);
const mergeEN = Object.assign(enLocale, locales['en-US']);
const mergeTW = Object.assign(zhTLocale, locales['zh-TW']);
Vue.locale('zh-CN', mergeZH);
Vue.locale('en-US', mergeEN);
Vue.locale('zh-TW', mergeTW);

View File

@ -1,318 +1,19 @@
import Vue from 'vue';
import iView from 'iview';
import VueRouter from 'vue-router';
import {routers, otherRouter, appRouter} from './router';
import Vuex from 'vuex';
import Util from './libs/util';
import {router} from './router/index';
import {appRouter} from './router/router';
import store from './store';
import App from './app.vue';
import Cookies from 'js-cookie';
import '@/locale';
import 'iview/dist/styles/iview.css';
import './styles/cropper.min.css';
import './styles/simplemde.min.css';
import VueI18n from 'vue-i18n';
import Locales from './locale';
import zhLocale from 'iview/src/locale/lang/zh-CN';
import enLocale from 'iview/src/locale/lang/en-US';
import zhTLocale from 'iview/src/locale/lang/zh-TW';
import util from '@/libs/util';
Vue.use(VueRouter);
Vue.use(Vuex);
Vue.use(VueI18n);
Vue.use(iView);
// 自动设置语言
const navLang = navigator.language;
const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false;
const lang = window.localStorage.lang || localLang || 'zh-CN';
Vue.config.lang = lang;
// 多语言配置
const locales = Locales;
const mergeZH = Object.assign(zhLocale, locales['zh-CN']);
const mergeEN = Object.assign(enLocale, locales['en-US']);
const mergeTW = Object.assign(zhTLocale, locales['zh-TW']);
Vue.locale('zh-CN', mergeZH);
Vue.locale('en-US', mergeEN);
Vue.locale('zh-TW', mergeTW);
// 路由配置
const RouterConfig = {
// mode: 'history',
routes: routers
};
const router = new VueRouter(RouterConfig);
router.beforeEach((to, from, next) => {
iView.LoadingBar.start();
Util.title(to.meta.title);
if (Cookies.get('locking') === '1' && to.name !== 'locking') { // 判断当前是否是锁定状态
next(false);
router.replace({
name: 'locking'
});
} else if (Cookies.get('locking') === '0' && to.name === 'locking') {
next(false);
} else {
if (!Cookies.get('user') && to.name !== 'login') { // 判断是否已经登录且前往的页面不是登录页
next({
name: 'login'
});
} else if (Cookies.get('user') && to.name === 'login') { // 判断是否已经登录且前往的是登录页
Util.title();
next({
name: 'home_index'
});
} else {
if (Util.getRouterObjByName([otherRouter, ...appRouter], to.name).access !== undefined) { // 判断用户是否有权限访问当前页
if (Util.getRouterObjByName([otherRouter, ...appRouter], to.name).access === parseInt(Cookies.get('access'))) {
Util.toDefaultPage([otherRouter, ...appRouter], to.name, router, next); // 如果在地址栏输入的是一级菜单则默认打开其第一个二级菜单的页面
} else {
router.replace({
name: 'error_401'
});
next();
}
} else {
Util.toDefaultPage([otherRouter, ...appRouter], to.name, router, next);
}
}
}
iView.LoadingBar.finish();
});
router.afterEach(() => {
iView.LoadingBar.finish();
window.scrollTo(0, 0);
});
// 状态管理
const store = new Vuex.Store({
state: {
routers: [
otherRouter,
...appRouter
],
menuList: [],
tagsList: [...otherRouter.children],
pageOpenedList: [{
title: '首页',
path: '',
name: 'home_index'
}],
currentPageName: '',
currentPath: [
{
title: '首页',
path: '',
name: 'home_index'
}
], // 面包屑数组
openedSubmenuArr: [], // 要展开的菜单数组
menuTheme: '', // 主题
theme: '',
cachePage: [],
lang: '',
isFullScreen: false,
dontCache: ['text-editor'] // 在这里定义你不想要缓存的页面的name属性值(参见路由配置router.js)
},
getters: {
},
mutations: {
setTagsList (state, list) {
state.tagsList.push(...list);
},
closePage (state, name) {
state.cachePage.forEach((item, index) => {
if (item === name) {
state.cachePage.splice(index, 1);
}
});
},
increateTag (state, tagObj) {
if (!Util.oneOf(tagObj.name, state.dontCache)) {
state.cachePage.push(tagObj.name);
localStorage.cachePage = JSON.stringify(state.cachePage);
}
state.pageOpenedList.push(tagObj);
},
initCachepage (state) {
if (localStorage.cachePage) {
state.cachePage = JSON.parse(localStorage.cachePage);
}
},
removeTag (state, name) {
state.pageOpenedList.map((item, index) => {
if (item.name === name) {
state.pageOpenedList.splice(index, 1);
}
});
},
pageOpenedList (state, get) {
let openedPage = state.pageOpenedList[get.index];
if (get.argu) {
openedPage.argu = get.argu;
}
if (get.query) {
openedPage.query = get.query;
}
state.pageOpenedList.splice(get.index, 1, openedPage);
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
clearAllTags (state) {
state.pageOpenedList.splice(1);
router.push({
name: 'home_index'
});
state.cachePage.length = 0;
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
clearOtherTags (state, vm) {
let currentName = vm.$route.name;
let currentIndex = 0;
state.pageOpenedList.forEach((item, index) => {
if (item.name === currentName) {
currentIndex = index;
}
});
if (currentIndex === 0) {
state.pageOpenedList.splice(1);
} else {
state.pageOpenedList.splice(currentIndex + 1);
state.pageOpenedList.splice(1, currentIndex - 1);
}
let newCachepage = state.cachePage.filter(item => {
return item === currentName;
});
state.cachePage = newCachepage;
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
setOpenedList (state) {
state.pageOpenedList = localStorage.pageOpenedList ? JSON.parse(localStorage.pageOpenedList) : [otherRouter.children[0]];
},
setCurrentPath (state, pathArr) {
state.currentPath = pathArr;
},
setCurrentPageName (state, name) {
state.currentPageName = name;
},
addOpenSubmenu (state, name) {
let hasThisName = false;
let isEmpty = false;
if (name.length === 0) {
isEmpty = true;
}
if (state.openedSubmenuArr.indexOf(name) > -1) {
hasThisName = true;
}
if (!hasThisName && !isEmpty) {
state.openedSubmenuArr.push(name);
}
},
clearOpenedSubmenu (state) {
state.openedSubmenuArr.length = 0;
},
changeMenuTheme (state, theme) {
state.menuTheme = theme;
},
changeMainTheme (state, mainTheme) {
state.theme = mainTheme;
},
lock (state) {
Cookies.set('locking', '1');
},
unlock (state) {
Cookies.set('locking', '0');
},
setMenuList (state, menulist) {
state.menuList = menulist;
},
updateMenulist (state) {
let accessCode = parseInt(Cookies.get('access'));
let menuList = [];
appRouter.forEach((item, index) => {
if (item.access !== undefined) {
if (Util.showThisRoute(item.access, accessCode)) {
if (item.children.length === 1) {
menuList.push(item);
} else {
let len = menuList.push(item);
let childrenArr = [];
childrenArr = item.children.filter(child => {
if (child.access !== undefined) {
if (child.access === accessCode) {
return child;
}
} else {
return child;
}
});
menuList[len - 1].children = childrenArr;
}
}
} else {
if (item.children.length === 1) {
menuList.push(item);
} else {
let len = menuList.push(item);
let childrenArr = [];
childrenArr = item.children.filter(child => {
if (child.access !== undefined) {
if (Util.showThisRoute(child.access, accessCode)) {
return child;
}
} else {
return child;
}
});
let handledItem = JSON.parse(JSON.stringify(menuList[len - 1]));
handledItem.children = childrenArr;
menuList.splice(len - 1, 1, handledItem);
}
}
});
state.menuList = menuList;
},
setAvator (state, path) {
localStorage.avatorImgPath = path;
},
switchLang (state, lang) {
state.lang = lang;
Vue.config.lang = lang;
},
handleFullScreen (state) {
let main = document.body;
if (state.isFullScreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (main.requestFullscreen) {
main.requestFullscreen();
} else if (main.mozRequestFullScreen) {
main.mozRequestFullScreen();
} else if (main.webkitRequestFullScreen) {
main.webkitRequestFullScreen();
} else if (main.msRequestFullscreen) {
main.msRequestFullscreen();
}
}
},
changeFullScreenState (state) {
state.isFullScreen = !state.isFullScreen;
}
},
actions: {
}
});
new Vue({
el: '#app',
router: router,
@ -326,19 +27,8 @@ new Vue({
this.$store.commit('initCachepage');
// 权限菜单过滤相关
this.$store.commit('updateMenulist');
// 全屏相关
document.addEventListener('fullscreenchange', () => {
this.$store.commit('changeFullScreenState');
});
document.addEventListener('mozfullscreenchange', () => {
this.$store.commit('changeFullScreenState');
});
document.addEventListener('webkitfullscreenchange', () => {
this.$store.commit('changeFullScreenState');
});
document.addEventListener('msfullscreenchange', () => {
this.$store.commit('changeFullScreenState');
});
// iview-admin检查更新
util.checkUpdate(this);
},
created () {
let tagsList = [];

59
src/router/index.js Normal file
View File

@ -0,0 +1,59 @@
import Vue from 'vue';
import iView from 'iview';
import Util from '../libs/util';
import VueRouter from 'vue-router';
import Cookies from 'js-cookie';
import {routers, otherRouter, appRouter} from './router';
Vue.use(VueRouter);
// 路由配置
const RouterConfig = {
// mode: 'history',
routes: routers
};
export const router = new VueRouter(RouterConfig);
router.beforeEach((to, from, next) => {
iView.LoadingBar.start();
Util.title(to.meta.title);
if (Cookies.get('locking') === '1' && to.name !== 'locking') { // 判断当前是否是锁定状态
next(false);
router.replace({
name: 'locking'
});
} else if (Cookies.get('locking') === '0' && to.name === 'locking') {
next(false);
} else {
if (!Cookies.get('user') && to.name !== 'login') { // 判断是否已经登录且前往的页面不是登录页
next({
name: 'login'
});
} else if (Cookies.get('user') && to.name === 'login') { // 判断是否已经登录且前往的是登录页
Util.title();
next({
name: 'home_index'
});
} else {
if (Util.getRouterObjByName([otherRouter, ...appRouter], to.name).access !== undefined) { // 判断用户是否有权限访问当前页
if (Util.getRouterObjByName([otherRouter, ...appRouter], to.name).access === parseInt(Cookies.get('access'))) {
Util.toDefaultPage([otherRouter, ...appRouter], to.name, router, next); // 如果在地址栏输入的是一级菜单则默认打开其第一个二级菜单的页面
} else {
router.replace({
name: 'error_403'
});
next();
}
} else {
Util.toDefaultPage([otherRouter, ...appRouter], to.name, router, next);
}
}
}
iView.LoadingBar.finish();
});
router.afterEach(() => {
iView.LoadingBar.finish();
window.scrollTo(0, 0);
});

View File

@ -1,4 +1,4 @@
import Main from './views/Main.vue';
import Main from '@/views/Main.vue';
// 不作为Main组件的子页面展示的页面单独写如下
export const loginRouter = {
@ -7,7 +7,7 @@ export const loginRouter = {
meta: {
title: 'Login - 登录'
},
component: resolve => { require(['./views/login.vue'], resolve); }
component: resolve => { require(['@/views/login.vue'], resolve); }
};
export const page404 = {
@ -16,16 +16,16 @@ export const page404 = {
meta: {
title: '404-页面不存在'
},
component: resolve => { require(['./views/error_page/404.vue'], resolve); }
component: resolve => { require(['@/views/error_page/404.vue'], resolve); }
};
export const page401 = {
path: '/401',
export const page403 = {
path: '/403',
meta: {
title: '401-权限不足'
title: '403-权限不足'
},
name: 'error_401',
component: resolve => { require(['./views/error_page/401.vue'], resolve); }
name: 'error_403',
component: resolve => { require(['@//views/error_page/403.vue'], resolve); }
};
export const page500 = {
@ -34,19 +34,19 @@ export const page500 = {
title: '500-服务端错误'
},
name: 'error_500',
component: resolve => { require(['./views/error_page/500.vue'], resolve); }
component: resolve => { require(['@/views/error_page/500.vue'], resolve); }
};
export const preview = {
path: '/preview',
name: 'preview',
component: resolve => { require(['./views/form/article-publish/preview.vue'], resolve); }
component: resolve => { require(['@/views/form/article-publish/preview.vue'], resolve); }
};
export const locking = {
path: '/locking',
name: 'locking',
component: resolve => { require(['./views/main_components/locking-page.vue'], resolve); }
component: resolve => { require(['@/views/main_components/lockscreen/components/locking-page.vue'], resolve); }
};
// 作为Main组件的子页面展示但是不在左侧菜单显示的路由写在otherRouter里
@ -55,11 +55,11 @@ export const otherRouter = {
name: 'otherRouter',
component: Main,
children: [
{ path: 'home', title: {i18n: 'home'}, name: 'home_index', component: resolve => { require(['./views/home/home.vue'], resolve); } },
{ path: 'ownspace', title: '个人中心', name: 'ownspace_index', component: resolve => { require(['./views/own-space/own-space.vue'], resolve); } },
{ path: 'order/:order_id', title: '订单详情', name: 'order_info', component: resolve => { require(['./views/advanced-router/component/order-info.vue'], resolve); } }, // 用于展示动态路由
{ path: 'shopping', title: '购物详情', name: 'shopping', component: resolve => { require(['./views/advanced-router/component/shopping-info.vue'], resolve); } }, // 用于展示带参路由
{ path: 'message', title: '消息中心', name: 'message_index', component: resolve => { require(['./views/message/message.vue'], resolve); } }
{ path: 'home', title: {i18n: 'home'}, name: 'home_index', component: resolve => { require(['@/views/home/home.vue'], resolve); } },
{ path: 'ownspace', title: '个人中心', name: 'ownspace_index', component: resolve => { require(['@/views/own-space/own-space.vue'], resolve); } },
{ path: 'order/:order_id', title: '订单详情', name: 'order_info', component: resolve => { require(['@/views/advanced-router/component/order-info.vue'], resolve); } }, // 用于展示动态路由
{ path: 'shopping', title: '购物详情', name: 'shopping', component: resolve => { require(['@/views/advanced-router/component/shopping-info.vue'], resolve); } }, // 用于展示带参路由
{ path: 'message', title: '消息中心', name: 'message_index', component: resolve => { require(['@/views/message/message.vue'], resolve); } }
]
};
@ -72,7 +72,7 @@ export const appRouter = [
title: '权限管理',
component: Main,
children: [
{ path: 'index', title: '权限管理', name: 'access_index', component: resolve => { require(['./views/access/access.vue'], resolve); } }
{ path: 'index', title: '权限管理', name: 'access_index', component: resolve => { require(['@/views/access/access.vue'], resolve); } }
]
},
{
@ -93,7 +93,7 @@ export const appRouter = [
name: 'international',
component: Main,
children: [
{ path: 'index', title: {i18n: 'international'}, name: 'international_index', component: resolve => { require(['./views/international/international.vue'], resolve); } }
{ path: 'index', title: {i18n: 'international'}, name: 'international_index', component: resolve => { require(['@/views/international/international.vue'], resolve); } }
]
},
{
@ -108,49 +108,49 @@ export const appRouter = [
icon: 'compose',
name: 'text-editor',
title: '富文本编辑器',
component: resolve => { require(['./views/my_components/text-editor/text-editor.vue'], resolve); }
component: resolve => { require(['@/views/my_components/text-editor/text-editor.vue'], resolve); }
},
{
path: 'md-editor',
icon: 'pound',
name: 'md-editor',
title: 'Markdown编辑器',
component: resolve => { require(['./views/my_components/markdown-editor/markdown-editor.vue'], resolve); }
component: resolve => { require(['@/views/my_components/markdown-editor/markdown-editor.vue'], resolve); }
},
{
path: 'image-editor',
icon: 'crop',
name: 'image-editor',
title: '图片预览编辑',
component: resolve => { require(['./views/my_components/image-editor/image-editor.vue'], resolve); }
component: resolve => { require(['@/views/my_components/image-editor/image-editor.vue'], resolve); }
},
{
path: 'draggable-list',
icon: 'arrow-move',
name: 'draggable-list',
title: '可拖拽列表',
component: resolve => { require(['./views/my_components/draggable-list/draggable-list.vue'], resolve); }
component: resolve => { require(['@/views/my_components/draggable-list/draggable-list.vue'], resolve); }
},
{
path: 'area-linkage',
icon: 'ios-more',
name: 'area-linkage',
title: '城市级联',
component: resolve => { require(['./views/my_components/area-linkage/area-linkage.vue'], resolve); }
component: resolve => { require(['@/views/my_components/area-linkage/area-linkage.vue'], resolve); }
},
{
path: 'file-upload',
icon: 'android-upload',
name: 'file-upload',
title: '文件上传',
component: resolve => { require(['./views/my_components/file-upload/file-upload.vue'], resolve); }
component: resolve => { require(['@/views/my_components/file-upload/file-upload.vue'], resolve); }
},
{
path: 'count-to',
icon: 'arrow-graph-up-right',
name: 'count-to',
title: '数字渐变',
component: resolve => { require(['./views/my_components/count-to/count-to.vue'], resolve); }
component: resolve => { require(['@/views/my_components/count-to/count-to.vue'], resolve); }
}
]
},
@ -161,8 +161,8 @@ export const appRouter = [
title: '表单编辑',
component: Main,
children: [
{ path: 'artical-publish', title: '文章发布', name: 'artical-publish', icon: 'compose', component: resolve => { require(['./views/form/article-publish/article-publish.vue'], resolve); } },
{ path: 'workflow', title: '工作流', name: 'workflow', icon: 'arrow-swap', component: resolve => { require(['./views/form/work-flow/work-flow.vue'], resolve); } }
{ path: 'artical-publish', title: '文章发布', name: 'artical-publish', icon: 'compose', component: resolve => { require(['@/views/form/article-publish/article-publish.vue'], resolve); } },
{ path: 'workflow', title: '工作流', name: 'workflow', icon: 'arrow-swap', component: resolve => { require(['@/views/form/work-flow/work-flow.vue'], resolve); } }
]
},
@ -173,8 +173,8 @@ export const appRouter = [
// title: '图表',
// component: Main,
// children: [
// { path: 'pie', title: '饼状图', name: 'pie', icon: 'ios-pie', component: resolve => { require('./views/access/access.vue') },
// { path: 'histogram', title: '柱状图', name: 'histogram', icon: 'stats-bars', component: resolve => { require('./views/access/access.vue') }
// { path: 'pie', title: '饼状图', name: 'pie', icon: 'ios-pie', component: resolve => { require('@/views/access/access.vue') },
// { path: 'histogram', title: '柱状图', name: 'histogram', icon: 'stats-bars', component: resolve => { require('@/views/access/access.vue') }
// ]
// },
@ -185,11 +185,11 @@ export const appRouter = [
title: '表格',
component: Main,
children: [
{ path: 'dragableTable', title: '可拖拽排序', name: 'dragable-table', icon: 'arrow-move', component: resolve => { require(['./views/tables/dragable-table.vue'], resolve); } },
{ path: 'editableTable', title: '可编辑表格', name: 'editable-table', icon: 'edit', component: resolve => { require(['./views/tables/editable-table.vue'], resolve); } },
{ path: 'searchableTable', title: '可搜索表格', name: 'searchable-table', icon: 'search', component: resolve => { require(['./views/tables/searchable-table.vue'], resolve); } },
{ path: 'exportableTable', title: '表格导出数据', name: 'exportable-table', icon: 'code-download', component: resolve => { require(['./views/tables/exportable-table.vue'], resolve); } },
{ path: 'table2image', title: '表格转图片', name: 'table-to-image', icon: 'images', component: resolve => { require(['./views/tables/table-to-image.vue'], resolve); } }
{ path: 'dragableTable', title: '可拖拽排序', name: 'dragable-table', icon: 'arrow-move', component: resolve => { require(['@/views/tables/dragable-table.vue'], resolve); } },
{ path: 'editableTable', title: '可编辑表格', name: 'editable-table', icon: 'edit', component: resolve => { require(['@/views/tables/editable-table.vue'], resolve); } },
{ path: 'searchableTable', title: '可搜索表格', name: 'searchable-table', icon: 'search', component: resolve => { require(['@/views/tables/searchable-table.vue'], resolve); } },
{ path: 'exportableTable', title: '表格导出数据', name: 'exportable-table', icon: 'code-download', component: resolve => { require(['@/views/tables/exportable-table.vue'], resolve); } },
{ path: 'table2image', title: '表格转图片', name: 'table-to-image', icon: 'images', component: resolve => { require(['@/views/tables/table-to-image.vue'], resolve); } }
]
},
{
@ -199,8 +199,8 @@ export const appRouter = [
title: '高级路由',
component: Main,
children: [
{ path: 'mutative-router', title: '动态路由', name: 'mutative-router', icon: 'link', component: resolve => { require(['./views/advanced-router/mutative-router.vue'], resolve); } },
{ path: 'argument-page', title: '带参页面', name: 'argument-page', icon: 'android-send', component: resolve => { require(['./views/advanced-router/argument-page.vue'], resolve); } }
{ path: 'mutative-router', title: '动态路由', name: 'mutative-router', icon: 'link', component: resolve => { require(['@/views/advanced-router/mutative-router.vue'], resolve); } },
{ path: 'argument-page', title: '带参页面', name: 'argument-page', icon: 'android-send', component: resolve => { require(['@/views/advanced-router/argument-page.vue'], resolve); } }
]
},
{
@ -210,7 +210,7 @@ export const appRouter = [
name: 'errorpage',
component: Main,
children: [
{ path: 'index', title: '错误页面', name: 'errorpage_index', component: resolve => { require(['./views/error_page/error-page.vue'], resolve); } }
{ path: 'index', title: '错误页面', name: 'errorpage_index', component: resolve => { require(['@/views/error_page/error-page.vue'], resolve); } }
]
}
];
@ -223,6 +223,6 @@ export const routers = [
locking,
...appRouter,
page500,
page401,
page403,
page404
];

32
src/store/index.js Normal file
View File

@ -0,0 +1,32 @@
import Vue from 'vue';
import Vuex from 'vuex';
import Util from '@/libs/util';
import app from './modules/app';
import user from './modules/user';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
dontCache: ['text-editor'] // 在这里定义你不想要缓存的页面的name属性值(参见路由配置router.js)
},
mutations: {
increateTag (state, tagObj) {
if (!Util.oneOf(tagObj.name, state.dontCache)) {
state.app.cachePage.push(tagObj.name);
localStorage.cachePage = JSON.stringify(state.app.cachePage);
}
state.app.pageOpenedList.push(tagObj);
}
},
actions: {
},
modules: {
app,
user
}
});
export default store;

181
src/store/modules/app.js Normal file
View File

@ -0,0 +1,181 @@
import {otherRouter, appRouter} from '@/router/router';
import Util from '@/libs/util';
import Cookies from 'js-cookie';
import Vue from 'vue';
import {router} from '@/router/index';
const app = {
state: {
cachePage: [],
lang: '',
isFullScreen: false,
openedSubmenuArr: [], // 要展开的菜单数组
menuTheme: '', // 主题
themeColor: '',
pageOpenedList: [{
title: '首页',
path: '',
name: 'home_index'
}],
currentPageName: '',
currentPath: [
{
title: '首页',
path: '',
name: 'home_index'
}
], // 面包屑数组
menuList: [],
routers: [
otherRouter,
...appRouter
],
tagsList: [...otherRouter.children]
},
mutations: {
setTagsList (state, list) {
state.tagsList.push(...list);
},
updateMenulist (state) {
let accessCode = parseInt(Cookies.get('access'));
let menuList = [];
appRouter.forEach((item, index) => {
if (item.access !== undefined) {
if (Util.showThisRoute(item.access, accessCode)) {
if (item.children.length === 1) {
menuList.push(item);
} else {
let len = menuList.push(item);
let childrenArr = [];
childrenArr = item.children.filter(child => {
if (child.access !== undefined) {
if (child.access === accessCode) {
return child;
}
} else {
return child;
}
});
menuList[len - 1].children = childrenArr;
}
}
} else {
if (item.children.length === 1) {
menuList.push(item);
} else {
let len = menuList.push(item);
let childrenArr = [];
childrenArr = item.children.filter(child => {
if (child.access !== undefined) {
if (Util.showThisRoute(child.access, accessCode)) {
return child;
}
} else {
return child;
}
});
let handledItem = JSON.parse(JSON.stringify(menuList[len - 1]));
handledItem.children = childrenArr;
menuList.splice(len - 1, 1, handledItem);
}
}
});
state.menuList = menuList;
},
changeMenuTheme (state, theme) {
state.menuTheme = theme;
},
changeMainTheme (state, mainTheme) {
state.themeColor = mainTheme;
},
addOpenSubmenu (state, name) {
let hasThisName = false;
let isEmpty = false;
if (name.length === 0) {
isEmpty = true;
}
if (state.openedSubmenuArr.indexOf(name) > -1) {
hasThisName = true;
}
if (!hasThisName && !isEmpty) {
state.openedSubmenuArr.push(name);
}
},
closePage (state, name) {
state.cachePage.forEach((item, index) => {
if (item === name) {
state.cachePage.splice(index, 1);
}
});
},
initCachepage (state) {
if (localStorage.cachePage) {
state.cachePage = JSON.parse(localStorage.cachePage);
}
},
removeTag (state, name) {
state.pageOpenedList.map((item, index) => {
if (item.name === name) {
state.pageOpenedList.splice(index, 1);
}
});
},
pageOpenedList (state, get) {
let openedPage = state.pageOpenedList[get.index];
if (get.argu) {
openedPage.argu = get.argu;
}
if (get.query) {
openedPage.query = get.query;
}
state.pageOpenedList.splice(get.index, 1, openedPage);
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
clearAllTags (state) {
state.pageOpenedList.splice(1);
state.cachePage.length = 0;
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
clearOtherTags (state, vm) {
let currentName = vm.$route.name;
let currentIndex = 0;
state.pageOpenedList.forEach((item, index) => {
if (item.name === currentName) {
currentIndex = index;
}
});
if (currentIndex === 0) {
state.pageOpenedList.splice(1);
} else {
state.pageOpenedList.splice(currentIndex + 1);
state.pageOpenedList.splice(1, currentIndex - 1);
}
let newCachepage = state.cachePage.filter(item => {
return item === currentName;
});
state.cachePage = newCachepage;
localStorage.pageOpenedList = JSON.stringify(state.pageOpenedList);
},
setOpenedList (state) {
state.pageOpenedList = localStorage.pageOpenedList ? JSON.parse(localStorage.pageOpenedList) : [otherRouter.children[0]];
},
setCurrentPath (state, pathArr) {
state.currentPath = pathArr;
},
setCurrentPageName (state, name) {
state.currentPageName = name;
},
setAvator (state, path) {
localStorage.avatorImgPath = path;
},
switchLang (state, lang) {
state.lang = lang;
Vue.config.lang = lang;
},
clearOpenedSubmenu (state) {
state.openedSubmenuArr.length = 0;
}
}
};
export default app;

26
src/store/modules/user.js Normal file
View File

@ -0,0 +1,26 @@
import Cookies from 'js-cookie';
const user = {
state: {},
mutations: {
logout (state, vm) {
Cookies.remove('user');
Cookies.remove('password');
Cookies.remove('access');
// 恢复默认样式
let themeLink = document.querySelector('link[name="theme"]');
themeLink.setAttribute('href', '');
// 清空打开的页面等数据,但是保存主题数据
let theme = '';
if (localStorage.theme) {
theme = localStorage.theme;
}
localStorage.clear();
if (theme) {
localStorage.theme = theme;
}
}
}
};
export default user;

View File

@ -2,14 +2,13 @@
<html lang="zh-CN">
<head>
<title>iView admin</title>
<title><%= htmlWebpackPlugin.options.title %></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
<link rel="stylesheet" name="theme" href="">
<link rel="icon" href="./td_icon.ico" type="image/x-icon" />
<link rel="stylesheet" href="./dist/simplemde.min.css">
<link rel="stylesheet" href="./dist/cropper.min.css">
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[1] %>">
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[2] %>">
</head>
<body>
@ -17,6 +16,7 @@
<div class="lock-screen-back" id="lock_screen_back"></div>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[1] %>"></script>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[2] %>"></script>
</body>
</html>

View File

@ -1,10 +0,0 @@
import Vue from 'vue';
import iView from 'iview';
import VueRouter from 'vue-router';
import axios from 'axios';
import Vuex from 'vuex';
import echarts from 'echarts';
import Cookies from 'js-cookie';
import clipboard from 'clipboard';
import html2canvas from 'html2canvas';
import rasterizehtml from 'rasterizehtml';

4
src/vendors/vendors.base.js vendored Normal file
View File

@ -0,0 +1,4 @@
import Vue from 'vue';
import iView from 'iview';
import VueRouter from 'vue-router';
import Vuex from 'vuex';

6
src/vendors/vendors.exten.js vendored Normal file
View File

@ -0,0 +1,6 @@
import axios from 'axios';
// import echarts from 'echarts';
import Cookies from 'js-cookie';
import clipboard from 'clipboard';
import html2canvas from 'html2canvas';
import rasterizehtml from 'rasterizehtml';

View File

@ -2,19 +2,25 @@
@import "./main.less";
</style>
<template>
<div class="main" :class="{'main-hide-text': hideMenuText}">
<div class="sidebar-menu-con" :style="{width: hideMenuText?'60px':'200px', overflow: hideMenuText ? 'visible' : 'auto', background: $store.state.menuTheme === 'dark'?'#495060':'white'}">
<div class="logo-con">
<img v-show="!hideMenuText" src="../images/logo.jpg" key="max-logo" />
<img v-show="hideMenuText" src="../images/logo-min.jpg" key="min-logo" />
</div>
<sidebar-menu v-if="!hideMenuText" :menuList="menuList" :iconSize="14"/>
<sidebar-menu-shrink :icon-color="menuIconColor" v-else :menuList="menuList"/>
<div class="main" :class="{'main-hide-text': shrink}">
<div class="sidebar-menu-con" :style="{width: shrink?'60px':'200px', overflow: shrink ? 'visible' : 'auto'}">
<shrinkable-menu
:shrink="shrink"
@on-change="handleSubmenuChange"
:theme="menuTheme"
:before-push="beforePush"
:open-names="openedSubmenuArr"
:menu-list="menuList">
<div slot="top" class="logo-con">
<img v-show="!shrink" src="../images/logo.jpg" key="max-logo" />
<img v-show="shrink" src="../images/logo-min.jpg" key="min-logo" />
</div>
</shrinkable-menu>
</div>
<div class="main-header-con" :style="{paddingLeft: hideMenuText?'60px':'200px'}">
<div class="main-header-con" :style="{paddingLeft: shrink?'60px':'200px'}">
<div class="main-header">
<div class="navicon-con">
<Button :style="{transform: 'rotateZ(' + (this.hideMenuText ? '-90' : '0') + 'deg)'}" type="text" @click="toggleClick">
<Button :style="{transform: 'rotateZ(' + (this.shrink ? '-90' : '0') + 'deg)'}" type="text" @click="toggleClick">
<Icon type="navicon" size="32"></Icon>
</Button>
</div>
@ -24,28 +30,11 @@
</div>
</div>
<div class="header-avator-con">
<div @click="handleFullScreen" v-if="showFullScreenBtn" class="full-screen-btn-con">
<Tooltip :content="isFullScreen ? '退出全屏' : '全屏'" placement="bottom">
<Icon :type="isFullScreen ? 'arrow-shrink' : 'arrow-expand'" :size="23"></Icon>
</Tooltip>
</div>
<div @click="lockScreen" class="lock-screen-btn-con">
<Tooltip content="锁屏" placement="bottom">
<Icon type="locked" :size="20"></Icon>
</Tooltip>
</div>
<div @click="showMessage" class="message-con">
<Tooltip :content="messageCount > 0 ? '有' + messageCount + '条未读消息' : '无未读消息'" placement="bottom">
<Badge :count="messageCount" dot>
<Icon type="ios-bell" :size="22"></Icon>
</Badge>
</Tooltip>
</div>
<div class="switch-theme-con">
<Row class="switch-theme" type="flex" justify="center" align="middle">
<theme-dropdown-menu></theme-dropdown-menu>
</Row>
</div>
<full-screen v-model="isFullScreen" @on-change="fullscreenChange"></full-screen>
<lock-screen></lock-screen>
<message-tip v-model="mesCount"></message-tip>
<theme-switch></theme-switch>
<div class="user-dropdown-menu-con">
<Row type="flex" justify="end" align="middle" class="user-dropdown-innercon">
<Dropdown transfer trigger="click" @on-click="handleClickUserDropdown">
@ -67,7 +56,7 @@
<tags-page-opened :pageTagsList="pageTagsList"></tags-page-opened>
</div>
</div>
<div class="single-page-con" :style="{left: hideMenuText?'60px':'200px'}">
<div class="single-page-con" :style="{left: shrink?'60px':'200px'}">
<div class="single-page">
<keep-alive :include="cachePage">
<router-view></router-view>
@ -77,66 +66,59 @@
</div>
</template>
<script>
import sidebarMenu from './main_components/sidebarMenu.vue';
import shrinkableMenu from './main_components/shrinkable-menu/shrinkable-menu.vue';
import tagsPageOpened from './main_components/tagsPageOpened.vue';
import breadcrumbNav from './main_components/breadcrumbNav.vue';
import themeDropdownMenu from './main_components/themeDropdownMenu.vue';
import sidebarMenuShrink from './main_components/sidebarMenuShrink.vue';
import fullScreen from './main_components/fullScreen.vue';
import lockScreen from './main_components/lockscreen/lockscreen.vue';
import messageTip from './main_components/message-tip.vue';
import themeSwitch from './main_components/theme-switch/themeSwitch.vue';
import Cookies from 'js-cookie';
import util from '@/libs/util.js';
export default {
components: {
sidebarMenu,
shrinkableMenu,
tagsPageOpened,
breadcrumbNav,
themeDropdownMenu,
sidebarMenuShrink
fullScreen,
lockScreen,
messageTip,
themeSwitch
},
data () {
return {
spanLeft: 4,
spanRight: 20,
currentPageName: '',
hideMenuText: false,
shrink: false,
userName: '',
showFullScreenBtn: window.navigator.userAgent.indexOf('MSIE') < 0,
messageCount: 0,
lockScreenSize: 0
mesCount: 3,
menuTheme: this.$store.state.app.menuTheme,
isFullScreen: false,
openedSubmenuArr: this.$store.state.app.openedSubmenuArr
};
},
computed: {
menuList () {
return this.$store.state.menuList;
},
tagsList () {
return this.$store.state.tagsList; //
return this.$store.state.app.menuList;
},
pageTagsList () {
return this.$store.state.pageOpenedList; //
return this.$store.state.app.pageOpenedList; //
},
currentPath () {
return this.$store.state.currentPath; //
},
menuIconColor () {
return this.$store.state.menuTheme === 'dark' ? 'white' : '#495060';
return this.$store.state.app.currentPath; //
},
avatorPath () {
return localStorage.avatorImgPath;
},
cachePage () {
return this.$store.state.cachePage;
return this.$store.state.app.cachePage;
},
lang () {
return this.$store.state.lang;
},
isFullScreen () {
return this.$store.state.isFullScreen;
return this.$store.state.app.lang;
}
},
methods: {
init () {
this.$store.commit('setCurrentPageName', this.$route.name);
// this.$store.commit('setCurrentPageName', this.$route.name);
let pathArr = util.setCurrentPath(this, this.$route.name);
if (pathArr.length >= 2) {
this.$store.commit('addOpenSubmenu', pathArr[1].name);
@ -147,7 +129,7 @@
this.checkTag(this.$route.name);
},
toggleClick () {
this.hideMenuText = !this.hideMenuText;
this.shrink = !this.shrink;
},
handleClickUserDropdown (name) {
if (name === 'ownSpace') {
@ -157,54 +139,13 @@
});
} else if (name === 'loginout') {
// 退
Cookies.remove('user');
Cookies.remove('password');
Cookies.remove('hasGreet');
Cookies.remove('access');
this.$Notice.close('greeting');
this.$store.commit('logout', this);
this.$store.commit('clearOpenedSubmenu');
//
let themeLink = document.querySelector('link[name="theme"]');
themeLink.setAttribute('href', '');
//
let theme = '';
if (localStorage.theme) {
theme = localStorage.theme;
}
localStorage.clear();
if (theme) {
localStorage.theme = theme;
}
this.$router.push({
name: 'login'
});
}
},
handleFullScreen () {
this.$store.commit('handleFullScreen');
// this.$store.commit('changeFullScreenState');
},
showMessage () {
util.openNewPage(this, 'message_index');
this.$router.push({
name: 'message_index'
});
},
lockScreen () {
let lockScreenBack = document.getElementById('lock_screen_back');
lockScreenBack.style.transition = 'all 3s';
lockScreenBack.style.zIndex = 10000;
lockScreenBack.style.boxShadow = '0 0 0 ' + this.lockScreenSize + 'px #667aa6 inset';
this.showUnlock = true;
this.$store.commit('lock');
Cookies.set('last_page_name', this.$route.name); // 便
setTimeout(() => {
lockScreenBack.style.transition = 'all 0s';
this.$router.push({
name: 'locking'
});
}, 800);
},
checkTag (name) {
let openpageHasTag = this.pageTagsList.some(item => {
if (item.name === name) {
@ -214,6 +155,19 @@
if (!openpageHasTag) { // 退退
util.openNewPage(this, name, this.$route.params || {}, this.$route.query || {});
}
},
handleSubmenuChange (val) {
// console.log(val)
},
beforePush (name) {
if (name === 'accesstest_index') {
return false;
} else {
return true;
}
},
fullscreenChange (isFullScreen) {
// console.log(isFullScreen);
}
},
watch: {
@ -224,6 +178,7 @@
this.$store.commit('addOpenSubmenu', pathArr[1].name);
}
this.checkTag(to.name);
localStorage.currentPageName = to.name;
},
lang () {
util.setCurrentPath(this, this.$route.name); //
@ -231,88 +186,8 @@
},
mounted () {
this.init();
//
let lockScreenBack = document.getElementById('lock_screen_back');
let x = document.body.clientWidth;
let y = document.body.clientHeight;
let r = Math.sqrt(x * x + y * y);
let size = parseInt(r);
this.lockScreenSize = size;
window.addEventListener('resize', () => {
let x = document.body.clientWidth;
let y = document.body.clientHeight;
let r = Math.sqrt(x * x + y * y);
let size = parseInt(r);
this.lockScreenSize = size;
lockScreenBack.style.transition = 'all 0s';
lockScreenBack.style.width = lockScreenBack.style.height = size + 'px';
});
lockScreenBack.style.width = lockScreenBack.style.height = size + 'px';
//
if (!Cookies.get('hasGreet')) {
let now = new Date();
let hour = now.getHours();
let greetingWord = {
title: '',
words: ''
};
let userName = Cookies.get('user');
if (hour > 5 && hour < 6) {
greetingWord = {title: '凌晨好~' + userName, words: '早起的鸟儿有虫吃~'};
} else if (hour >= 6 && hour < 9) {
greetingWord = {title: '早上好~' + userName, words: '来一杯咖啡开启美好的一天~'};
} else if (hour >= 9 && hour < 12) {
greetingWord = {title: '上午好~' + userName, words: '工作要加油哦~'};
} else if (hour >= 12 && hour < 14) {
greetingWord = {title: '中午好~' + userName, words: '午饭要吃饱~'};
} else if (hour >= 14 && hour < 17) {
greetingWord = {title: '下午好~' + userName, words: '下午也要活力满满哦~'};
} else if (hour >= 17 && hour < 19) {
greetingWord = {title: '傍晚好~' + userName, words: '下班没事问候下爸妈吧~'};
} else if (hour >= 19 && hour < 21) {
greetingWord = {title: '晚上好~' + userName, words: '工作之余品一品书香吧~'};
} else {
greetingWord = {title: '深夜好~' + userName, words: '夜深了,注意休息哦~'};
}
this.$Notice.config({
top: 130
});
this.$Notice.info({
title: greetingWord.title,
desc: greetingWord.words,
duration: 4,
name: 'greeting'
});
Cookies.set('hasGreet', 1);
}
},
created () {
//
let name = Cookies.get('user');
if (localStorage.theme) {
let hasThisUser = JSON.parse(localStorage.theme).some(item => {
if (item.userName === name) {
this.$store.commit('changeMenuTheme', item.menuTheme);
this.$store.commit('changeMainTheme', item.mainTheme);
return true;
} else {
return false;
}
});
if (!hasThisUser) {
this.$store.commit('changeMenuTheme', 'dark');
this.$store.commit('changeMainTheme', 'b');
}
} else {
this.$store.commit('changeMenuTheme', 'dark');
this.$store.commit('changeMainTheme', 'b');
}
//
if (this.$store.state.theme !== 'b') {
let stylesheetPath = './dist/' + this.$store.state.theme + '.css';
let themeLink = document.querySelector('link[name="theme"]');
themeLink.setAttribute('href', stylesheetPath);
}
//
this.$store.commit('setOpenedList');
}

View File

@ -1,4 +1,4 @@
@keyframes error401animation {
@keyframes error403animation {
0% {
transform: rotateZ(0deg);
}
@ -21,7 +21,7 @@
transform: rotateZ(0deg);
}
}
.error401{
.error403{
&-body-con{
width: 700px;
height: 500px;
@ -37,7 +37,7 @@
height: 260px;
line-height: 260px;
margin-top: 40px;
.error401-0-span{
.error403-0-span{
display: inline-block;
position: relative;
width: 170px;
@ -55,11 +55,11 @@
transform: translate(-50%,-50%);
}
}
.error401-key-span{
.error403-key-span{
display: inline-block;
position: relative;
width: 100px;
height: 170px;
height: 190px;
border-radius: 50%;
margin-right: 10px;
i{
@ -67,9 +67,9 @@
font-size: 190px;
position: absolute;
left: 20px;
transform: translate(-50%,-50%);
transform: translate(-50%,-60%);
transform-origin: center bottom;
animation: error401animation 2.8s ease 0s infinite;
animation: error403animation 2.8s ease 0s infinite;
}
}
}

View File

@ -1,14 +1,14 @@
<style lang="less">
@import './401.less';
@import './403.less';
</style>
<template>
<div class="error401">
<div class="error401-body-con">
<div class="error403">
<div class="error403-body-con">
<Card>
<div class="error401-body-con-title">4<span class="error401-0-span"><Icon type="android-lock"></Icon></span><span class="error401-key-span"><Icon type="key"></Icon></span></div>
<p class="error401-body-con-message">You don't have permission</p>
<div class="error401-btn-con">
<div class="error403-body-con-title">4<span class="error403-0-span"><Icon type="android-lock"></Icon></span><span class="error403-key-span"><Icon size="220" type="ios-bolt"></Icon></span></div>
<p class="error403-body-con-message">You don't have permission</p>
<div class="error403-btn-con">
<Button @click="goHome" size="large" style="width: 200px;" type="text">返回首页</Button>
<Button @click="backPage" size="large" style="width: 200px;margin-left: 40px;" type="primary">返回上一页</Button>
</div>
@ -19,7 +19,7 @@
<script>
export default {
name: 'Error401',
name: 'Error403',
methods: {
backPage () {
this.$router.go(-1);

View File

@ -34,14 +34,14 @@
<Card>
<p slot="title">
<Icon :size="14" type="android-lock"></Icon>
401-权限不足
403-权限不足
</p>
<Row>
<Col span="10">
<Card dis-hover>
<Row>
<div class="error-page-show">
<error401></error401>
<error403></error403>
</div>
<div class="error-page-cover"></div>
</Row>
@ -86,12 +86,12 @@
<script>
import Error404 from './404.vue';
import Error500 from './500.vue';
import Error401 from './401.vue';
import Error403 from './403.vue';
export default {
components: {
Error404,
Error500,
Error401
Error403
}
};
</script>

View File

@ -3,7 +3,7 @@
</template>
<script>
const echarts = require('echarts');
import echarts from 'echarts';
export default {
name: 'dataSourcePie',

View File

@ -3,7 +3,7 @@
</template>
<script>
const echarts = require('echarts');
import echarts from 'echarts';
export default {
name: 'serviceRequests',
mounted () {

View File

@ -3,7 +3,7 @@
</template>
<script>
const echarts = require('echarts');
import echarts from 'echarts';
export default {
name: 'visiteVolume',
data () {

View File

@ -1,10 +1,10 @@
<template>
<Breadcrumb>
<BreadcrumbItem
v-for="item in $store.state.currentPath"
v-for="item in currentPath"
:href="item.path"
:key="item.name"
>{{itemTitle(item)}}</BreadcrumbItem>
>{{ itemTitle(item) }}</BreadcrumbItem>
</Breadcrumb>
</template>

View File

@ -0,0 +1,74 @@
<template>
<div @click="handleChange" v-if="showFullScreenBtn" class="full-screen-btn-con">
<Tooltip :content="value ? '退出全屏' : '全屏'" placement="bottom">
<Icon :type="value ? 'arrow-shrink' : 'arrow-expand'" :size="23"></Icon>
</Tooltip>
</div>
</template>
<script>
export default {
name: 'fullScreen',
props: {
value: {
type: Boolean,
default: false
}
},
computed: {
showFullScreenBtn () {
return window.navigator.userAgent.indexOf('MSIE') < 0;
}
},
methods: {
handleFullscreen () {
let main = document.body;
if (this.value) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (main.requestFullscreen) {
main.requestFullscreen();
} else if (main.mozRequestFullScreen) {
main.mozRequestFullScreen();
} else if (main.webkitRequestFullScreen) {
main.webkitRequestFullScreen();
} else if (main.msRequestFullscreen) {
main.msRequestFullscreen();
}
}
},
handleChange () {
this.handleFullscreen();
}
},
created () {
let isFullscreen = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
isFullscreen = !!isFullscreen;
document.addEventListener('fullscreenchange', () => {
this.$emit('input', !this.value);
this.$emit('on-change', !this.value);
});
document.addEventListener('mozfullscreenchange', () => {
this.$emit('input', !this.value);
this.$emit('on-change', !this.value);
});
document.addEventListener('webkitfullscreenchange', () => {
this.$emit('input', !this.value);
this.$emit('on-change', !this.value);
});
document.addEventListener('msfullscreenchange', () => {
this.$emit('input', !this.value);
this.$emit('on-change', !this.value);
});
this.$emit('input', isFullscreen);
}
};
</script>

View File

@ -31,6 +31,12 @@ export default {
},
mounted () {
this.showUnlock = true;
if (!document.getElementById('lock_screen_back')) {
let lockdiv = document.createElement('div');
lockdiv.setAttribute('id', 'lock_screen_back');
lockdiv.setAttribute('class', 'lock-screen-back');
document.body.appendChild(lockdiv);
}
let lockScreenBack = document.getElementById('lock_screen_back');
lockScreenBack.style.zIndex = -1;
}

View File

@ -1,5 +1,5 @@
<style lang="less">
@import './unlock.less';
@import '../styles/unlock.less';
</style>
<template>
@ -34,7 +34,8 @@ export default {
return {
avatorLeft: '0px',
inputLeft: '400px',
password: ''
password: '',
check: null
};
},
props: {
@ -49,17 +50,20 @@ export default {
}
},
methods: {
validator () {
return true; // ajaxthis.password
},
handleClickAvator () {
this.avatorLeft = '-180px';
this.inputLeft = '0px';
this.$refs.inputEle.focus();
},
handleUnlock () {
if (Cookies.get('password') === this.password) {
if (this.validator()) {
this.avatorLeft = '0px';
this.inputLeft = '400px';
this.password = '';
this.$store.commit('unlock');
Cookies.set('locking', '0');
this.$emit('on-unlock');
} else {
this.$Message.error('密码错误,请重新输入。如果忘了密码,清除浏览器缓存重新登录即可,这里没有做后端验证');

View File

@ -0,0 +1,60 @@
<template>
<div @click="lockScreen" class="lock-screen-btn-con">
<Tooltip content="锁屏" placement="bottom">
<Icon type="locked" :size="20"></Icon>
</Tooltip>
</div>
</template>
<script>
import Cookies from 'js-cookie';
export default {
name: 'lockScreen',
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
lockScreen () {
let lockScreenBack = document.getElementById('lock_screen_back');
lockScreenBack.style.transition = 'all 3s';
lockScreenBack.style.zIndex = 10000;
lockScreenBack.style.boxShadow = '0 0 0 ' + this.lockScreenSize + 'px #667aa6 inset';
this.showUnlock = true;
Cookies.set('last_page_name', this.$route.name); // 便
setTimeout(() => {
lockScreenBack.style.transition = 'all 0s';
this.$router.push({
name: 'locking'
});
}, 800);
Cookies.set('locking', '1');
}
},
mounted () {
let lockdiv = document.createElement('div');
lockdiv.setAttribute('id', 'lock_screen_back');
lockdiv.setAttribute('class', 'lock-screen-back');
document.body.appendChild(lockdiv);
let lockScreenBack = document.getElementById('lock_screen_back');
let x = document.body.clientWidth;
let y = document.body.clientHeight;
let r = Math.sqrt(x * x + y * y);
let size = parseInt(r);
this.lockScreenSize = size;
window.addEventListener('resize', () => {
let x = document.body.clientWidth;
let y = document.body.clientHeight;
let r = Math.sqrt(x * x + y * y);
let size = parseInt(r);
this.lockScreenSize = size;
lockScreenBack.style.transition = 'all 0s';
lockScreenBack.style.width = lockScreenBack.style.height = size + 'px';
});
lockScreenBack.style.width = lockScreenBack.style.height = size + 'px';
}
};
</script>

View File

@ -0,0 +1,30 @@
<template>
<div @click="showMessage" class="message-con">
<Tooltip :content="value > 0 ? '有' + value + '条未读消息' : '无未读消息'" placement="bottom">
<Badge :count="value" dot>
<Icon type="ios-bell" :size="22"></Icon>
</Badge>
</Tooltip>
</div>
</template>
<script>
import util from '@/libs/util.js';
export default {
name: 'messageTip',
props: {
value: {
type: Number,
default: 0
}
},
methods: {
showMessage () {
util.openNewPage(this, 'message_index');
this.$router.push({
name: 'message_index'
});
}
}
};
</script>

View File

@ -1,16 +1,16 @@
<style lang="less">
@import './menu.less';
@import '../styles/menu.less';
</style>
<template>
<Menu ref="sideMenu" :active-name="$route.name" :open-names="openedSubmenuArr" :theme="$store.state.menuTheme" width="auto" @on-select="changeMenu">
<Menu ref="sideMenu" :active-name="$route.name" :open-names="openNames" :theme="menuTheme" width="auto" @on-select="changeMenu">
<template v-for="item in menuList">
<MenuItem v-if="item.children.length<=1" :name="item.children[0].name" :key="item.path">
<Icon :type="item.icon" :size="iconSize" :key="item.path"></Icon>
<span class="layout-text" :key="item.path">{{ itemTitle(item) }}</span>
</MenuItem>
<Submenu v-if="item.children.length>1" :name="item.name" :key="item.path">
<Submenu v-if="item.children.length > 1" :name="item.name" :key="item.path">
<template slot="title">
<Icon :type="item.icon" :size="iconSize"></Icon>
<span class="layout-text">{{ itemTitle(item) }}</span>
@ -27,35 +27,22 @@
</template>
<script>
import util from '@/libs/util';
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
export default {
data () {
return {
openedSubmenuArr: this.$store.state.openedSubmenuArr
};
},
name: 'sidebarMenu',
props: {
slotTopClass: String,
menuList: Array,
iconSize: Number
},
computed: {
tagsList () {
return this.$store.state.tagsList;
iconSize: Number,
menuTheme: {
type: String,
default: 'dark'
},
openNames: {
type: Array
}
},
methods: {
changeMenu (active) {
if (active !== 'accesstest_index') {
util.openNewPage(this, active);
this.$router.push({
name: active
});
}
this.$emit('on-change', active);
},
itemTitle (item) {
if (typeof item.title === 'object') {
@ -65,19 +52,6 @@ export default {
}
}
},
watch: {
'$route' (to) {
localStorage.currentPageName = to.name;
},
currentPageName () {
this.openedSubmenuArr = this.$store.state.openedSubmenuArr;
this.$nextTick(() => {
if (this.$refs.sideMenu) {
this.$refs.sideMenu.updateOpened();
}
});
}
},
updated () {
this.$nextTick(() => {
if (this.$refs.sideMenu) {

View File

@ -26,10 +26,6 @@
</template>
<script>
import util from '@/libs/util';
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
export default {
name: 'sidebarMenuShrink',
props: {
@ -39,27 +35,15 @@ export default {
iconColor: {
type: String,
default: 'white'
}
},
data () {
return {
currentPageName: this.$route.name,
openedSubmenuArr: this.$store.state.openedSubmenuArr
};
},
computed: {
tagsList () {
return this.$store.state.tagsList;
},
menuTheme: {
type: String,
default: 'darck'
}
},
methods: {
changeMenu (active) {
if (active !== 'accesstest_index') {
util.openNewPage(this, active);
this.$router.push({
name: active
});
}
this.$emit('on-change', active);
},
itemTitle (item) {
if (typeof item.title === 'object') {
@ -68,12 +52,6 @@ export default {
return item.title;
}
}
},
watch: {
'$route' (to) {
this.currentPageName = to.name;
localStorage.currentPageName = to.name;
}
}
};
</script>

View File

@ -0,0 +1,80 @@
<style lang="less">
@import './styles/menu.less';
</style>
<template>
<div :style="{background: bgColor}" class="ivu-shrinkable-menu">
<slot name="top"></slot>
<sidebar-menu
v-show="!shrink"
:menu-theme="menuTheme"
:menu-list="menuList"
:open-names="openNames"
@on-change="handleChange"
></sidebar-menu>
<sidebar-menu-shrink
v-show="shrink"
:menu-theme="menuTheme"
:menu-list="menuList"
@on-change="handleChange"
></sidebar-menu-shrink>
</div>
</template>
<script>
import sidebarMenu from './components/sidebarMenu.vue';
import sidebarMenuShrink from './components/sidebarMenuShrink.vue';
import util from '@/libs/util';
export default {
name: 'shrinkableMenu',
components: {
sidebarMenu,
sidebarMenuShrink
},
props: {
shrink: {
type: Boolean,
default: false
},
menuList: {
type: Array,
required: true
},
menuTheme: {
type: String,
default: 'dark',
validator (val) {
return util.oneOf(val, ['dark', 'light']);
}
},
beforePush: {
type: Function
},
openNames: {
type: Array
}
},
computed: {
bgColor () {
return this.menuTheme === 'dark' ? '#495060' : '#fff';
}
},
methods: {
handleChange (name) {
let willpush = true;
if (this.beforePush !== undefined) {
if (!this.beforePush(name)) {
willpush = false;
}
}
if (willpush) {
this.$router.push({
name: name
});
util.openNewPage(this, name);
}
this.$emit('on-change', name);
}
}
};
</script>

View File

@ -0,0 +1,4 @@
.ivu-shrinkable-menu{
height: 100%;
width: 100%;
}

View File

@ -3,7 +3,7 @@
</style>
<template>
<div ref="scrollCon" @mousewheel="handlescroll" class="tags-outer-scroll-con">
<div ref="scrollCon" @DOMMouseScroll="handlescroll" @mousewheel="handlescroll" class="tags-outer-scroll-con">
<div class="close-all-tag-con">
<Dropdown transfer @on-click="handleTagsOption">
<Button size="small" type="primary">
@ -44,20 +44,25 @@ export default {
return {
currentPageName: this.$route.name,
tagBodyLeft: 0,
currentScrollBodyWidth: 0,
refsTag: [],
tagsCount: 1
};
},
props: {
pageTagsList: Array
pageTagsList: Array,
beforePush: {
type: Function,
default: (item) => {
return true;
}
}
},
computed: {
title () {
return this.$store.state.currentTitle;
return this.$store.state.app.currentTitle;
},
tagsList () {
return this.$store.state.pageOpenedList;
return this.$store.state.app.pageOpenedList;
}
},
methods: {
@ -71,13 +76,14 @@ export default {
closePage (event, name) {
this.$store.commit('removeTag', name);
this.$store.commit('closePage', name);
localStorage.pageOpenedList = JSON.stringify(this.$store.state.pageOpenedList);
let pageOpenedList = this.$store.state.app.pageOpenedList;
localStorage.pageOpenedList = JSON.stringify(pageOpenedList);
if (this.currentPageName === name) {
let lastPageName = '';
if (this.$store.state.pageOpenedList.length > 1) {
lastPageName = this.$store.state.pageOpenedList[1].name;
if (pageOpenedList.length > 1) {
lastPageName = pageOpenedList[1].name;
} else {
lastPageName = this.$store.state.pageOpenedList[0].name;
lastPageName = pageOpenedList[0].name;
}
this.$router.push({
name: lastPageName
@ -93,18 +99,25 @@ export default {
if (item.query) {
routerObj.query = item.query;
}
this.$router.push(routerObj);
if (this.beforePush(item)) {
this.$router.push(routerObj);
}
},
handlescroll (e) {
var type = e.type;
let delta = 0;
if (type === 'DOMMouseScroll' || type === 'mousewheel') {
delta = (e.wheelDelta) ? e.wheelDelta : -(e.detail || 0) * 40;
}
let left = 0;
if (e.wheelDelta > 0) {
left = Math.min(0, this.tagBodyLeft + e.wheelDelta);
if (delta > 0) {
left = Math.min(0, this.tagBodyLeft + delta);
} else {
if (this.$refs.scrollCon.offsetWidth - 100 < this.$refs.scrollBody.offsetWidth) {
if (this.tagBodyLeft < -(this.$refs.scrollBody.offsetWidth - this.$refs.scrollCon.offsetWidth + 100)) {
left = this.tagBodyLeft;
} else {
left = Math.max(this.tagBodyLeft + e.wheelDelta, this.$refs.scrollCon.offsetWidth - this.$refs.scrollBody.offsetWidth - 100);
left = Math.max(this.tagBodyLeft + delta, this.$refs.scrollCon.offsetWidth - this.$refs.scrollBody.offsetWidth - 100);
}
} else {
this.tagBodyLeft = 0;
@ -115,6 +128,9 @@ export default {
handleTagsOption (type) {
if (type === 'clearAll') {
this.$store.commit('clearAllTags');
this.$router.push({
name: 'home_index'
});
} else {
this.$store.commit('clearOtherTags', this);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,24 +1,27 @@
<template>
<Dropdown trigger="click" @on-click="setTheme">
<a href="javascript:void(0)">
<Icon :style="{marginTop: '-2px', verticalAlign: 'middle'}" color="#495060" :size="18" type="paintbucket"></Icon>
<Icon type="arrow-down-b"></Icon>
</a>
<DropdownMenu slot="list">
<DropdownItem v-for="(item, index) in themeList" :key="index" :name="item.name">
<Row type="flex" justify="center" align="middle">
<span style="margin-right:10px;"><Icon :size="20" :type="item.name.substr(0, 1) !== 'b' ? 'happy-outline' : 'happy'" :color="item.menu"/></span>
<span><Icon :size="22" type="record" :color="item.element"/></span>
</Row>
</DropdownItem>
</DropdownMenu>
</Dropdown>
<div style="display:inline-block;padding:0 6px;">
<Dropdown trigger="click" @on-click="setTheme">
<a href="javascript:void(0)">
<Icon :style="{marginTop: '-2px', verticalAlign: 'middle'}" color="#495060" :size="18" type="paintbucket"></Icon>
<Icon type="arrow-down-b"></Icon>
</a>
<DropdownMenu slot="list">
<DropdownItem v-for="(item, index) in themeList" :key="index" :name="item.name">
<Row type="flex" justify="center" align="middle">
<span style="margin-right:10px;"><Icon :size="20" :type="item.name.substr(0, 1) !== 'b' ? 'happy-outline' : 'happy'" :color="item.menu"/></span>
<span><Icon :size="22" type="record" :color="item.element"/></span>
</Row>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</template>
<script>
import Cookies from 'js-cookie';
import config from '../../../../build/config.js';
export default {
name: 'themeDropdownMenu',
name: 'themeSwitch',
data () {
return {
themeList: [
@ -30,17 +33,17 @@ export default {
{
name: 'black_g',
menu: '#495060',
element: '#64d572'
element: '#00a854'
},
{
name: 'black_y',
menu: '#495060',
element: '#ffd572'
element: '#e96500'
},
{
name: 'black_r',
menu: '#495060',
element: '#f25e43'
element: '#e43e31'
},
{
name: 'light_b',
@ -50,17 +53,17 @@ export default {
{
name: 'light_g',
menu: '#495060',
element: '#64d572'
element: '#00a854'
},
{
name: 'light_y',
menu: '#495060',
element: '#ffd572'
element: '#e96500'
},
{
name: 'light_r',
menu: '#495060',
element: '#f25e43'
element: '#e43e31'
}
]
};
@ -109,13 +112,52 @@ export default {
menuTheme: menuTheme
}]);
}
let stylePath = '';
if (config.env.indexOf('dev') > -1) {
stylePath = './src/views/main_components/theme-switch/theme/';
} else {
stylePath = 'dist/';
}
if (mainTheme !== 'b') {
path = 'dist/' + mainTheme + '.css';
path = stylePath + mainTheme + '.css';
} else {
path = '';
}
themeLink.setAttribute('href', path);
}
},
created () {
let path = '';
if (config.env.indexOf('dev') > -1) {
path = './src/views/main_components/theme-switch/theme/';
} else {
path = 'dist/';
}
let name = Cookies.get('user');
if (localStorage.theme) {
let hasThisUser = JSON.parse(localStorage.theme).some(item => {
if (item.userName === name) {
this.$store.commit('changeMenuTheme', item.menuTheme);
this.$store.commit('changeMainTheme', item.mainTheme);
return true;
} else {
return false;
}
});
if (!hasThisUser) {
this.$store.commit('changeMenuTheme', 'dark');
this.$store.commit('changeMainTheme', 'b');
}
} else {
this.$store.commit('changeMenuTheme', 'dark');
this.$store.commit('changeMainTheme', 'b');
}
//
if (this.$store.state.app.themeColor !== 'b') {
let stylesheetPath = path + this.$store.state.app.themeColor + '.css';
let themeLink = document.querySelector('link[name="theme"]');
themeLink.setAttribute('href', stylesheetPath);
}
}
};
</script>

View File

@ -0,0 +1,23 @@
<template>
<div class="user-dropdown-menu-con">
<Row type="flex" justify="end" align="middle" class="user-dropdown-innercon">
<Dropdown transfer trigger="click" @on-click="handleClickUserDropdown">
<a href="javascript:void(0)">
<span class="main-user-name">{{ userName }}</span>
<Icon type="arrow-down-b"></Icon>
</a>
<DropdownMenu slot="list">
<DropdownItem name="ownSpace">个人中心</DropdownItem>
<DropdownItem name="loginout" divided>退出登录</DropdownItem>
</DropdownMenu>
</Dropdown>
<Avatar :src="avatorPath" style="background: #619fe7;margin-left: 10px;"></Avatar>
</Row>
</div>
</template>
<script>
export default {
name: 'userInfo'
};
</script>

View File

@ -15,7 +15,7 @@
</template>
<script>
import tinymce from 'tinymce';
const tinymce = require('tinymce');
export default {
name: 'text-editor',
data () {
@ -63,7 +63,7 @@ export default {
});
}
},
created () {
mounted () {
this.init();
},
destroyed () {

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