add prettier and deep fixed
This commit is contained in:
parent
0f5ea1867a
commit
521316e256
220
.eslintrc.js
220
.eslintrc.js
|
@ -1,198 +1,38 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
parserOptions: {
|
|
||||||
parser: 'babel-eslint',
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
node: true,
|
node: true,
|
||||||
es6: true,
|
es6: true
|
||||||
|
},
|
||||||
|
parser: "vue-eslint-parser",
|
||||||
|
parserOptions: {
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
sourceType: "module"
|
||||||
},
|
},
|
||||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
|
||||||
|
|
||||||
// add your custom rules here
|
plugins: [
|
||||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
"vue",
|
||||||
|
"@typescript-eslint",
|
||||||
|
"jsdoc",
|
||||||
|
"eslint-comments",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
"vue/max-attributes-per-line": [2, {
|
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"singleline": 10,
|
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"multiline": {
|
|
||||||
"max": 1,
|
"prettier/prettier": ["error"]
|
||||||
"allowFirstLine": false
|
},
|
||||||
}
|
extends: ["plugin:vue/essential", "prettier"] // activate vue related rules
|
||||||
}],
|
// extends: [
|
||||||
"vue/singleline-html-element-content-newline": "off",
|
// "eslint:recommended",
|
||||||
"vue/multiline-html-element-content-newline":"off",
|
// "plugin:vue/recommended",
|
||||||
"vue/name-property-casing": ["error", "PascalCase"],
|
// "plugin:vue/base",
|
||||||
"vue/no-v-html": "off",
|
// "@vue/standard",
|
||||||
'accessor-pairs': 2,
|
// "@vue/typescript",
|
||||||
'arrow-spacing': [2, {
|
// "plugin:prettier/recommended"
|
||||||
'before': true,
|
// ]
|
||||||
'after': true
|
};
|
||||||
}],
|
|
||||||
'block-spacing': [2, 'always'],
|
|
||||||
'brace-style': [2, '1tbs', {
|
|
||||||
'allowSingleLine': true
|
|
||||||
}],
|
|
||||||
'camelcase': [0, {
|
|
||||||
'properties': 'always'
|
|
||||||
}],
|
|
||||||
'comma-dangle': [2, 'never'],
|
|
||||||
'comma-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'comma-style': [2, 'last'],
|
|
||||||
'constructor-super': 2,
|
|
||||||
'curly': [2, 'multi-line'],
|
|
||||||
'dot-location': [2, 'property'],
|
|
||||||
'eol-last': 2,
|
|
||||||
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
|
||||||
'generator-star-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'handle-callback-err': [2, '^(err|error)$'],
|
|
||||||
'indent': [2, 2, {
|
|
||||||
'SwitchCase': 1
|
|
||||||
}],
|
|
||||||
'jsx-quotes': [2, 'prefer-single'],
|
|
||||||
'key-spacing': [2, {
|
|
||||||
'beforeColon': false,
|
|
||||||
'afterColon': true
|
|
||||||
}],
|
|
||||||
'keyword-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'new-cap': [2, {
|
|
||||||
'newIsCap': true,
|
|
||||||
'capIsNew': false
|
|
||||||
}],
|
|
||||||
'new-parens': 2,
|
|
||||||
'no-array-constructor': 2,
|
|
||||||
'no-caller': 2,
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-class-assign': 2,
|
|
||||||
'no-cond-assign': 2,
|
|
||||||
'no-const-assign': 2,
|
|
||||||
'no-control-regex': 0,
|
|
||||||
'no-delete-var': 2,
|
|
||||||
'no-dupe-args': 2,
|
|
||||||
'no-dupe-class-members': 2,
|
|
||||||
'no-dupe-keys': 2,
|
|
||||||
'no-duplicate-case': 2,
|
|
||||||
'no-empty-character-class': 2,
|
|
||||||
'no-empty-pattern': 2,
|
|
||||||
'no-eval': 2,
|
|
||||||
'no-ex-assign': 2,
|
|
||||||
'no-extend-native': 2,
|
|
||||||
'no-extra-bind': 2,
|
|
||||||
'no-extra-boolean-cast': 2,
|
|
||||||
'no-extra-parens': [2, 'functions'],
|
|
||||||
'no-fallthrough': 2,
|
|
||||||
'no-floating-decimal': 2,
|
|
||||||
'no-func-assign': 2,
|
|
||||||
'no-implied-eval': 2,
|
|
||||||
'no-inner-declarations': [2, 'functions'],
|
|
||||||
'no-invalid-regexp': 2,
|
|
||||||
'no-irregular-whitespace': 2,
|
|
||||||
'no-iterator': 2,
|
|
||||||
'no-label-var': 2,
|
|
||||||
'no-labels': [2, {
|
|
||||||
'allowLoop': false,
|
|
||||||
'allowSwitch': false
|
|
||||||
}],
|
|
||||||
'no-lone-blocks': 2,
|
|
||||||
'no-mixed-spaces-and-tabs': 2,
|
|
||||||
'no-multi-spaces': 2,
|
|
||||||
'no-multi-str': 2,
|
|
||||||
'no-multiple-empty-lines': [2, {
|
|
||||||
'max': 1
|
|
||||||
}],
|
|
||||||
'no-native-reassign': 2,
|
|
||||||
'no-negated-in-lhs': 2,
|
|
||||||
'no-new-object': 2,
|
|
||||||
'no-new-require': 2,
|
|
||||||
'no-new-symbol': 2,
|
|
||||||
'no-new-wrappers': 2,
|
|
||||||
'no-obj-calls': 2,
|
|
||||||
'no-octal': 2,
|
|
||||||
'no-octal-escape': 2,
|
|
||||||
'no-path-concat': 2,
|
|
||||||
'no-proto': 2,
|
|
||||||
'no-redeclare': 2,
|
|
||||||
'no-regex-spaces': 2,
|
|
||||||
'no-return-assign': [2, 'except-parens'],
|
|
||||||
'no-self-assign': 2,
|
|
||||||
'no-self-compare': 2,
|
|
||||||
'no-sequences': 2,
|
|
||||||
'no-shadow-restricted-names': 2,
|
|
||||||
'no-spaced-func': 2,
|
|
||||||
'no-sparse-arrays': 2,
|
|
||||||
'no-this-before-super': 2,
|
|
||||||
'no-throw-literal': 2,
|
|
||||||
'no-trailing-spaces': 2,
|
|
||||||
'no-undef': 2,
|
|
||||||
'no-undef-init': 2,
|
|
||||||
'no-unexpected-multiline': 2,
|
|
||||||
'no-unmodified-loop-condition': 2,
|
|
||||||
'no-unneeded-ternary': [2, {
|
|
||||||
'defaultAssignment': false
|
|
||||||
}],
|
|
||||||
'no-unreachable': 2,
|
|
||||||
'no-unsafe-finally': 2,
|
|
||||||
'no-unused-vars': [2, {
|
|
||||||
'vars': 'all',
|
|
||||||
'args': 'none'
|
|
||||||
}],
|
|
||||||
'no-useless-call': 2,
|
|
||||||
'no-useless-computed-key': 2,
|
|
||||||
'no-useless-constructor': 2,
|
|
||||||
'no-useless-escape': 0,
|
|
||||||
'no-whitespace-before-property': 2,
|
|
||||||
'no-with': 2,
|
|
||||||
'one-var': [2, {
|
|
||||||
'initialized': 'never'
|
|
||||||
}],
|
|
||||||
'operator-linebreak': [2, 'after', {
|
|
||||||
'overrides': {
|
|
||||||
'?': 'before',
|
|
||||||
':': 'before'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
'padded-blocks': [2, 'never'],
|
|
||||||
'quotes': [2, 'single', {
|
|
||||||
'avoidEscape': true,
|
|
||||||
'allowTemplateLiterals': true
|
|
||||||
}],
|
|
||||||
'semi': [2, 'never'],
|
|
||||||
'semi-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'space-before-blocks': [2, 'always'],
|
|
||||||
'space-before-function-paren': [2, 'never'],
|
|
||||||
'space-in-parens': [2, 'never'],
|
|
||||||
'space-infix-ops': 2,
|
|
||||||
'space-unary-ops': [2, {
|
|
||||||
'words': true,
|
|
||||||
'nonwords': false
|
|
||||||
}],
|
|
||||||
'spaced-comment': [2, 'always', {
|
|
||||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
|
||||||
}],
|
|
||||||
'template-curly-spacing': [2, 'never'],
|
|
||||||
'use-isnan': 2,
|
|
||||||
'valid-typeof': 2,
|
|
||||||
'wrap-iife': [2, 'any'],
|
|
||||||
'yield-star-spacing': [2, 'both'],
|
|
||||||
'yoda': [2, 'never'],
|
|
||||||
'prefer-const': 2,
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
|
||||||
'object-curly-spacing': [2, 'always', {
|
|
||||||
objectsInObjects: false
|
|
||||||
}],
|
|
||||||
'array-bracket-spacing': [2, 'never']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
.prettierrc.js
|
||||||
|
.eslintrc.js
|
||||||
|
jest.config.js
|
||||||
|
vue.config.js
|
||||||
|
postcss.config.js
|
||||||
|
settings.js
|
|
@ -0,0 +1,8 @@
|
||||||
|
/** eslint-disable */
|
||||||
|
module.exports =
|
||||||
|
{
|
||||||
|
|
||||||
|
"endOfLine":"auto"
|
||||||
|
|
||||||
|
|
||||||
|
}
|
118
mock/article.js
118
mock/article.js
|
@ -1,51 +1,64 @@
|
||||||
import Mock from 'mockjs'
|
import Mock from "mockjs";
|
||||||
|
|
||||||
const List = []
|
const List = [];
|
||||||
const count = 100
|
const count = 100;
|
||||||
|
|
||||||
const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
|
const baseContent =
|
||||||
const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
|
'<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>';
|
||||||
|
const image_uri =
|
||||||
|
"https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3";
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
List.push(Mock.mock({
|
List.push(
|
||||||
id: '@increment',
|
Mock.mock({
|
||||||
timestamp: +Mock.Random.date('T'),
|
id: "@increment",
|
||||||
author: '@first',
|
timestamp: +Mock.Random.date("T"),
|
||||||
reviewer: '@first',
|
author: "@first",
|
||||||
title: '@title(5, 10)',
|
reviewer: "@first",
|
||||||
content_short: 'mock data',
|
title: "@title(5, 10)",
|
||||||
|
content_short: "mock data",
|
||||||
content: baseContent,
|
content: baseContent,
|
||||||
forecast: '@float(0, 100, 2, 2)',
|
forecast: "@float(0, 100, 2, 2)",
|
||||||
importance: '@integer(1, 3)',
|
importance: "@integer(1, 3)",
|
||||||
'type|1': ['CN', 'US', 'JP', 'EU'],
|
"type|1": ["CN", "US", "JP", "EU"],
|
||||||
'status|1': ['published', 'draft', 'deleted'],
|
"status|1": ["published", "draft", "deleted"],
|
||||||
display_time: '@datetime',
|
display_time: "@datetime",
|
||||||
comment_disabled: true,
|
comment_disabled: true,
|
||||||
pageviews: '@integer(300, 5000)',
|
pageviews: "@integer(300, 5000)",
|
||||||
image_uri,
|
image_uri,
|
||||||
platforms: ['a-platform']
|
platforms: ["a-platform"]
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
url: '/article/list',
|
url: "/article/list",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: config => {
|
response: config => {
|
||||||
const { importance, type, title, page = 1, limit = 20, sort } = config.query
|
const {
|
||||||
|
importance,
|
||||||
|
type,
|
||||||
|
title,
|
||||||
|
page = 1,
|
||||||
|
limit = 20,
|
||||||
|
sort
|
||||||
|
} = config.query;
|
||||||
|
|
||||||
let mockList = List.filter(item => {
|
let mockList = List.filter(item => {
|
||||||
if (importance && item.importance !== +importance) return false
|
if (importance && item.importance !== +importance) return false;
|
||||||
if (type && item.type !== type) return false
|
if (type && item.type !== type) return false;
|
||||||
if (title && item.title.indexOf(title) < 0) return false
|
if (title && item.title.indexOf(title) < 0) return false;
|
||||||
return true
|
return true;
|
||||||
})
|
});
|
||||||
|
|
||||||
if (sort === '-id') {
|
if (sort === "-id") {
|
||||||
mockList = mockList.reverse()
|
mockList = mockList.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
|
const pageList = mockList.filter(
|
||||||
|
(item, index) => index < limit * page && index >= limit * (page - 1)
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
|
@ -53,64 +66,63 @@ export default [
|
||||||
total: mockList.length,
|
total: mockList.length,
|
||||||
items: pageList
|
items: pageList
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
url: '/article/detail',
|
url: "/article/detail",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: config => {
|
response: config => {
|
||||||
const { id } = config.query
|
const { id } = config.query;
|
||||||
for (const article of List) {
|
for (const article of List) {
|
||||||
if (article.id === +id) {
|
if (article.id === +id) {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: article
|
data: article
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
url: '/article/pv',
|
url: "/article/pv",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: {
|
data: {
|
||||||
pvData: [
|
pvData: [
|
||||||
{ key: 'PC', pv: 1024 },
|
{ key: "PC", pv: 1024 },
|
||||||
{ key: 'mobile', pv: 1024 },
|
{ key: "mobile", pv: 1024 },
|
||||||
{ key: 'ios', pv: 1024 },
|
{ key: "ios", pv: 1024 },
|
||||||
{ key: 'android', pv: 1024 }
|
{ key: "android", pv: 1024 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
url: '/article/create',
|
url: "/article/create",
|
||||||
type: 'post',
|
type: "post",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: 'success'
|
data: "success"
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
url: '/article/update',
|
url: "/article/update",
|
||||||
type: 'post',
|
type: "post",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: 'success'
|
data: "success"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
];
|
||||||
]
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
import Mock from 'mockjs'
|
import Mock from "mockjs";
|
||||||
import { param2Obj } from '../src/utils'
|
import { param2Obj } from "../src/utils";
|
||||||
|
|
||||||
import user from './user'
|
import user from "./user";
|
||||||
import role from './role'
|
import role from "./role";
|
||||||
import article from './article'
|
import article from "./article";
|
||||||
import search from './remote-search'
|
import search from "./remote-search";
|
||||||
|
|
||||||
const mocks = [
|
const mocks = [...user, ...role, ...article, ...search];
|
||||||
...user,
|
|
||||||
...role,
|
|
||||||
...article,
|
|
||||||
...search
|
|
||||||
]
|
|
||||||
|
|
||||||
// for front mock
|
// for front mock
|
||||||
// please use it cautiously, it will redefine XMLHttpRequest,
|
// please use it cautiously, it will redefine XMLHttpRequest,
|
||||||
|
@ -19,38 +14,42 @@ const mocks = [
|
||||||
export function mockXHR() {
|
export function mockXHR() {
|
||||||
// mock patch
|
// mock patch
|
||||||
// https://github.com/nuysoft/Mock/issues/300
|
// https://github.com/nuysoft/Mock/issues/300
|
||||||
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send;
|
||||||
Mock.XHR.prototype.send = function() {
|
Mock.XHR.prototype.send = function() {
|
||||||
if (this.custom.xhr) {
|
if (this.custom.xhr) {
|
||||||
this.custom.xhr.withCredentials = this.withCredentials || false
|
this.custom.xhr.withCredentials = this.withCredentials || false;
|
||||||
|
|
||||||
if (this.responseType) {
|
if (this.responseType) {
|
||||||
this.custom.xhr.responseType = this.responseType
|
this.custom.xhr.responseType = this.responseType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.proxy_send(...arguments)
|
this.proxy_send(...arguments);
|
||||||
}
|
};
|
||||||
|
|
||||||
function XHR2ExpressReqWrap(respond) {
|
function XHR2ExpressReqWrap(respond) {
|
||||||
return function(options) {
|
return function(options) {
|
||||||
let result = null
|
let result = null;
|
||||||
if (respond instanceof Function) {
|
if (respond instanceof Function) {
|
||||||
const { body, type, url } = options
|
const { body, type, url } = options;
|
||||||
// https://expressjs.com/en/4x/api.html#req
|
// https://expressjs.com/en/4x/api.html#req
|
||||||
result = respond({
|
result = respond({
|
||||||
method: type,
|
method: type,
|
||||||
body: JSON.parse(body),
|
body: JSON.parse(body),
|
||||||
query: param2Obj(url)
|
query: param2Obj(url)
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
result = respond
|
result = respond;
|
||||||
}
|
|
||||||
return Mock.mock(result)
|
|
||||||
}
|
}
|
||||||
|
return Mock.mock(result);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const i of mocks) {
|
for (const i of mocks) {
|
||||||
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
|
Mock.mock(
|
||||||
|
new RegExp(i.url),
|
||||||
|
i.type || "get",
|
||||||
|
XHR2ExpressReqWrap(i.response)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,13 +57,15 @@ export function mockXHR() {
|
||||||
const responseFake = (url, type, respond) => {
|
const responseFake = (url, type, respond) => {
|
||||||
return {
|
return {
|
||||||
url: new RegExp(`/mock${url}`),
|
url: new RegExp(`/mock${url}`),
|
||||||
type: type || 'get',
|
type: type || "get",
|
||||||
response(req, res) {
|
response(req, res) {
|
||||||
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
res.json(
|
||||||
|
Mock.mock(respond instanceof Function ? respond(req, res) : respond)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
export default mocks.map(route => {
|
export default mocks.map(route => {
|
||||||
return responseFake(route.url, route.type, route.response)
|
return responseFake(route.url, route.type, route.response);
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,68 +1,76 @@
|
||||||
const chokidar = require('chokidar')
|
const chokidar = require("chokidar");
|
||||||
const bodyParser = require('body-parser')
|
const bodyParser = require("body-parser");
|
||||||
const chalk = require('chalk')
|
const chalk = require("chalk");
|
||||||
const path = require('path')
|
const path = require("path");
|
||||||
|
|
||||||
const mockDir = path.join(process.cwd(), 'mock')
|
const mockDir = path.join(process.cwd(), "mock");
|
||||||
|
|
||||||
function registerRoutes(app) {
|
function registerRoutes(app) {
|
||||||
let mockLastIndex
|
let mockLastIndex;
|
||||||
const { default: mocks } = require('./index.js')
|
const { default: mocks } = require("./index.js");
|
||||||
for (const mock of mocks) {
|
for (const mock of mocks) {
|
||||||
app[mock.type](mock.url, mock.response)
|
app[mock.type](mock.url, mock.response);
|
||||||
mockLastIndex = app._router.stack.length
|
mockLastIndex = app._router.stack.length;
|
||||||
}
|
}
|
||||||
const mockRoutesLength = Object.keys(mocks).length
|
const mockRoutesLength = Object.keys(mocks).length;
|
||||||
return {
|
return {
|
||||||
mockRoutesLength: mockRoutesLength,
|
mockRoutesLength: mockRoutesLength,
|
||||||
mockStartIndex: mockLastIndex - mockRoutesLength
|
mockStartIndex: mockLastIndex - mockRoutesLength
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function unregisterRoutes() {
|
function unregisterRoutes() {
|
||||||
Object.keys(require.cache).forEach(i => {
|
Object.keys(require.cache).forEach(i => {
|
||||||
if (i.includes(mockDir)) {
|
if (i.includes(mockDir)) {
|
||||||
delete require.cache[require.resolve(i)]
|
delete require.cache[require.resolve(i)];
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
// es6 polyfill
|
// es6 polyfill
|
||||||
require('@babel/register')
|
require("@babel/register");
|
||||||
|
|
||||||
// parse app.body
|
// parse app.body
|
||||||
// https://expressjs.com/en/4x/api.html#req.body
|
// https://expressjs.com/en/4x/api.html#req.body
|
||||||
app.use(bodyParser.json())
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({
|
app.use(
|
||||||
|
bodyParser.urlencoded({
|
||||||
extended: true
|
extended: true
|
||||||
}))
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const mockRoutes = registerRoutes(app)
|
const mockRoutes = registerRoutes(app);
|
||||||
var mockRoutesLength = mockRoutes.mockRoutesLength
|
var mockRoutesLength = mockRoutes.mockRoutesLength;
|
||||||
var mockStartIndex = mockRoutes.mockStartIndex
|
var mockStartIndex = mockRoutes.mockStartIndex;
|
||||||
|
|
||||||
// watch files, hot reload mock server
|
// watch files, hot reload mock server
|
||||||
chokidar.watch(mockDir, {
|
chokidar
|
||||||
|
.watch(mockDir, {
|
||||||
ignored: /mock-server/,
|
ignored: /mock-server/,
|
||||||
ignoreInitial: true
|
ignoreInitial: true
|
||||||
}).on('all', (event, path) => {
|
})
|
||||||
if (event === 'change' || event === 'add') {
|
.on("all", (event, path) => {
|
||||||
|
if (event === "change" || event === "add") {
|
||||||
try {
|
try {
|
||||||
// remove mock routes stack
|
// remove mock routes stack
|
||||||
app._router.stack.splice(mockStartIndex, mockRoutesLength)
|
app._router.stack.splice(mockStartIndex, mockRoutesLength);
|
||||||
|
|
||||||
// clear routes cache
|
// clear routes cache
|
||||||
unregisterRoutes()
|
unregisterRoutes();
|
||||||
|
|
||||||
const mockRoutes = registerRoutes(app)
|
const mockRoutes = registerRoutes(app);
|
||||||
mockRoutesLength = mockRoutes.mockRoutesLength
|
mockRoutesLength = mockRoutes.mockRoutesLength;
|
||||||
mockStartIndex = mockRoutes.mockStartIndex
|
mockStartIndex = mockRoutes.mockStartIndex;
|
||||||
|
|
||||||
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
console.log(
|
||||||
|
chalk.magentaBright(
|
||||||
|
`\n > Mock Server hot reload success! changed ${path}`
|
||||||
|
)
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(chalk.redBright(error))
|
console.log(chalk.redBright(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,51 +1,55 @@
|
||||||
import Mock from 'mockjs'
|
import Mock from "mockjs";
|
||||||
|
|
||||||
const NameList = []
|
const NameList = [];
|
||||||
const count = 100
|
const count = 100;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
NameList.push(Mock.mock({
|
NameList.push(
|
||||||
name: '@first'
|
Mock.mock({
|
||||||
}))
|
name: "@first"
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
NameList.push({ name: 'mock-Pan' })
|
NameList.push({ name: "mock-Pan" });
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// username search
|
// username search
|
||||||
{
|
{
|
||||||
url: '/search/user',
|
url: "/search/user",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: config => {
|
response: config => {
|
||||||
const { name } = config.query
|
const { name } = config.query;
|
||||||
const mockNameList = NameList.filter(item => {
|
const mockNameList = NameList.filter(item => {
|
||||||
const lowerCaseName = item.name.toLowerCase()
|
const lowerCaseName = item.name.toLowerCase();
|
||||||
return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
|
return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0);
|
||||||
})
|
});
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: { items: mockNameList }
|
data: { items: mockNameList }
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// transaction list
|
// transaction list
|
||||||
{
|
{
|
||||||
url: '/transaction/list',
|
url: "/transaction/list",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: {
|
data: {
|
||||||
total: 20,
|
total: 20,
|
||||||
'items|20': [{
|
"items|20": [
|
||||||
order_no: '@guid()',
|
{
|
||||||
timestamp: +Mock.Random.date('T'),
|
order_no: "@guid()",
|
||||||
username: '@name()',
|
timestamp: +Mock.Random.date("T"),
|
||||||
price: '@float(1000, 15000, 0, 2)',
|
username: "@name()",
|
||||||
'status|1': ['success', 'pending']
|
price: "@float(1000, 15000, 0, 2)",
|
||||||
}]
|
"status|1": ["success", "pending"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
];
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,98 +1,101 @@
|
||||||
import Mock from 'mockjs'
|
import Mock from "mockjs";
|
||||||
import { deepClone } from '../../src/utils/index.js'
|
import { deepClone } from "../../src/utils/index.js";
|
||||||
import { asyncRoutes, constantRoutes } from './routes.js'
|
import { asyncRoutes, constantRoutes } from "./routes.js";
|
||||||
|
|
||||||
const routes = deepClone([...constantRoutes, ...asyncRoutes])
|
const routes = deepClone([...constantRoutes, ...asyncRoutes]);
|
||||||
|
|
||||||
const roles = [
|
const roles = [
|
||||||
{
|
{
|
||||||
key: 'admin',
|
key: "admin",
|
||||||
name: 'admin',
|
name: "admin",
|
||||||
description: 'Super Administrator. Have access to view all pages.',
|
description: "Super Administrator. Have access to view all pages.",
|
||||||
routes: routes
|
routes: routes
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'editor',
|
key: "editor",
|
||||||
name: 'editor',
|
name: "editor",
|
||||||
description: 'Normal Editor. Can see all pages except permission page',
|
description: "Normal Editor. Can see all pages except permission page",
|
||||||
routes: routes.filter(i => i.path !== '/permission')// just a mock
|
routes: routes.filter(i => i.path !== "/permission") // just a mock
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'visitor',
|
key: "visitor",
|
||||||
name: 'visitor',
|
name: "visitor",
|
||||||
description: 'Just a visitor. Can only see the home page and the document page',
|
description:
|
||||||
routes: [{
|
"Just a visitor. Can only see the home page and the document page",
|
||||||
path: '',
|
routes: [
|
||||||
redirect: 'dashboard',
|
{
|
||||||
|
path: "",
|
||||||
|
redirect: "dashboard",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: "dashboard",
|
||||||
name: 'Dashboard',
|
name: "Dashboard",
|
||||||
meta: { title: 'dashboard', icon: 'dashboard' }
|
meta: { title: "dashboard", icon: "dashboard" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// mock get all routes form server
|
// mock get all routes form server
|
||||||
{
|
{
|
||||||
url: '/routes',
|
url: "/routes",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: routes
|
data: routes
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// mock get all roles form server
|
// mock get all roles form server
|
||||||
{
|
{
|
||||||
url: '/roles',
|
url: "/roles",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: roles
|
data: roles
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// add role
|
// add role
|
||||||
{
|
{
|
||||||
url: '/role',
|
url: "/role",
|
||||||
type: 'post',
|
type: "post",
|
||||||
response: {
|
response: {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: {
|
data: {
|
||||||
key: Mock.mock('@integer(300, 5000)')
|
key: Mock.mock("@integer(300, 5000)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// update role
|
// update role
|
||||||
{
|
{
|
||||||
url: '/role/[A-Za-z0-9]',
|
url: "/role/[A-Za-z0-9]",
|
||||||
type: 'put',
|
type: "put",
|
||||||
response: {
|
response: {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: {
|
data: {
|
||||||
status: 'success'
|
status: "success"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// delete role
|
// delete role
|
||||||
{
|
{
|
||||||
url: '/role/[A-Za-z0-9]',
|
url: "/role/[A-Za-z0-9]",
|
||||||
type: 'delete',
|
type: "delete",
|
||||||
response: {
|
response: {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: {
|
data: {
|
||||||
status: 'success'
|
status: "success"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
|
@ -2,524 +2,524 @@
|
||||||
|
|
||||||
export const constantRoutes = [
|
export const constantRoutes = [
|
||||||
{
|
{
|
||||||
path: '/redirect',
|
path: "/redirect",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/redirect/:path*',
|
path: "/redirect/:path*",
|
||||||
component: 'views/redirect/index'
|
component: "views/redirect/index"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: "/login",
|
||||||
component: 'views/login/index',
|
component: "views/login/index",
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth-redirect',
|
path: "/auth-redirect",
|
||||||
component: 'views/login/auth-redirect',
|
component: "views/login/auth-redirect",
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/404',
|
path: "/404",
|
||||||
component: 'views/error-page/404',
|
component: "views/error-page/404",
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/401',
|
path: "/401",
|
||||||
component: 'views/error-page/401',
|
component: "views/error-page/401",
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: "",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'dashboard',
|
redirect: "dashboard",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: "dashboard",
|
||||||
component: 'views/dashboard/index',
|
component: "views/dashboard/index",
|
||||||
name: 'Dashboard',
|
name: "Dashboard",
|
||||||
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
|
meta: { title: "Dashboard", icon: "dashboard", affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/documentation',
|
path: "/documentation",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/documentation/index',
|
component: "views/documentation/index",
|
||||||
name: 'Documentation',
|
name: "Documentation",
|
||||||
meta: { title: 'Documentation', icon: 'documentation', affix: true }
|
meta: { title: "Documentation", icon: "documentation", affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/guide',
|
path: "/guide",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/guide/index',
|
redirect: "/guide/index",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/guide/index',
|
component: "views/guide/index",
|
||||||
name: 'Guide',
|
name: "Guide",
|
||||||
meta: { title: 'Guide', icon: 'guide', noCache: true }
|
meta: { title: "Guide", icon: "guide", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
||||||
export const asyncRoutes = [
|
export const asyncRoutes = [
|
||||||
{
|
{
|
||||||
path: '/permission',
|
path: "/permission",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/permission/index',
|
redirect: "/permission/index",
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Permission',
|
title: "Permission",
|
||||||
icon: 'lock',
|
icon: "lock",
|
||||||
roles: ['admin', 'editor']
|
roles: ["admin", "editor"]
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'page',
|
path: "page",
|
||||||
component: 'views/permission/page',
|
component: "views/permission/page",
|
||||||
name: 'PagePermission',
|
name: "PagePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Page Permission',
|
title: "Page Permission",
|
||||||
roles: ['admin']
|
roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'directive',
|
path: "directive",
|
||||||
component: 'views/permission/directive',
|
component: "views/permission/directive",
|
||||||
name: 'DirectivePermission',
|
name: "DirectivePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Directive Permission'
|
title: "Directive Permission"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'role',
|
path: "role",
|
||||||
component: 'views/permission/role',
|
component: "views/permission/role",
|
||||||
name: 'RolePermission',
|
name: "RolePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Role Permission',
|
title: "Role Permission",
|
||||||
roles: ['admin']
|
roles: ["admin"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/icon',
|
path: "/icon",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/icons/index',
|
component: "views/icons/index",
|
||||||
name: 'Icons',
|
name: "Icons",
|
||||||
meta: { title: 'Icons', icon: 'icon', noCache: true }
|
meta: { title: "Icons", icon: "icon", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/components',
|
path: "/components",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'ComponentDemo',
|
name: "ComponentDemo",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Components',
|
title: "Components",
|
||||||
icon: 'component'
|
icon: "component"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'tinymce',
|
path: "tinymce",
|
||||||
component: 'views/components-demo/tinymce',
|
component: "views/components-demo/tinymce",
|
||||||
name: 'TinymceDemo',
|
name: "TinymceDemo",
|
||||||
meta: { title: 'Tinymce' }
|
meta: { title: "Tinymce" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'markdown',
|
path: "markdown",
|
||||||
component: 'views/components-demo/markdown',
|
component: "views/components-demo/markdown",
|
||||||
name: 'MarkdownDemo',
|
name: "MarkdownDemo",
|
||||||
meta: { title: 'Markdown' }
|
meta: { title: "Markdown" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'json-editor',
|
path: "json-editor",
|
||||||
component: 'views/components-demo/json-editor',
|
component: "views/components-demo/json-editor",
|
||||||
name: 'JsonEditorDemo',
|
name: "JsonEditorDemo",
|
||||||
meta: { title: 'Json Editor' }
|
meta: { title: "Json Editor" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'split-pane',
|
path: "split-pane",
|
||||||
component: 'views/components-demo/split-pane',
|
component: "views/components-demo/split-pane",
|
||||||
name: 'SplitpaneDemo',
|
name: "SplitpaneDemo",
|
||||||
meta: { title: 'SplitPane' }
|
meta: { title: "SplitPane" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'avatar-upload',
|
path: "avatar-upload",
|
||||||
component: 'views/components-demo/avatar-upload',
|
component: "views/components-demo/avatar-upload",
|
||||||
name: 'AvatarUploadDemo',
|
name: "AvatarUploadDemo",
|
||||||
meta: { title: 'Avatar Upload' }
|
meta: { title: "Avatar Upload" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dropzone',
|
path: "dropzone",
|
||||||
component: 'views/components-demo/dropzone',
|
component: "views/components-demo/dropzone",
|
||||||
name: 'DropzoneDemo',
|
name: "DropzoneDemo",
|
||||||
meta: { title: 'Dropzone' }
|
meta: { title: "Dropzone" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'sticky',
|
path: "sticky",
|
||||||
component: 'views/components-demo/sticky',
|
component: "views/components-demo/sticky",
|
||||||
name: 'StickyDemo',
|
name: "StickyDemo",
|
||||||
meta: { title: 'Sticky' }
|
meta: { title: "Sticky" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'count-to',
|
path: "count-to",
|
||||||
component: 'views/components-demo/count-to',
|
component: "views/components-demo/count-to",
|
||||||
name: 'CountToDemo',
|
name: "CountToDemo",
|
||||||
meta: { title: 'Count To' }
|
meta: { title: "Count To" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'mixin',
|
path: "mixin",
|
||||||
component: 'views/components-demo/mixin',
|
component: "views/components-demo/mixin",
|
||||||
name: 'ComponentMixinDemo',
|
name: "ComponentMixinDemo",
|
||||||
meta: { title: 'componentMixin' }
|
meta: { title: "componentMixin" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'back-to-top',
|
path: "back-to-top",
|
||||||
component: 'views/components-demo/back-to-top',
|
component: "views/components-demo/back-to-top",
|
||||||
name: 'BackToTopDemo',
|
name: "BackToTopDemo",
|
||||||
meta: { title: 'Back To Top' }
|
meta: { title: "Back To Top" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-dialog',
|
path: "drag-dialog",
|
||||||
component: 'views/components-demo/drag-dialog',
|
component: "views/components-demo/drag-dialog",
|
||||||
name: 'DragDialogDemo',
|
name: "DragDialogDemo",
|
||||||
meta: { title: 'Drag Dialog' }
|
meta: { title: "Drag Dialog" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-select',
|
path: "drag-select",
|
||||||
component: 'views/components-demo/drag-select',
|
component: "views/components-demo/drag-select",
|
||||||
name: 'DragSelectDemo',
|
name: "DragSelectDemo",
|
||||||
meta: { title: 'Drag Select' }
|
meta: { title: "Drag Select" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dnd-list',
|
path: "dnd-list",
|
||||||
component: 'views/components-demo/dnd-list',
|
component: "views/components-demo/dnd-list",
|
||||||
name: 'DndListDemo',
|
name: "DndListDemo",
|
||||||
meta: { title: 'Dnd List' }
|
meta: { title: "Dnd List" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-kanban',
|
path: "drag-kanban",
|
||||||
component: 'views/components-demo/drag-kanban',
|
component: "views/components-demo/drag-kanban",
|
||||||
name: 'DragKanbanDemo',
|
name: "DragKanbanDemo",
|
||||||
meta: { title: 'Drag Kanban' }
|
meta: { title: "Drag Kanban" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/charts',
|
path: "/charts",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'Charts',
|
name: "Charts",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Charts',
|
title: "Charts",
|
||||||
icon: 'chart'
|
icon: "chart"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'keyboard',
|
path: "keyboard",
|
||||||
component: 'views/charts/keyboard',
|
component: "views/charts/keyboard",
|
||||||
name: 'KeyboardChart',
|
name: "KeyboardChart",
|
||||||
meta: { title: 'Keyboard Chart', noCache: true }
|
meta: { title: "Keyboard Chart", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'line',
|
path: "line",
|
||||||
component: 'views/charts/line',
|
component: "views/charts/line",
|
||||||
name: 'LineChart',
|
name: "LineChart",
|
||||||
meta: { title: 'Line Chart', noCache: true }
|
meta: { title: "Line Chart", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'mixchart',
|
path: "mixchart",
|
||||||
component: 'views/charts/mixChart',
|
component: "views/charts/mixChart",
|
||||||
name: 'MixChart',
|
name: "MixChart",
|
||||||
meta: { title: 'Mix Chart', noCache: true }
|
meta: { title: "Mix Chart", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/nested',
|
path: "/nested",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/nested/menu1/menu1-1',
|
redirect: "/nested/menu1/menu1-1",
|
||||||
name: 'Nested',
|
name: "Nested",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Nested',
|
title: "Nested",
|
||||||
icon: 'nested'
|
icon: "nested"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1',
|
path: "menu1",
|
||||||
component: 'views/nested/menu1/index',
|
component: "views/nested/menu1/index",
|
||||||
name: 'Menu1',
|
name: "Menu1",
|
||||||
meta: { title: 'Menu1' },
|
meta: { title: "Menu1" },
|
||||||
redirect: '/nested/menu1/menu1-1',
|
redirect: "/nested/menu1/menu1-1",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1-1',
|
path: "menu1-1",
|
||||||
component: 'views/nested/menu1/menu1-1',
|
component: "views/nested/menu1/menu1-1",
|
||||||
name: 'Menu1-1',
|
name: "Menu1-1",
|
||||||
meta: { title: 'Menu1-1' }
|
meta: { title: "Menu1-1" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-2',
|
path: "menu1-2",
|
||||||
component: 'views/nested/menu1/menu1-2',
|
component: "views/nested/menu1/menu1-2",
|
||||||
name: 'Menu1-2',
|
name: "Menu1-2",
|
||||||
redirect: '/nested/menu1/menu1-2/menu1-2-1',
|
redirect: "/nested/menu1/menu1-2/menu1-2-1",
|
||||||
meta: { title: 'Menu1-2' },
|
meta: { title: "Menu1-2" },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1-2-1',
|
path: "menu1-2-1",
|
||||||
component: 'views/nested/menu1/menu1-2/menu1-2-1',
|
component: "views/nested/menu1/menu1-2/menu1-2-1",
|
||||||
name: 'Menu1-2-1',
|
name: "Menu1-2-1",
|
||||||
meta: { title: 'Menu1-2-1' }
|
meta: { title: "Menu1-2-1" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-2-2',
|
path: "menu1-2-2",
|
||||||
component: 'views/nested/menu1/menu1-2/menu1-2-2',
|
component: "views/nested/menu1/menu1-2/menu1-2-2",
|
||||||
name: 'Menu1-2-2',
|
name: "Menu1-2-2",
|
||||||
meta: { title: 'Menu1-2-2' }
|
meta: { title: "Menu1-2-2" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-3',
|
path: "menu1-3",
|
||||||
component: 'views/nested/menu1/menu1-3',
|
component: "views/nested/menu1/menu1-3",
|
||||||
name: 'Menu1-3',
|
name: "Menu1-3",
|
||||||
meta: { title: 'Menu1-3' }
|
meta: { title: "Menu1-3" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu2',
|
path: "menu2",
|
||||||
name: 'Menu2',
|
name: "Menu2",
|
||||||
component: 'views/nested/menu2/index',
|
component: "views/nested/menu2/index",
|
||||||
meta: { title: 'Menu2' }
|
meta: { title: "Menu2" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/example',
|
path: "/example",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/example/list',
|
redirect: "/example/list",
|
||||||
name: 'Example',
|
name: "Example",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Example',
|
title: "Example",
|
||||||
icon: 'example'
|
icon: "example"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: "create",
|
||||||
component: 'views/example/create',
|
component: "views/example/create",
|
||||||
name: 'CreateArticle',
|
name: "CreateArticle",
|
||||||
meta: { title: 'Create Article', icon: 'edit' }
|
meta: { title: "Create Article", icon: "edit" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'edit/:id(\\d+)',
|
path: "edit/:id(\\d+)",
|
||||||
component: 'views/example/edit',
|
component: "views/example/edit",
|
||||||
name: 'EditArticle',
|
name: "EditArticle",
|
||||||
meta: { title: 'Edit Article', noCache: true },
|
meta: { title: "Edit Article", noCache: true },
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: "list",
|
||||||
component: 'views/example/list',
|
component: "views/example/list",
|
||||||
name: 'ArticleList',
|
name: "ArticleList",
|
||||||
meta: { title: 'Article List', icon: 'list' }
|
meta: { title: "Article List", icon: "list" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/tab',
|
path: "/tab",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/tab/index',
|
component: "views/tab/index",
|
||||||
name: 'Tab',
|
name: "Tab",
|
||||||
meta: { title: 'Tab', icon: 'tab' }
|
meta: { title: "Tab", icon: "tab" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/error',
|
path: "/error",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'ErrorPages',
|
name: "ErrorPages",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Error Pages',
|
title: "Error Pages",
|
||||||
icon: '404'
|
icon: "404"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '401',
|
path: "401",
|
||||||
component: 'views/error-page/401',
|
component: "views/error-page/401",
|
||||||
name: 'Page401',
|
name: "Page401",
|
||||||
meta: { title: 'Page 401', noCache: true }
|
meta: { title: "Page 401", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '404',
|
path: "404",
|
||||||
component: 'views/error-page/404',
|
component: "views/error-page/404",
|
||||||
name: 'Page404',
|
name: "Page404",
|
||||||
meta: { title: 'Page 404', noCache: true }
|
meta: { title: "Page 404", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/error-log',
|
path: "/error-log",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'log',
|
path: "log",
|
||||||
component: 'views/error-log/index',
|
component: "views/error-log/index",
|
||||||
name: 'ErrorLog',
|
name: "ErrorLog",
|
||||||
meta: { title: 'Error Log', icon: 'bug' }
|
meta: { title: "Error Log", icon: "bug" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/excel',
|
path: "/excel",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/excel/export-excel',
|
redirect: "/excel/export-excel",
|
||||||
name: 'Excel',
|
name: "Excel",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Excel',
|
title: "Excel",
|
||||||
icon: 'excel'
|
icon: "excel"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'export-excel',
|
path: "export-excel",
|
||||||
component: 'views/excel/export-excel',
|
component: "views/excel/export-excel",
|
||||||
name: 'ExportExcel',
|
name: "ExportExcel",
|
||||||
meta: { title: 'Export Excel' }
|
meta: { title: "Export Excel" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'export-selected-excel',
|
path: "export-selected-excel",
|
||||||
component: 'views/excel/select-excel',
|
component: "views/excel/select-excel",
|
||||||
name: 'SelectExcel',
|
name: "SelectExcel",
|
||||||
meta: { title: 'Select Excel' }
|
meta: { title: "Select Excel" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'export-merge-header',
|
path: "export-merge-header",
|
||||||
component: 'views/excel/merge-header',
|
component: "views/excel/merge-header",
|
||||||
name: 'MergeHeader',
|
name: "MergeHeader",
|
||||||
meta: { title: 'Merge Header' }
|
meta: { title: "Merge Header" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'upload-excel',
|
path: "upload-excel",
|
||||||
component: 'views/excel/upload-excel',
|
component: "views/excel/upload-excel",
|
||||||
name: 'UploadExcel',
|
name: "UploadExcel",
|
||||||
meta: { title: 'Upload Excel' }
|
meta: { title: "Upload Excel" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/zip',
|
path: "/zip",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/zip/download',
|
redirect: "/zip/download",
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
meta: { title: 'Zip', icon: 'zip' },
|
meta: { title: "Zip", icon: "zip" },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'download',
|
path: "download",
|
||||||
component: 'views/zip/index',
|
component: "views/zip/index",
|
||||||
name: 'ExportZip',
|
name: "ExportZip",
|
||||||
meta: { title: 'Export Zip' }
|
meta: { title: "Export Zip" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/pdf',
|
path: "/pdf",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: '/pdf/index',
|
redirect: "/pdf/index",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/pdf/index',
|
component: "views/pdf/index",
|
||||||
name: 'PDF',
|
name: "PDF",
|
||||||
meta: { title: 'PDF', icon: 'pdf' }
|
meta: { title: "PDF", icon: "pdf" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/pdf/download',
|
path: "/pdf/download",
|
||||||
component: 'views/pdf/download',
|
component: "views/pdf/download",
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/theme',
|
path: "/theme",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/theme/index',
|
component: "views/theme/index",
|
||||||
name: 'Theme',
|
name: "Theme",
|
||||||
meta: { title: 'Theme', icon: 'theme' }
|
meta: { title: "Theme", icon: "theme" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/clipboard',
|
path: "/clipboard",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/clipboard/index',
|
component: "views/clipboard/index",
|
||||||
name: 'ClipboardDemo',
|
name: "ClipboardDemo",
|
||||||
meta: { title: 'Clipboard Demo', icon: 'clipboard' }
|
meta: { title: "Clipboard Demo", icon: "clipboard" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/i18n',
|
path: "/i18n",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: 'views/i18n-demo/index',
|
component: "views/i18n-demo/index",
|
||||||
name: 'I18n',
|
name: "I18n",
|
||||||
meta: { title: 'I18n', icon: 'international' }
|
meta: { title: "I18n", icon: "international" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: 'external-link',
|
path: "external-link",
|
||||||
component: 'layout/Layout',
|
component: "layout/Layout",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'https://github.com/PanJiaChen/vue-element-admin',
|
path: "https://github.com/PanJiaChen/vue-element-admin",
|
||||||
meta: { title: 'External Link', icon: 'link' }
|
meta: { title: "External Link", icon: "link" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{ path: '*', redirect: '/404', hidden: true }
|
{ path: "*", redirect: "/404", hidden: true }
|
||||||
]
|
];
|
||||||
|
|
69
mock/user.js
69
mock/user.js
|
@ -1,84 +1,85 @@
|
||||||
|
|
||||||
const tokens = {
|
const tokens = {
|
||||||
admin: {
|
admin: {
|
||||||
token: 'admin-token'
|
token: "admin-token"
|
||||||
},
|
},
|
||||||
editor: {
|
editor: {
|
||||||
token: 'editor-token'
|
token: "editor-token"
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const users = {
|
const users = {
|
||||||
'admin-token': {
|
"admin-token": {
|
||||||
roles: ['admin'],
|
roles: ["admin"],
|
||||||
introduction: 'I am a super administrator',
|
introduction: "I am a super administrator",
|
||||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
avatar:
|
||||||
name: 'Super Admin'
|
"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
|
||||||
|
name: "Super Admin"
|
||||||
},
|
},
|
||||||
'editor-token': {
|
"editor-token": {
|
||||||
roles: ['editor'],
|
roles: ["editor"],
|
||||||
introduction: 'I am an editor',
|
introduction: "I am an editor",
|
||||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
avatar:
|
||||||
name: 'Normal Editor'
|
"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
|
||||||
|
name: "Normal Editor"
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
// user login
|
// user login
|
||||||
{
|
{
|
||||||
url: '/user/login',
|
url: "/user/login",
|
||||||
type: 'post',
|
type: "post",
|
||||||
response: config => {
|
response: config => {
|
||||||
const { username } = config.body
|
const { username } = config.body;
|
||||||
const token = tokens[username]
|
const token = tokens[username];
|
||||||
|
|
||||||
// mock error
|
// mock error
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return {
|
return {
|
||||||
code: 60204,
|
code: 60204,
|
||||||
message: 'Account and password are incorrect.'
|
message: "Account and password are incorrect."
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: token
|
data: token
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// get user info
|
// get user info
|
||||||
{
|
{
|
||||||
url: '/user/info\.*',
|
url: "/user/info.*",
|
||||||
type: 'get',
|
type: "get",
|
||||||
response: config => {
|
response: config => {
|
||||||
const { token } = config.query
|
const { token } = config.query;
|
||||||
const info = users[token]
|
const info = users[token];
|
||||||
|
|
||||||
// mock error
|
// mock error
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return {
|
return {
|
||||||
code: 50008,
|
code: 50008,
|
||||||
message: 'Login failed, unable to get user details.'
|
message: "Login failed, unable to get user details."
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: info
|
data: info
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// user logout
|
// user logout
|
||||||
{
|
{
|
||||||
url: '/user/logout',
|
url: "/user/logout",
|
||||||
type: 'post',
|
type: "post",
|
||||||
response: _ => {
|
response: _ => {
|
||||||
return {
|
return {
|
||||||
code: 20000,
|
code: 20000,
|
||||||
data: 'success'
|
data: "success"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
];
|
||||||
]
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||||
"test:ci": "npm run lint && npm run test:unit",
|
"test:ci": "npm run lint && npm run test:unit",
|
||||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||||
|
"format": "prettier \"./{src,tests,mock}/{**/*,*}.{ts,spec.ts,vue,js,spec.js}\" --write",
|
||||||
"new": "plop"
|
"new": "plop"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
|
@ -86,7 +87,8 @@
|
||||||
"chokidar": "2.1.5",
|
"chokidar": "2.1.5",
|
||||||
"connect": "3.6.6",
|
"connect": "3.6.6",
|
||||||
"eslint": "5.15.3",
|
"eslint": "5.15.3",
|
||||||
"eslint-plugin-vue": "5.2.2",
|
"eslint-config-prettier": "^4.3.0",
|
||||||
|
"eslint-plugin-vue": "^5.2.2",
|
||||||
"html-webpack-plugin": "3.2.0",
|
"html-webpack-plugin": "3.2.0",
|
||||||
"husky": "1.3.1",
|
"husky": "1.3.1",
|
||||||
"lint-staged": "8.1.5",
|
"lint-staged": "8.1.5",
|
||||||
|
|
|
@ -6,6 +6,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'App'
|
name: "App"
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
import request from '@/utils/request'
|
import request from "@/utils/request";
|
||||||
|
|
||||||
export function fetchList(query) {
|
export function fetchList(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/article/list',
|
url: "/article/list",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: query
|
params: query
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchArticle(id) {
|
export function fetchArticle(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/article/detail',
|
url: "/article/detail",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { id }
|
params: { id }
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchPv(pv) {
|
export function fetchPv(pv) {
|
||||||
return request({
|
return request({
|
||||||
url: '/article/pv',
|
url: "/article/pv",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { pv }
|
params: { pv }
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createArticle(data) {
|
export function createArticle(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/article/create',
|
url: "/article/create",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data
|
data
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateArticle(data) {
|
export function updateArticle(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/article/update',
|
url: "/article/update",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data
|
data
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import request from '@/utils/request'
|
import request from "@/utils/request";
|
||||||
|
|
||||||
export function getToken() {
|
export function getToken() {
|
||||||
return request({
|
return request({
|
||||||
url: '/qiniu/upload/token', // 假地址 自行替换
|
url: "/qiniu/upload/token", // 假地址 自行替换
|
||||||
method: 'get'
|
method: "get"
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import request from '@/utils/request'
|
import request from "@/utils/request";
|
||||||
|
|
||||||
export function searchUser(name) {
|
export function searchUser(name) {
|
||||||
return request({
|
return request({
|
||||||
url: '/search/user',
|
url: "/search/user",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { name }
|
params: { name }
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transactionList(query) {
|
export function transactionList(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/transaction/list',
|
url: "/transaction/list",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: query
|
params: query
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
import request from '@/utils/request'
|
import request from "@/utils/request";
|
||||||
|
|
||||||
export function getRoutes() {
|
export function getRoutes() {
|
||||||
return request({
|
return request({
|
||||||
url: '/routes',
|
url: "/routes",
|
||||||
method: 'get'
|
method: "get"
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRoles() {
|
export function getRoles() {
|
||||||
return request({
|
return request({
|
||||||
url: '/roles',
|
url: "/roles",
|
||||||
method: 'get'
|
method: "get"
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addRole(data) {
|
export function addRole(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/role',
|
url: "/role",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data
|
data
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateRole(id, data) {
|
export function updateRole(id, data) {
|
||||||
return request({
|
return request({
|
||||||
url: `/role/${id}`,
|
url: `/role/${id}`,
|
||||||
method: 'put',
|
method: "put",
|
||||||
data
|
data
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteRole(id) {
|
export function deleteRole(id) {
|
||||||
return request({
|
return request({
|
||||||
url: `/role/${id}`,
|
url: `/role/${id}`,
|
||||||
method: 'delete'
|
method: "delete"
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import request from '@/utils/request'
|
import request from "@/utils/request";
|
||||||
|
|
||||||
export function login(data) {
|
export function login(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/login',
|
url: "/user/login",
|
||||||
method: 'post',
|
method: "post",
|
||||||
data
|
data
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInfo(token) {
|
export function getInfo(token) {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/info',
|
url: "/user/info",
|
||||||
method: 'get',
|
method: "get",
|
||||||
params: { token }
|
params: { token }
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/logout',
|
url: "/user/logout",
|
||||||
method: 'post'
|
method: "post"
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
<transition :name="transitionName">
|
<transition :name="transitionName">
|
||||||
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
|
<div
|
||||||
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height:16px;width:16px"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></svg>
|
v-show="visible"
|
||||||
|
:style="customStyle"
|
||||||
|
class="back-to-ceiling"
|
||||||
|
@click="backToTop"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 17 17"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="Icon Icon--backToTopArrow"
|
||||||
|
aria-hidden="true"
|
||||||
|
style="height:16px;width:16px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'BackToTop',
|
name: "BackToTop",
|
||||||
props: {
|
props: {
|
||||||
visibilityHeight: {
|
visibilityHeight: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -22,19 +39,19 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: function() {
|
default: function() {
|
||||||
return {
|
return {
|
||||||
right: '50px',
|
right: "50px",
|
||||||
bottom: '50px',
|
bottom: "50px",
|
||||||
width: '40px',
|
width: "40px",
|
||||||
height: '40px',
|
height: "40px",
|
||||||
'border-radius': '4px',
|
"border-radius": "4px",
|
||||||
'line-height': '45px',
|
"line-height": "45px",
|
||||||
background: '#e7eaf1'
|
background: "#e7eaf1"
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
transitionName: {
|
transitionName: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'fade'
|
default: "fade"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -42,44 +59,44 @@ export default {
|
||||||
visible: false,
|
visible: false,
|
||||||
interval: null,
|
interval: null,
|
||||||
isMoving: false
|
isMoving: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
window.addEventListener('scroll', this.handleScroll)
|
window.addEventListener("scroll", this.handleScroll);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('scroll', this.handleScroll)
|
window.removeEventListener("scroll", this.handleScroll);
|
||||||
if (this.interval) {
|
if (this.interval) {
|
||||||
clearInterval(this.interval)
|
clearInterval(this.interval);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll() {
|
handleScroll() {
|
||||||
this.visible = window.pageYOffset > this.visibilityHeight
|
this.visible = window.pageYOffset > this.visibilityHeight;
|
||||||
},
|
},
|
||||||
backToTop() {
|
backToTop() {
|
||||||
if (this.isMoving) return
|
if (this.isMoving) return;
|
||||||
const start = window.pageYOffset
|
const start = window.pageYOffset;
|
||||||
let i = 0
|
let i = 0;
|
||||||
this.isMoving = true
|
this.isMoving = true;
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500));
|
||||||
if (next <= this.backPosition) {
|
if (next <= this.backPosition) {
|
||||||
window.scrollTo(0, this.backPosition)
|
window.scrollTo(0, this.backPosition);
|
||||||
clearInterval(this.interval)
|
clearInterval(this.interval);
|
||||||
this.isMoving = false
|
this.isMoving = false;
|
||||||
} else {
|
} else {
|
||||||
window.scrollTo(0, next)
|
window.scrollTo(0, next);
|
||||||
}
|
}
|
||||||
i++
|
i++;
|
||||||
}, 16.7)
|
}, 16.7);
|
||||||
},
|
},
|
||||||
easeInOutQuad(t, b, c, d) {
|
easeInOutQuad(t, b, c, d) {
|
||||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b
|
if ((t /= d / 2) < 1) return (c / 2) * t * t + b;
|
||||||
return -c / 2 * (--t * (t - 2) - 1) + b
|
return (-c / 2) * (--t * (t - 2) - 1) + b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -96,12 +113,12 @@ export default {
|
||||||
|
|
||||||
.fade-enter-active,
|
.fade-enter-active,
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
transition: opacity .5s;
|
transition: opacity 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter,
|
.fade-enter,
|
||||||
.fade-leave-to {
|
.fade-leave-to {
|
||||||
opacity: 0
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-ceiling .Icon {
|
.back-to-ceiling .Icon {
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||||
<transition-group name="breadcrumb">
|
<transition-group name="breadcrumb">
|
||||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
|
||||||
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
<span
|
||||||
|
v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
|
||||||
|
class="no-redirect"
|
||||||
|
>{{ item.meta.title }}</span
|
||||||
|
>
|
||||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
|
@ -10,61 +14,69 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import pathToRegexp from 'path-to-regexp'
|
import pathToRegexp from "path-to-regexp";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
levelList: null
|
levelList: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
$route(route) {
|
$route(route) {
|
||||||
// if you go to the redirect page, do not update the breadcrumbs
|
// if you go to the redirect page, do not update the breadcrumbs
|
||||||
if (route.path.startsWith('/redirect/')) {
|
if (route.path.startsWith("/redirect/")) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.getBreadcrumb()
|
this.getBreadcrumb();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getBreadcrumb()
|
this.getBreadcrumb();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getBreadcrumb() {
|
getBreadcrumb() {
|
||||||
// only show routes with meta.title
|
// only show routes with meta.title
|
||||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
let matched = this.$route.matched.filter(
|
||||||
const first = matched[0]
|
item => item.meta && item.meta.title
|
||||||
|
);
|
||||||
|
const first = matched[0];
|
||||||
|
|
||||||
if (!this.isDashboard(first)) {
|
if (!this.isDashboard(first)) {
|
||||||
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
|
matched = [{ path: "/dashboard", meta: { title: "Dashboard" } }].concat(
|
||||||
|
matched
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
this.levelList = matched.filter(
|
||||||
|
item => item.meta && item.meta.title && item.meta.breadcrumb !== false
|
||||||
|
);
|
||||||
},
|
},
|
||||||
isDashboard(route) {
|
isDashboard(route) {
|
||||||
const name = route && route.name
|
const name = route && route.name;
|
||||||
if (!name) {
|
if (!name) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
return (
|
||||||
|
name.trim().toLocaleLowerCase() === "Dashboard".toLocaleLowerCase()
|
||||||
|
);
|
||||||
},
|
},
|
||||||
pathCompile(path) {
|
pathCompile(path) {
|
||||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||||
const { params } = this.$route
|
const { params } = this.$route;
|
||||||
var toPath = pathToRegexp.compile(path)
|
var toPath = pathToRegexp.compile(path);
|
||||||
return toPath(params)
|
return toPath(params);
|
||||||
},
|
},
|
||||||
handleLink(item) {
|
handleLink(item) {
|
||||||
const { redirect, path } = item
|
const { redirect, path } = item;
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
this.$router.push(redirect)
|
this.$router.push(redirect);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.$router.push(this.pathCompile(path))
|
this.$router.push(this.pathCompile(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -1,78 +1,88 @@
|
||||||
<template>
|
<template>
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
<div :id="id" :class="className" :style="{ height: height, width: width }" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import echarts from "echarts";
|
||||||
import resize from './mixins/resize'
|
import resize from "./mixins/resize";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [resize],
|
mixins: [resize],
|
||||||
props: {
|
props: {
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null
|
chart: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initChart()
|
this.initChart();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (!this.chart) {
|
if (!this.chart) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.chart.dispose()
|
this.chart.dispose();
|
||||||
this.chart = null
|
this.chart = null;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initChart() {
|
initChart() {
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
this.chart = echarts.init(document.getElementById(this.id));
|
||||||
|
|
||||||
const xAxisData = []
|
const xAxisData = [];
|
||||||
const data = []
|
const data = [];
|
||||||
const data2 = []
|
const data2 = [];
|
||||||
for (let i = 0; i < 50; i++) {
|
for (let i = 0; i < 50; i++) {
|
||||||
xAxisData.push(i)
|
xAxisData.push(i);
|
||||||
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
|
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5);
|
||||||
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
|
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3);
|
||||||
}
|
}
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
backgroundColor: '#08263a',
|
backgroundColor: "#08263a",
|
||||||
grid: {
|
grid: {
|
||||||
left: '5%',
|
left: "5%",
|
||||||
right: '5%'
|
right: "5%"
|
||||||
},
|
},
|
||||||
xAxis: [{
|
xAxis: [
|
||||||
|
{
|
||||||
show: false,
|
show: false,
|
||||||
data: xAxisData
|
data: xAxisData
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
show: false,
|
show: false,
|
||||||
data: xAxisData
|
data: xAxisData
|
||||||
}],
|
}
|
||||||
|
],
|
||||||
visualMap: {
|
visualMap: {
|
||||||
show: false,
|
show: false,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 50,
|
max: 50,
|
||||||
dimension: 0,
|
dimension: 0,
|
||||||
inRange: {
|
inRange: {
|
||||||
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
color: [
|
||||||
|
"#4a657a",
|
||||||
|
"#308e92",
|
||||||
|
"#b1cfa5",
|
||||||
|
"#f5d69f",
|
||||||
|
"#f5898b",
|
||||||
|
"#ef5055"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
|
@ -81,22 +91,23 @@ export default {
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#4a657a'
|
color: "#4a657a"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: true,
|
show: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#08263f'
|
color: "#08263f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
series: [{
|
series: [
|
||||||
name: 'back',
|
{
|
||||||
type: 'bar',
|
name: "back",
|
||||||
|
type: "bar",
|
||||||
data: data2,
|
data: data2,
|
||||||
z: 1,
|
z: 1,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
|
@ -104,33 +115,35 @@ export default {
|
||||||
opacity: 0.4,
|
opacity: 0.4,
|
||||||
barBorderRadius: 5,
|
barBorderRadius: 5,
|
||||||
shadowBlur: 3,
|
shadowBlur: 3,
|
||||||
shadowColor: '#111'
|
shadowColor: "#111"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
name: 'Simulate Shadow',
|
{
|
||||||
type: 'line',
|
name: "Simulate Shadow",
|
||||||
|
type: "line",
|
||||||
data,
|
data,
|
||||||
z: 2,
|
z: 2,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
animationDelay: 0,
|
animationDelay: 0,
|
||||||
animationEasing: 'linear',
|
animationEasing: "linear",
|
||||||
animationDuration: 1200,
|
animationDuration: 1200,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'transparent'
|
color: "transparent"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: '#08263a',
|
color: "#08263a",
|
||||||
shadowBlur: 50,
|
shadowBlur: 50,
|
||||||
shadowColor: '#000'
|
shadowColor: "#000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
name: 'front',
|
{
|
||||||
type: 'bar',
|
name: "front",
|
||||||
|
type: "bar",
|
||||||
data,
|
data,
|
||||||
xAxisIndex: 1,
|
xAxisIndex: 1,
|
||||||
z: 3,
|
z: 3,
|
||||||
|
@ -139,17 +152,18 @@ export default {
|
||||||
barBorderRadius: 5
|
barBorderRadius: 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}],
|
}
|
||||||
animationEasing: 'elasticOut',
|
],
|
||||||
animationEasingUpdate: 'elasticOut',
|
animationEasing: "elasticOut",
|
||||||
|
animationEasingUpdate: "elasticOut",
|
||||||
animationDelay(idx) {
|
animationDelay(idx) {
|
||||||
return idx * 20
|
return idx * 20;
|
||||||
},
|
},
|
||||||
animationDelayUpdate(idx) {
|
animationDelayUpdate(idx) {
|
||||||
return idx * 20
|
return idx * 20;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,109 +1,125 @@
|
||||||
<template>
|
<template>
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
<div :id="id" :class="className" :style="{ height: height, width: width }" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import echarts from "echarts";
|
||||||
import resize from './mixins/resize'
|
import resize from "./mixins/resize";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [resize],
|
mixins: [resize],
|
||||||
props: {
|
props: {
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null
|
chart: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initChart()
|
this.initChart();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (!this.chart) {
|
if (!this.chart) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.chart.dispose()
|
this.chart.dispose();
|
||||||
this.chart = null
|
this.chart = null;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initChart() {
|
initChart() {
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
this.chart = echarts.init(document.getElementById(this.id));
|
||||||
|
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
backgroundColor: '#394056',
|
backgroundColor: "#394056",
|
||||||
title: {
|
title: {
|
||||||
top: 20,
|
top: 20,
|
||||||
text: 'Requests',
|
text: "Requests",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontWeight: 'normal',
|
fontWeight: "normal",
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#F1F1F3'
|
color: "#F1F1F3"
|
||||||
},
|
},
|
||||||
left: '1%'
|
left: "1%"
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: "axis",
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#57617B'
|
color: "#57617B"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
top: 20,
|
top: 20,
|
||||||
icon: 'rect',
|
icon: "rect",
|
||||||
itemWidth: 14,
|
itemWidth: 14,
|
||||||
itemHeight: 5,
|
itemHeight: 5,
|
||||||
itemGap: 13,
|
itemGap: 13,
|
||||||
data: ['CMCC', 'CTCC', 'CUCC'],
|
data: ["CMCC", "CTCC", "CUCC"],
|
||||||
right: '4%',
|
right: "4%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#F1F1F3'
|
color: "#F1F1F3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 100,
|
top: 100,
|
||||||
left: '2%',
|
left: "2%",
|
||||||
right: '2%',
|
right: "2%",
|
||||||
bottom: '2%',
|
bottom: "2%",
|
||||||
containLabel: true
|
containLabel: true
|
||||||
},
|
},
|
||||||
xAxis: [{
|
xAxis: [
|
||||||
type: 'category',
|
{
|
||||||
|
type: "category",
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#57617B'
|
color: "#57617B"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
|
data: [
|
||||||
}],
|
"13:00",
|
||||||
yAxis: [{
|
"13:05",
|
||||||
type: 'value',
|
"13:10",
|
||||||
name: '(%)',
|
"13:15",
|
||||||
|
"13:20",
|
||||||
|
"13:25",
|
||||||
|
"13:30",
|
||||||
|
"13:35",
|
||||||
|
"13:40",
|
||||||
|
"13:45",
|
||||||
|
"13:50",
|
||||||
|
"13:55"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: "value",
|
||||||
|
name: "(%)",
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#57617B'
|
color: "#57617B"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
|
@ -114,15 +130,17 @@ export default {
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#57617B'
|
color: "#57617B"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}],
|
}
|
||||||
series: [{
|
],
|
||||||
name: 'CMCC',
|
series: [
|
||||||
type: 'line',
|
{
|
||||||
|
name: "CMCC",
|
||||||
|
type: "line",
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'circle',
|
symbol: "circle",
|
||||||
symbolSize: 5,
|
symbolSize: 5,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
@ -132,31 +150,41 @@ export default {
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
offset: 0,
|
offset: 0,
|
||||||
color: 'rgba(137, 189, 27, 0.3)'
|
color: "rgba(137, 189, 27, 0.3)"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
offset: 0.8,
|
offset: 0.8,
|
||||||
color: 'rgba(137, 189, 27, 0)'
|
color: "rgba(137, 189, 27, 0)"
|
||||||
}], false),
|
}
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
],
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shadowColor: "rgba(0, 0, 0, 0.1)",
|
||||||
shadowBlur: 10
|
shadowBlur: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgb(137,189,27)',
|
color: "rgb(137,189,27)",
|
||||||
borderColor: 'rgba(137,189,2,0.27)',
|
borderColor: "rgba(137,189,2,0.27)",
|
||||||
borderWidth: 12
|
borderWidth: 12
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
||||||
}, {
|
},
|
||||||
name: 'CTCC',
|
{
|
||||||
type: 'line',
|
name: "CTCC",
|
||||||
|
type: "line",
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'circle',
|
symbol: "circle",
|
||||||
symbolSize: 5,
|
symbolSize: 5,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
@ -166,31 +194,41 @@ export default {
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
offset: 0,
|
offset: 0,
|
||||||
color: 'rgba(0, 136, 212, 0.3)'
|
color: "rgba(0, 136, 212, 0.3)"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
offset: 0.8,
|
offset: 0.8,
|
||||||
color: 'rgba(0, 136, 212, 0)'
|
color: "rgba(0, 136, 212, 0)"
|
||||||
}], false),
|
}
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
],
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shadowColor: "rgba(0, 0, 0, 0.1)",
|
||||||
shadowBlur: 10
|
shadowBlur: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgb(0,136,212)',
|
color: "rgb(0,136,212)",
|
||||||
borderColor: 'rgba(0,136,212,0.2)',
|
borderColor: "rgba(0,136,212,0.2)",
|
||||||
borderWidth: 12
|
borderWidth: 12
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
||||||
}, {
|
},
|
||||||
name: 'CUCC',
|
{
|
||||||
type: 'line',
|
name: "CUCC",
|
||||||
|
type: "line",
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'circle',
|
symbol: "circle",
|
||||||
symbolSize: 5,
|
symbolSize: 5,
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
|
@ -200,28 +238,39 @@ export default {
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
color: new echarts.graphic.LinearGradient(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
{
|
||||||
offset: 0,
|
offset: 0,
|
||||||
color: 'rgba(219, 50, 51, 0.3)'
|
color: "rgba(219, 50, 51, 0.3)"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
offset: 0.8,
|
offset: 0.8,
|
||||||
color: 'rgba(219, 50, 51, 0)'
|
color: "rgba(219, 50, 51, 0)"
|
||||||
}], false),
|
}
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
],
|
||||||
|
false
|
||||||
|
),
|
||||||
|
shadowColor: "rgba(0, 0, 0, 0.1)",
|
||||||
shadowBlur: 10
|
shadowBlur: 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgb(219,50,51)',
|
color: "rgb(219,50,51)",
|
||||||
borderColor: 'rgba(219,50,51,0.2)',
|
borderColor: "rgba(219,50,51,0.2)",
|
||||||
borderWidth: 12
|
borderWidth: 12
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
||||||
}]
|
}
|
||||||
})
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,103 +1,104 @@
|
||||||
<template>
|
<template>
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
<div :id="id" :class="className" :style="{ height: height, width: width }" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import echarts from "echarts";
|
||||||
import resize from './mixins/resize'
|
import resize from "./mixins/resize";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [resize],
|
mixins: [resize],
|
||||||
props: {
|
props: {
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'chart'
|
default: "chart"
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '200px'
|
default: "200px"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null
|
chart: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initChart()
|
this.initChart();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (!this.chart) {
|
if (!this.chart) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.chart.dispose()
|
this.chart.dispose();
|
||||||
this.chart = null
|
this.chart = null;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initChart() {
|
initChart() {
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
this.chart = echarts.init(document.getElementById(this.id));
|
||||||
const xData = (function() {
|
const xData = (function() {
|
||||||
const data = []
|
const data = [];
|
||||||
for (let i = 1; i < 13; i++) {
|
for (let i = 1; i < 13; i++) {
|
||||||
data.push(i + 'month')
|
data.push(i + "month");
|
||||||
}
|
}
|
||||||
return data
|
return data;
|
||||||
}())
|
})();
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
backgroundColor: '#344b58',
|
backgroundColor: "#344b58",
|
||||||
title: {
|
title: {
|
||||||
text: 'statistics',
|
text: "statistics",
|
||||||
x: '20',
|
x: "20",
|
||||||
top: '20',
|
top: "20",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff',
|
color: "#fff",
|
||||||
fontSize: '22'
|
fontSize: "22"
|
||||||
},
|
},
|
||||||
subtextStyle: {
|
subtextStyle: {
|
||||||
color: '#90979c',
|
color: "#90979c",
|
||||||
fontSize: '16'
|
fontSize: "16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: "axis",
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff'
|
color: "#fff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: '5%',
|
left: "5%",
|
||||||
right: '5%',
|
right: "5%",
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
top: 150,
|
top: 150,
|
||||||
bottom: 95,
|
bottom: 95,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff'
|
color: "#fff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
x: '5%',
|
x: "5%",
|
||||||
top: '10%',
|
top: "10%",
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#90979c'
|
color: "#90979c"
|
||||||
},
|
},
|
||||||
data: ['female', 'male', 'average']
|
data: ["female", "male", "average"]
|
||||||
},
|
},
|
||||||
calculable: true,
|
calculable: true,
|
||||||
xAxis: [{
|
xAxis: [
|
||||||
type: 'category',
|
{
|
||||||
|
type: "category",
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#90979c'
|
color: "#90979c"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
|
@ -111,18 +112,19 @@ export default {
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
interval: 0
|
interval: 0
|
||||||
|
|
||||||
},
|
},
|
||||||
data: xData
|
data: xData
|
||||||
}],
|
}
|
||||||
yAxis: [{
|
],
|
||||||
type: 'value',
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: "value",
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#90979c'
|
color: "#90979c"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
|
@ -134,50 +136,53 @@ export default {
|
||||||
splitArea: {
|
splitArea: {
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
}],
|
}
|
||||||
dataZoom: [{
|
],
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
show: true,
|
show: true,
|
||||||
height: 30,
|
height: 30,
|
||||||
xAxisIndex: [
|
xAxisIndex: [0],
|
||||||
0
|
|
||||||
],
|
|
||||||
bottom: 30,
|
bottom: 30,
|
||||||
start: 10,
|
start: 10,
|
||||||
end: 80,
|
end: 80,
|
||||||
handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
|
handleIcon:
|
||||||
handleSize: '110%',
|
"path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z",
|
||||||
|
handleSize: "110%",
|
||||||
handleStyle: {
|
handleStyle: {
|
||||||
color: '#d3dee5'
|
color: "#d3dee5"
|
||||||
|
|
||||||
},
|
},
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff' },
|
color: "#fff"
|
||||||
borderColor: '#90979c'
|
},
|
||||||
|
borderColor: "#90979c"
|
||||||
}, {
|
},
|
||||||
type: 'inside',
|
{
|
||||||
|
type: "inside",
|
||||||
show: true,
|
show: true,
|
||||||
height: 15,
|
height: 15,
|
||||||
start: 1,
|
start: 1,
|
||||||
end: 35
|
end: 35
|
||||||
}],
|
}
|
||||||
series: [{
|
],
|
||||||
name: 'female',
|
series: [
|
||||||
type: 'bar',
|
{
|
||||||
stack: 'total',
|
name: "female",
|
||||||
|
type: "bar",
|
||||||
|
stack: "total",
|
||||||
barMaxWidth: 35,
|
barMaxWidth: 35,
|
||||||
barGap: '10%',
|
barGap: "10%",
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgba(255,144,128,1)',
|
color: "rgba(255,144,128,1)",
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#fff'
|
color: "#fff"
|
||||||
},
|
},
|
||||||
position: 'insideTop',
|
position: "insideTop",
|
||||||
formatter(p) {
|
formatter(p) {
|
||||||
return p.value > 0 ? p.value : ''
|
return p.value > 0 ? p.value : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,18 +204,18 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'male',
|
name: "male",
|
||||||
type: 'bar',
|
type: "bar",
|
||||||
stack: 'total',
|
stack: "total",
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgba(0,191,183,1)',
|
color: "rgba(0,191,183,1)",
|
||||||
barBorderRadius: 0,
|
barBorderRadius: 0,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: 'top',
|
position: "top",
|
||||||
formatter(p) {
|
formatter(p) {
|
||||||
return p.value > 0 ? p.value : ''
|
return p.value > 0 ? p.value : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,21 +234,22 @@ export default {
|
||||||
381,
|
381,
|
||||||
220
|
220
|
||||||
]
|
]
|
||||||
}, {
|
},
|
||||||
name: 'average',
|
{
|
||||||
type: 'line',
|
name: "average",
|
||||||
stack: 'total',
|
type: "line",
|
||||||
|
stack: "total",
|
||||||
symbolSize: 10,
|
symbolSize: 10,
|
||||||
symbol: 'circle',
|
symbol: "circle",
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
color: 'rgba(252,230,48,1)',
|
color: "rgba(252,230,48,1)",
|
||||||
barBorderRadius: 0,
|
barBorderRadius: 0,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: 'top',
|
position: "top",
|
||||||
formatter(p) {
|
formatter(p) {
|
||||||
return p.value > 0 ? p.value : ''
|
return p.value > 0 ? p.value : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,8 +270,8 @@ export default {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,34 +1,42 @@
|
||||||
import { debounce } from '@/utils'
|
import { debounce } from "@/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
$_sidebarElm: null
|
$_sidebarElm: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.__resizeHandler = debounce(() => {
|
this.__resizeHandler = debounce(() => {
|
||||||
if (this.chart) {
|
if (this.chart) {
|
||||||
this.chart.resize()
|
this.chart.resize();
|
||||||
}
|
}
|
||||||
}, 100)
|
}, 100);
|
||||||
window.addEventListener('resize', this.__resizeHandler)
|
window.addEventListener("resize", this.__resizeHandler);
|
||||||
|
|
||||||
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
this.$_sidebarElm = document.getElementsByClassName("sidebar-container")[0];
|
||||||
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
this.$_sidebarElm &&
|
||||||
|
this.$_sidebarElm.addEventListener(
|
||||||
|
"transitionend",
|
||||||
|
this.$_sidebarResizeHandler
|
||||||
|
);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('resize', this.__resizeHandler)
|
window.removeEventListener("resize", this.__resizeHandler);
|
||||||
|
|
||||||
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
this.$_sidebarElm &&
|
||||||
|
this.$_sidebarElm.removeEventListener(
|
||||||
|
"transitionend",
|
||||||
|
this.$_sidebarResizeHandler
|
||||||
|
);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// use $_ for mixins properties
|
// use $_ for mixins properties
|
||||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||||
$_sidebarResizeHandler(e) {
|
$_sidebarResizeHandler(e) {
|
||||||
if (e.propertyName === 'width') {
|
if (e.propertyName === "width") {
|
||||||
this.__resizeHandler()
|
this.__resizeHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,24 +1,40 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dndList">
|
<div class="dndList">
|
||||||
<div :style="{width:width1}" class="dndList-list">
|
<div :style="{ width: width1 }" class="dndList-list">
|
||||||
<h3>{{ list1Title }}</h3>
|
<h3>{{ list1Title }}</h3>
|
||||||
<draggable :set-data="setData" :list="list1" group="article" class="dragArea">
|
<draggable
|
||||||
<div v-for="element in list1" :key="element.id" class="list-complete-item">
|
:set-data="setData"
|
||||||
|
:list="list1"
|
||||||
|
group="article"
|
||||||
|
class="dragArea"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="element in list1"
|
||||||
|
:key="element.id"
|
||||||
|
class="list-complete-item"
|
||||||
|
>
|
||||||
<div class="list-complete-item-handle">
|
<div class="list-complete-item-handle">
|
||||||
{{ element.id }}[{{ element.author }}] {{ element.title }}
|
{{ element.id }}[{{ element.author }}] {{ element.title }}
|
||||||
</div>
|
</div>
|
||||||
<div style="position:absolute;right:0px;">
|
<div style="position:absolute;right:0px;">
|
||||||
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
|
<span
|
||||||
|
style="float: right ;margin-top: -20px;margin-right:5px;"
|
||||||
|
@click="deleteEle(element)"
|
||||||
|
>
|
||||||
<i style="color:#ff4949" class="el-icon-delete" />
|
<i style="color:#ff4949" class="el-icon-delete" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</draggable>
|
</draggable>
|
||||||
</div>
|
</div>
|
||||||
<div :style="{width:width2}" class="dndList-list">
|
<div :style="{ width: width2 }" class="dndList-list">
|
||||||
<h3>{{ list2Title }}</h3>
|
<h3>{{ list2Title }}</h3>
|
||||||
<draggable :list="list2" group="article" class="dragArea">
|
<draggable :list="list2" group="article" class="dragArea">
|
||||||
<div v-for="element in list2" :key="element.id" class="list-complete-item">
|
<div
|
||||||
|
v-for="element in list2"
|
||||||
|
:key="element.id"
|
||||||
|
class="list-complete-item"
|
||||||
|
>
|
||||||
<div class="list-complete-item-handle2" @click="pushEle(element)">
|
<div class="list-complete-item-handle2" @click="pushEle(element)">
|
||||||
{{ element.id }} [{{ element.author }}] {{ element.title }}
|
{{ element.id }} [{{ element.author }}] {{ element.title }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,79 +45,79 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from "vuedraggable";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DndList',
|
name: "DndList",
|
||||||
components: { draggable },
|
components: { draggable },
|
||||||
props: {
|
props: {
|
||||||
list1: {
|
list1: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
default() {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list2: {
|
list2: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
default() {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list1Title: {
|
list1Title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'list1'
|
default: "list1"
|
||||||
},
|
},
|
||||||
list2Title: {
|
list2Title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'list2'
|
default: "list2"
|
||||||
},
|
},
|
||||||
width1: {
|
width1: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '48%'
|
default: "48%"
|
||||||
},
|
},
|
||||||
width2: {
|
width2: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '48%'
|
default: "48%"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isNotInList1(v) {
|
isNotInList1(v) {
|
||||||
return this.list1.every(k => v.id !== k.id)
|
return this.list1.every(k => v.id !== k.id);
|
||||||
},
|
},
|
||||||
isNotInList2(v) {
|
isNotInList2(v) {
|
||||||
return this.list2.every(k => v.id !== k.id)
|
return this.list2.every(k => v.id !== k.id);
|
||||||
},
|
},
|
||||||
deleteEle(ele) {
|
deleteEle(ele) {
|
||||||
for (const item of this.list1) {
|
for (const item of this.list1) {
|
||||||
if (item.id === ele.id) {
|
if (item.id === ele.id) {
|
||||||
const index = this.list1.indexOf(item)
|
const index = this.list1.indexOf(item);
|
||||||
this.list1.splice(index, 1)
|
this.list1.splice(index, 1);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.isNotInList2(ele)) {
|
if (this.isNotInList2(ele)) {
|
||||||
this.list2.unshift(ele)
|
this.list2.unshift(ele);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pushEle(ele) {
|
pushEle(ele) {
|
||||||
for (const item of this.list2) {
|
for (const item of this.list2) {
|
||||||
if (item.id === ele.id) {
|
if (item.id === ele.id) {
|
||||||
const index = this.list2.indexOf(item)
|
const index = this.list2.indexOf(item);
|
||||||
this.list2.splice(index, 1)
|
this.list2.splice(index, 1);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.isNotInList1(ele)) {
|
if (this.isNotInList1(ele)) {
|
||||||
this.list1.push(ele)
|
this.list1.push(ele);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setData(dataTransfer) {
|
setData(dataTransfer) {
|
||||||
// to avoid Firefox bug
|
// to avoid Firefox bug
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
dataTransfer.setData('Text', '')
|
dataTransfer.setData("Text", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -152,11 +168,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-complete-item.sortable-chosen {
|
.list-complete-item.sortable-chosen {
|
||||||
background: #4AB7BD;
|
background: #4ab7bd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-complete-item.sortable-ghost {
|
.list-complete-item.sortable-ghost {
|
||||||
background: #30B08F;
|
background: #30b08f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-complete-enter,
|
.list-complete-enter,
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
|
<el-select
|
||||||
|
ref="dragSelect"
|
||||||
|
v-model="selectVal"
|
||||||
|
v-bind="$attrs"
|
||||||
|
class="drag-select"
|
||||||
|
multiple
|
||||||
|
v-on="$listeners"
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Sortable from 'sortablejs'
|
import Sortable from "sortablejs";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DragSelect',
|
name: "DragSelect",
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -18,41 +25,43 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
selectVal: {
|
selectVal: {
|
||||||
get() {
|
get() {
|
||||||
return [...this.value]
|
return [...this.value];
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('input', [...val])
|
this.$emit("input", [...val]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setSort()
|
this.setSort();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setSort() {
|
setSort() {
|
||||||
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
|
const el = this.$refs.dragSelect.$el.querySelectorAll(
|
||||||
|
".el-select__tags > span"
|
||||||
|
)[0];
|
||||||
this.sortable = Sortable.create(el, {
|
this.sortable = Sortable.create(el, {
|
||||||
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
|
ghostClass: "sortable-ghost", // Class name for the drop placeholder,
|
||||||
setData: function(dataTransfer) {
|
setData: function(dataTransfer) {
|
||||||
dataTransfer.setData('Text', '')
|
dataTransfer.setData("Text", "");
|
||||||
// to avoid Firefox bug
|
// to avoid Firefox bug
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
},
|
},
|
||||||
onEnd: evt => {
|
onEnd: evt => {
|
||||||
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
|
const targetRow = this.value.splice(evt.oldIndex, 1)[0];
|
||||||
this.value.splice(evt.newIndex, 0, targetRow)
|
this.value.splice(evt.newIndex, 0, targetRow);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.drag-select >>> .sortable-ghost {
|
.drag-select >>> .sortable-ghost {
|
||||||
opacity: .8;
|
opacity: 0.8;
|
||||||
color: #fff!important;
|
color: #fff !important;
|
||||||
background: #42b983!important;
|
background: #42b983 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drag-select >>> .el-tag {
|
.drag-select >>> .el-tag {
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div :id="id" :ref="id" :action="url" class="dropzone">
|
<div :id="id" :ref="id" :action="url" class="dropzone">
|
||||||
<input type="file" name="file">
|
<input type="file" name="file" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Dropzone from 'dropzone'
|
import Dropzone from "dropzone";
|
||||||
import 'dropzone/dist/dropzone.css'
|
import "dropzone/dist/dropzone.css";
|
||||||
// import { getToken } from 'api/qiniu';
|
// import { getToken } from 'api/qiniu';
|
||||||
|
|
||||||
Dropzone.autoDiscover = false
|
Dropzone.autoDiscover = false;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
@ -27,11 +27,11 @@ export default {
|
||||||
},
|
},
|
||||||
defaultMsg: {
|
defaultMsg: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '上传图片'
|
default: "上传图片"
|
||||||
},
|
},
|
||||||
acceptedFiles: {
|
acceptedFiles: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
},
|
},
|
||||||
thumbnailHeight: {
|
thumbnailHeight: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -62,7 +62,7 @@ export default {
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
defaultImg: {
|
defaultImg: {
|
||||||
default: '',
|
default: "",
|
||||||
type: [String, Array]
|
type: [String, Array]
|
||||||
},
|
},
|
||||||
couldPaste: {
|
couldPaste: {
|
||||||
|
@ -72,58 +72,70 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dropzone: '',
|
dropzone: "",
|
||||||
initOnce: true
|
initOnce: true
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
defaultImg(val) {
|
defaultImg(val) {
|
||||||
if (val.length === 0) {
|
if (val.length === 0) {
|
||||||
this.initOnce = false
|
this.initOnce = false;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (!this.initOnce) return
|
if (!this.initOnce) return;
|
||||||
this.initImages(val)
|
this.initImages(val);
|
||||||
this.initOnce = false
|
this.initOnce = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const element = document.getElementById(this.id)
|
const element = document.getElementById(this.id);
|
||||||
const vm = this
|
const vm = this;
|
||||||
this.dropzone = new Dropzone(element, {
|
this.dropzone = new Dropzone(element, {
|
||||||
clickable: this.clickable,
|
clickable: this.clickable,
|
||||||
thumbnailWidth: this.thumbnailWidth,
|
thumbnailWidth: this.thumbnailWidth,
|
||||||
thumbnailHeight: this.thumbnailHeight,
|
thumbnailHeight: this.thumbnailHeight,
|
||||||
maxFiles: this.maxFiles,
|
maxFiles: this.maxFiles,
|
||||||
maxFilesize: this.maxFilesize,
|
maxFilesize: this.maxFilesize,
|
||||||
dictRemoveFile: 'Remove',
|
dictRemoveFile: "Remove",
|
||||||
addRemoveLinks: this.showRemoveLink,
|
addRemoveLinks: this.showRemoveLink,
|
||||||
acceptedFiles: this.acceptedFiles,
|
acceptedFiles: this.acceptedFiles,
|
||||||
autoProcessQueue: this.autoProcessQueue,
|
autoProcessQueue: this.autoProcessQueue,
|
||||||
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
|
dictDefaultMessage:
|
||||||
dictMaxFilesExceeded: '只能一个图',
|
'<i style="margin-top: 3em;display: inline-block" class="material-icons">' +
|
||||||
previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
|
this.defaultMsg +
|
||||||
|
"</i><br>Drop files here to upload",
|
||||||
|
dictMaxFilesExceeded: "只能一个图",
|
||||||
|
previewTemplate:
|
||||||
|
'<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' +
|
||||||
|
this.thumbnailWidth +
|
||||||
|
"px;height:" +
|
||||||
|
this.thumbnailHeight +
|
||||||
|
'px" ><img style="width:' +
|
||||||
|
this.thumbnailWidth +
|
||||||
|
"px;height:" +
|
||||||
|
this.thumbnailHeight +
|
||||||
|
'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
|
||||||
init() {
|
init() {
|
||||||
const val = vm.defaultImg
|
const val = vm.defaultImg;
|
||||||
if (!val) return
|
if (!val) return;
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
if (val.length === 0) return
|
if (val.length === 0) return;
|
||||||
val.map((v, i) => {
|
val.map((v, i) => {
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
const mockFile = { name: "name" + i, size: 12345, url: v };
|
||||||
this.options.addedfile.call(this, mockFile)
|
this.options.addedfile.call(this, mockFile);
|
||||||
this.options.thumbnail.call(this, mockFile, v)
|
this.options.thumbnail.call(this, mockFile, v);
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
mockFile.previewElement.classList.add("dz-success");
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
mockFile.previewElement.classList.add("dz-complete");
|
||||||
vm.initOnce = false
|
vm.initOnce = false;
|
||||||
return true
|
return true;
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
const mockFile = { name: 'name', size: 12345, url: val }
|
const mockFile = { name: "name", size: 12345, url: val };
|
||||||
this.options.addedfile.call(this, mockFile)
|
this.options.addedfile.call(this, mockFile);
|
||||||
this.options.thumbnail.call(this, mockFile, val)
|
this.options.thumbnail.call(this, mockFile, val);
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
mockFile.previewElement.classList.add("dz-success");
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
mockFile.previewElement.classList.add("dz-complete");
|
||||||
vm.initOnce = false
|
vm.initOnce = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
accept: (file, done) => {
|
accept: (file, done) => {
|
||||||
|
@ -135,136 +147,137 @@ export default {
|
||||||
// file.url = response.data.qiniu_url;
|
// file.url = response.data.qiniu_url;
|
||||||
// done();
|
// done();
|
||||||
// })
|
// })
|
||||||
done()
|
done();
|
||||||
},
|
},
|
||||||
sending: (file, xhr, formData) => {
|
sending: (file, xhr, formData) => {
|
||||||
// formData.append('token', file.token);
|
// formData.append('token', file.token);
|
||||||
// formData.append('key', file.key);
|
// formData.append('key', file.key);
|
||||||
vm.initOnce = false
|
vm.initOnce = false;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
if (this.couldPaste) {
|
if (this.couldPaste) {
|
||||||
document.addEventListener('paste', this.pasteImg)
|
document.addEventListener("paste", this.pasteImg);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dropzone.on('success', file => {
|
this.dropzone.on("success", file => {
|
||||||
vm.$emit('dropzone-success', file, vm.dropzone.element)
|
vm.$emit("dropzone-success", file, vm.dropzone.element);
|
||||||
})
|
});
|
||||||
this.dropzone.on('addedfile', file => {
|
this.dropzone.on("addedfile", file => {
|
||||||
vm.$emit('dropzone-fileAdded', file)
|
vm.$emit("dropzone-fileAdded", file);
|
||||||
})
|
});
|
||||||
this.dropzone.on('removedfile', file => {
|
this.dropzone.on("removedfile", file => {
|
||||||
vm.$emit('dropzone-removedFile', file)
|
vm.$emit("dropzone-removedFile", file);
|
||||||
})
|
});
|
||||||
this.dropzone.on('error', (file, error, xhr) => {
|
this.dropzone.on("error", (file, error, xhr) => {
|
||||||
vm.$emit('dropzone-error', file, error, xhr)
|
vm.$emit("dropzone-error", file, error, xhr);
|
||||||
})
|
});
|
||||||
this.dropzone.on('successmultiple', (file, error, xhr) => {
|
this.dropzone.on("successmultiple", (file, error, xhr) => {
|
||||||
vm.$emit('dropzone-successmultiple', file, error, xhr)
|
vm.$emit("dropzone-successmultiple", file, error, xhr);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
document.removeEventListener('paste', this.pasteImg)
|
document.removeEventListener("paste", this.pasteImg);
|
||||||
this.dropzone.destroy()
|
this.dropzone.destroy();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
removeAllFiles() {
|
removeAllFiles() {
|
||||||
this.dropzone.removeAllFiles(true)
|
this.dropzone.removeAllFiles(true);
|
||||||
},
|
},
|
||||||
processQueue() {
|
processQueue() {
|
||||||
this.dropzone.processQueue()
|
this.dropzone.processQueue();
|
||||||
},
|
},
|
||||||
pasteImg(event) {
|
pasteImg(event) {
|
||||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items
|
const items = (event.clipboardData || event.originalEvent.clipboardData)
|
||||||
if (items[0].kind === 'file') {
|
.items;
|
||||||
this.dropzone.addFile(items[0].getAsFile())
|
if (items[0].kind === "file") {
|
||||||
|
this.dropzone.addFile(items[0].getAsFile());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initImages(val) {
|
initImages(val) {
|
||||||
if (!val) return
|
if (!val) return;
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
val.map((v, i) => {
|
val.map((v, i) => {
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
const mockFile = { name: "name" + i, size: 12345, url: v };
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
this.dropzone.options.addedfile.call(this.dropzone, mockFile);
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
|
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v);
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
mockFile.previewElement.classList.add("dz-success");
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
mockFile.previewElement.classList.add("dz-complete");
|
||||||
return true
|
return true;
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
const mockFile = { name: 'name', size: 12345, url: val }
|
const mockFile = { name: "name", size: 12345, url: val };
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
this.dropzone.options.addedfile.call(this.dropzone, mockFile);
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
|
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val);
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
mockFile.previewElement.classList.add("dz-success");
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
mockFile.previewElement.classList.add("dz-complete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.dropzone {
|
.dropzone {
|
||||||
border: 2px solid #E5E5E5;
|
border: 2px solid #e5e5e5;
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: "Roboto", sans-serif;
|
||||||
color: #777;
|
color: #777;
|
||||||
transition: background-color .2s linear;
|
transition: background-color 0.2s linear;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone:hover {
|
.dropzone:hover {
|
||||||
background-color: #F6F6F6;
|
background-color: #f6f6f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
color: #CCC;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-image img {
|
.dropzone .dz-image img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone input[name='file'] {
|
.dropzone input[name="file"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-image {
|
.dropzone .dz-preview .dz-image {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-image img {
|
.dropzone .dz-preview:hover .dz-image img {
|
||||||
transform: none;
|
transform: none;
|
||||||
filter: none;
|
filter: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details {
|
.dropzone .dz-preview .dz-details {
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: rgba(33, 150, 243, 0.8);
|
background-color: rgba(33, 150, 243, 0.8);
|
||||||
transition: opacity .2s linear;
|
transition: opacity 0.2s linear;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
|
.dropzone .dz-preview .dz-details .dz-filename span,
|
||||||
|
.dropzone .dz-preview .dz-details .dz-size span {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
|
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename:hover span {
|
.dropzone .dz-preview .dz-details .dz-filename:hover span {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-remove {
|
.dropzone .dz-preview .dz-remove {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -279,19 +292,21 @@ export default {
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 1.1px;
|
letter-spacing: 1.1px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-remove {
|
.dropzone .dz-preview:hover .dz-remove {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
|
.dropzone .dz-preview .dz-success-mark,
|
||||||
|
.dropzone .dz-preview .dz-error-mark {
|
||||||
margin-left: -40px;
|
margin-left: -40px;
|
||||||
margin-top: -50px;
|
margin-top: -50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-success-mark i, .dropzone .dz-preview .dz-error-mark i {
|
.dropzone .dz-preview .dz-success-mark i,
|
||||||
|
.dropzone .dz-preview .dz-error-mark i {
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="errorLogs.length>0">
|
<div v-if="errorLogs.length > 0">
|
||||||
<el-badge :is-dot="true" style="line-height: 25px;margin-top: -5px;" @click.native="dialogTableVisible=true">
|
<el-badge
|
||||||
|
:is-dot="true"
|
||||||
|
style="line-height: 25px;margin-top: -5px;"
|
||||||
|
@click.native="dialogTableVisible = true"
|
||||||
|
>
|
||||||
<el-button style="padding: 8px 10px;" size="small" type="danger">
|
<el-button style="padding: 8px 10px;" size="small" type="danger">
|
||||||
<svg-icon icon-class="bug" />
|
<svg-icon icon-class="bug" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -9,27 +13,37 @@
|
||||||
<el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
|
<el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<span style="padding-right: 10px;">Error Log</span>
|
<span style="padding-right: 10px;">Error Log</span>
|
||||||
<el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</el-button>
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="clearAll"
|
||||||
|
>Clear All</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="errorLogs" border>
|
<el-table :data="errorLogs" border>
|
||||||
<el-table-column label="Message">
|
<el-table-column label="Message">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{ row }">
|
||||||
<div>
|
<div>
|
||||||
<span class="message-title">Msg:</span>
|
<span class="message-title">Msg:</span>
|
||||||
<el-tag type="danger">
|
<el-tag type="danger">
|
||||||
{{ row.err.message }}
|
{{ row.err.message }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br />
|
||||||
<div>
|
<div>
|
||||||
<span class="message-title" style="padding-right: 10px;">Info: </span>
|
<span class="message-title" style="padding-right: 10px;"
|
||||||
|
>Info:
|
||||||
|
</span>
|
||||||
<el-tag type="warning">
|
<el-tag type="warning">
|
||||||
{{ row.vm.$vnode.tag }} error in {{ row.info }}
|
{{ row.vm.$vnode.tag }} error in {{ row.info }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br />
|
||||||
<div>
|
<div>
|
||||||
<span class="message-title" style="padding-right: 16px;">Url: </span>
|
<span class="message-title" style="padding-right: 16px;"
|
||||||
|
>Url:
|
||||||
|
</span>
|
||||||
<el-tag type="success">
|
<el-tag type="success">
|
||||||
{{ row.url }}
|
{{ row.url }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
@ -48,24 +62,24 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ErrorLog',
|
name: "ErrorLog",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dialogTableVisible: false
|
dialogTableVisible: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
errorLogs() {
|
errorLogs() {
|
||||||
return this.$store.getters.errorLogs
|
return this.$store.getters.errorLogs;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clearAll() {
|
clearAll() {
|
||||||
this.dialogTableVisible = false
|
this.dialogTableVisible = false;
|
||||||
this.$store.dispatch('errorLog/clearErrorLog')
|
this.$store.dispatch("errorLog/clearErrorLog");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
|
<a
|
||||||
|
href="https://github.com/PanJiaChen/vue-element-admin"
|
||||||
|
target="_blank"
|
||||||
|
class="github-corner"
|
||||||
|
aria-label="View source on Github"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
width="80"
|
width="80"
|
||||||
height="80"
|
height="80"
|
||||||
|
@ -25,30 +30,30 @@
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.github-corner:hover .octo-arm {
|
.github-corner:hover .octo-arm {
|
||||||
animation: octocat-wave 560ms ease-in-out
|
animation: octocat-wave 560ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes octocat-wave {
|
@keyframes octocat-wave {
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
transform: rotate(0)
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
20%,
|
20%,
|
||||||
60% {
|
60% {
|
||||||
transform: rotate(-25deg)
|
transform: rotate(-25deg);
|
||||||
}
|
}
|
||||||
40%,
|
40%,
|
||||||
80% {
|
80% {
|
||||||
transform: rotate(10deg)
|
transform: rotate(10deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:500px) {
|
@media (max-width: 500px) {
|
||||||
.github-corner:hover .octo-arm {
|
.github-corner:hover .octo-arm {
|
||||||
animation: none
|
animation: none;
|
||||||
}
|
}
|
||||||
.github-corner .octo-arm {
|
.github-corner .octo-arm {
|
||||||
animation: octocat-wave 560ms ease-in-out
|
animation: octocat-wave 560ms ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="padding: 0 15px;" @click="toggleClick">
|
<div style="padding: 0 15px;" @click="toggleClick">
|
||||||
<svg
|
<svg
|
||||||
:class="{'is-active':isActive}"
|
:class="{ 'is-active': isActive }"
|
||||||
class="hamburger"
|
class="hamburger"
|
||||||
viewBox="0 0 1024 1024"
|
viewBox="0 0 1024 1024"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="64"
|
width="64"
|
||||||
height="64"
|
height="64"
|
||||||
>
|
>
|
||||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
<path
|
||||||
|
d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Hamburger',
|
name: "Hamburger",
|
||||||
props: {
|
props: {
|
||||||
isActive: {
|
isActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -24,10 +26,10 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleClick() {
|
toggleClick() {
|
||||||
this.$emit('toggleClick')
|
this.$emit("toggleClick");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{'show':show}" class="header-search">
|
<div :class="{ show: show }" class="header-search">
|
||||||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
<svg-icon
|
||||||
|
class-name="search-icon"
|
||||||
|
icon-class="search"
|
||||||
|
@click.stop="click"
|
||||||
|
/>
|
||||||
<el-select
|
<el-select
|
||||||
ref="headerSearchSelect"
|
ref="headerSearchSelect"
|
||||||
v-model="search"
|
v-model="search"
|
||||||
|
@ -12,7 +16,12 @@
|
||||||
class="header-search-select"
|
class="header-search-select"
|
||||||
@change="change"
|
@change="change"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
:key="item.path"
|
||||||
|
:value="item"
|
||||||
|
:label="item.title.join(' > ')"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -20,62 +29,62 @@
|
||||||
<script>
|
<script>
|
||||||
// fuse is a lightweight fuzzy-search module
|
// fuse is a lightweight fuzzy-search module
|
||||||
// make search results more in line with expectations
|
// make search results more in line with expectations
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from "fuse.js";
|
||||||
import path from 'path'
|
import path from "path";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HeaderSearch',
|
name: "HeaderSearch",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
search: '',
|
search: "",
|
||||||
options: [],
|
options: [],
|
||||||
searchPool: [],
|
searchPool: [],
|
||||||
show: false,
|
show: false,
|
||||||
fuse: undefined
|
fuse: undefined
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
routes() {
|
routes() {
|
||||||
return this.$store.getters.permission_routes
|
return this.$store.getters.permission_routes;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
routes() {
|
routes() {
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
this.searchPool = this.generateRoutes(this.routes);
|
||||||
},
|
},
|
||||||
searchPool(list) {
|
searchPool(list) {
|
||||||
this.initFuse(list)
|
this.initFuse(list);
|
||||||
},
|
},
|
||||||
show(value) {
|
show(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
document.body.addEventListener('click', this.close)
|
document.body.addEventListener("click", this.close);
|
||||||
} else {
|
} else {
|
||||||
document.body.removeEventListener('click', this.close)
|
document.body.removeEventListener("click", this.close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
this.searchPool = this.generateRoutes(this.routes);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
click() {
|
click() {
|
||||||
this.show = !this.show
|
this.show = !this.show;
|
||||||
if (this.show) {
|
if (this.show) {
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
|
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
|
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur();
|
||||||
this.options = []
|
this.options = [];
|
||||||
this.show = false
|
this.show = false;
|
||||||
},
|
},
|
||||||
change(val) {
|
change(val) {
|
||||||
this.$router.push(val.path)
|
this.$router.push(val.path);
|
||||||
this.search = ''
|
this.search = "";
|
||||||
this.options = []
|
this.options = [];
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.show = false
|
this.show = false;
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
initFuse(list) {
|
initFuse(list) {
|
||||||
this.fuse = new Fuse(list, {
|
this.fuse = new Fuse(list, {
|
||||||
|
@ -85,58 +94,67 @@ export default {
|
||||||
distance: 100,
|
distance: 100,
|
||||||
maxPatternLength: 32,
|
maxPatternLength: 32,
|
||||||
minMatchCharLength: 1,
|
minMatchCharLength: 1,
|
||||||
keys: [{
|
keys: [
|
||||||
name: 'title',
|
{
|
||||||
|
name: "title",
|
||||||
weight: 0.7
|
weight: 0.7
|
||||||
}, {
|
},
|
||||||
name: 'path',
|
{
|
||||||
|
name: "path",
|
||||||
weight: 0.3
|
weight: 0.3
|
||||||
}]
|
}
|
||||||
})
|
]
|
||||||
|
});
|
||||||
},
|
},
|
||||||
// Filter out the routes that can be displayed in the sidebar
|
// Filter out the routes that can be displayed in the sidebar
|
||||||
// And generate the internationalized title
|
// And generate the internationalized title
|
||||||
generateRoutes(routes, basePath = '/', prefixTitle = []) {
|
generateRoutes(routes, basePath = "/", prefixTitle = []) {
|
||||||
let res = []
|
let res = [];
|
||||||
|
|
||||||
for (const router of routes) {
|
for (const router of routes) {
|
||||||
// skip hidden router
|
// skip hidden router
|
||||||
if (router.hidden) { continue }
|
if (router.hidden) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
path: path.resolve(basePath, router.path),
|
path: path.resolve(basePath, router.path),
|
||||||
title: [...prefixTitle]
|
title: [...prefixTitle]
|
||||||
}
|
};
|
||||||
|
|
||||||
if (router.meta && router.meta.title) {
|
if (router.meta && router.meta.title) {
|
||||||
data.title = [...data.title, router.meta.title]
|
data.title = [...data.title, router.meta.title];
|
||||||
|
|
||||||
if (router.redirect !== 'noRedirect') {
|
if (router.redirect !== "noRedirect") {
|
||||||
// only push the routes with title
|
// only push the routes with title
|
||||||
// special case: need to exclude parent router without redirect
|
// special case: need to exclude parent router without redirect
|
||||||
res.push(data)
|
res.push(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursive child routes
|
// recursive child routes
|
||||||
if (router.children) {
|
if (router.children) {
|
||||||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
|
const tempRoutes = this.generateRoutes(
|
||||||
|
router.children,
|
||||||
|
data.path,
|
||||||
|
data.title
|
||||||
|
);
|
||||||
if (tempRoutes.length >= 1) {
|
if (tempRoutes.length >= 1) {
|
||||||
res = [...res, ...tempRoutes]
|
res = [...res, ...tempRoutes];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res
|
return res;
|
||||||
},
|
},
|
||||||
querySearch(query) {
|
querySearch(query) {
|
||||||
if (query !== '') {
|
if (query !== "") {
|
||||||
this.options = this.fuse.search(query)
|
this.options = this.fuse.search(query);
|
||||||
} else {
|
} else {
|
||||||
this.options = []
|
this.options = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -159,7 +177,7 @@ export default {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
/deep/ .el-input__inner {
|
::v-deep .el-input__inner {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,14 +6,14 @@
|
||||||
* @return {[blob]} [description]
|
* @return {[blob]} [description]
|
||||||
*/
|
*/
|
||||||
export default function(data, mime) {
|
export default function(data, mime) {
|
||||||
data = data.split(',')[1]
|
data = data.split(",")[1];
|
||||||
data = window.atob(data)
|
data = window.atob(data);
|
||||||
var ia = new Uint8Array(data.length)
|
var ia = new Uint8Array(data.length);
|
||||||
for (var i = 0; i < data.length; i++) {
|
for (var i = 0; i < data.length; i++) {
|
||||||
ia[i] = data.charCodeAt(i)
|
ia[i] = data.charCodeAt(i);
|
||||||
}
|
}
|
||||||
// canvas.toDataURL 返回的默认格式就是 image/png
|
// canvas.toDataURL 返回的默认格式就是 image/png
|
||||||
return new Blob([ia], {
|
return new Blob([ia], {
|
||||||
type: mime
|
type: mime
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,34 +6,48 @@
|
||||||
* @return {[bollean]} [description]
|
* @return {[bollean]} [description]
|
||||||
*/
|
*/
|
||||||
export default function(e, arg_opts) {
|
export default function(e, arg_opts) {
|
||||||
var opts = Object.assign({
|
var opts = Object.assign(
|
||||||
|
{
|
||||||
ele: e.target, // 波纹作用元素
|
ele: e.target, // 波纹作用元素
|
||||||
type: 'hit', // hit点击位置扩散center中心点扩展
|
type: "hit", // hit点击位置扩散center中心点扩展
|
||||||
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
bgc: "rgba(0, 0, 0, 0.15)" // 波纹颜色
|
||||||
}, arg_opts)
|
},
|
||||||
var target = opts.ele
|
arg_opts
|
||||||
|
);
|
||||||
|
var target = opts.ele;
|
||||||
if (target) {
|
if (target) {
|
||||||
var rect = target.getBoundingClientRect()
|
var rect = target.getBoundingClientRect();
|
||||||
var ripple = target.querySelector('.e-ripple')
|
var ripple = target.querySelector(".e-ripple");
|
||||||
if (!ripple) {
|
if (!ripple) {
|
||||||
ripple = document.createElement('span')
|
ripple = document.createElement("span");
|
||||||
ripple.className = 'e-ripple'
|
ripple.className = "e-ripple";
|
||||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
|
ripple.style.height = ripple.style.width =
|
||||||
target.appendChild(ripple)
|
Math.max(rect.width, rect.height) + "px";
|
||||||
|
target.appendChild(ripple);
|
||||||
} else {
|
} else {
|
||||||
ripple.className = 'e-ripple'
|
ripple.className = "e-ripple";
|
||||||
}
|
}
|
||||||
switch (opts.type) {
|
switch (opts.type) {
|
||||||
case 'center':
|
case "center":
|
||||||
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
|
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + "px";
|
||||||
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
|
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + "px";
|
||||||
break
|
break;
|
||||||
default:
|
default:
|
||||||
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
|
ripple.style.top =
|
||||||
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
|
e.pageY -
|
||||||
|
rect.top -
|
||||||
|
ripple.offsetHeight / 2 -
|
||||||
|
document.body.scrollTop +
|
||||||
|
"px";
|
||||||
|
ripple.style.left =
|
||||||
|
e.pageX -
|
||||||
|
rect.left -
|
||||||
|
ripple.offsetWidth / 2 -
|
||||||
|
document.body.scrollLeft +
|
||||||
|
"px";
|
||||||
}
|
}
|
||||||
ripple.style.backgroundColor = opts.bgc
|
ripple.style.backgroundColor = opts.bgc;
|
||||||
ripple.className = 'e-ripple z-active'
|
ripple.className = "e-ripple z-active";
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,232 +1,240 @@
|
||||||
export default {
|
export default {
|
||||||
zh: {
|
zh: {
|
||||||
hint: '点击,或拖动图片至此处',
|
hint: "点击,或拖动图片至此处",
|
||||||
loading: '正在上传……',
|
loading: "正在上传……",
|
||||||
noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
|
noSupported: "浏览器不支持该功能,请使用IE10以上或其他现在浏览器!",
|
||||||
success: '上传成功',
|
success: "上传成功",
|
||||||
fail: '图片上传失败',
|
fail: "图片上传失败",
|
||||||
preview: '头像预览',
|
preview: "头像预览",
|
||||||
btn: {
|
btn: {
|
||||||
off: '取消',
|
off: "取消",
|
||||||
close: '关闭',
|
close: "关闭",
|
||||||
back: '上一步',
|
back: "上一步",
|
||||||
save: '保存'
|
save: "保存"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: '仅限图片格式',
|
onlyImg: "仅限图片格式",
|
||||||
outOfSize: '单文件大小不能超过 ',
|
outOfSize: "单文件大小不能超过 ",
|
||||||
lowestPx: '图片最低像素为(宽*高):'
|
lowestPx: "图片最低像素为(宽*高):"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'zh-tw': {
|
"zh-tw": {
|
||||||
hint: '點擊,或拖動圖片至此處',
|
hint: "點擊,或拖動圖片至此處",
|
||||||
loading: '正在上傳……',
|
loading: "正在上傳……",
|
||||||
noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!',
|
noSupported: "瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!",
|
||||||
success: '上傳成功',
|
success: "上傳成功",
|
||||||
fail: '圖片上傳失敗',
|
fail: "圖片上傳失敗",
|
||||||
preview: '頭像預覽',
|
preview: "頭像預覽",
|
||||||
btn: {
|
btn: {
|
||||||
off: '取消',
|
off: "取消",
|
||||||
close: '關閉',
|
close: "關閉",
|
||||||
back: '上一步',
|
back: "上一步",
|
||||||
save: '保存'
|
save: "保存"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: '僅限圖片格式',
|
onlyImg: "僅限圖片格式",
|
||||||
outOfSize: '單文件大小不能超過 ',
|
outOfSize: "單文件大小不能超過 ",
|
||||||
lowestPx: '圖片最低像素為(寬*高):'
|
lowestPx: "圖片最低像素為(寬*高):"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
hint: 'Click or drag the file here to upload',
|
hint: "Click or drag the file here to upload",
|
||||||
loading: 'Uploading…',
|
loading: "Uploading…",
|
||||||
noSupported: 'Browser is not supported, please use IE10+ or other browsers',
|
noSupported: "Browser is not supported, please use IE10+ or other browsers",
|
||||||
success: 'Upload success',
|
success: "Upload success",
|
||||||
fail: 'Upload failed',
|
fail: "Upload failed",
|
||||||
preview: 'Preview',
|
preview: "Preview",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Cancel',
|
off: "Cancel",
|
||||||
close: 'Close',
|
close: "Close",
|
||||||
back: 'Back',
|
back: "Back",
|
||||||
save: 'Save'
|
save: "Save"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Image only',
|
onlyImg: "Image only",
|
||||||
outOfSize: 'Image exceeds size limit: ',
|
outOfSize: "Image exceeds size limit: ",
|
||||||
lowestPx: 'Image\'s size is too low. Expected at least: '
|
lowestPx: "Image's size is too low. Expected at least: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ro: {
|
ro: {
|
||||||
hint: 'Atinge sau trage fișierul aici',
|
hint: "Atinge sau trage fișierul aici",
|
||||||
loading: 'Se încarcă',
|
loading: "Se încarcă",
|
||||||
noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.',
|
noSupported:
|
||||||
success: 'S-a încărcat cu succes',
|
"Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.",
|
||||||
fail: 'A apărut o problemă la încărcare',
|
success: "S-a încărcat cu succes",
|
||||||
preview: 'Previzualizează',
|
fail: "A apărut o problemă la încărcare",
|
||||||
|
preview: "Previzualizează",
|
||||||
|
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Anulează',
|
off: "Anulează",
|
||||||
close: 'Închide',
|
close: "Închide",
|
||||||
back: 'Înapoi',
|
back: "Înapoi",
|
||||||
save: 'Salvează'
|
save: "Salvează"
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Doar imagini',
|
onlyImg: "Doar imagini",
|
||||||
outOfSize: 'Imaginea depășește limita de: ',
|
outOfSize: "Imaginea depășește limita de: ",
|
||||||
loewstPx: 'Imaginea este prea mică; Minim: '
|
loewstPx: "Imaginea este prea mică; Minim: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ru: {
|
ru: {
|
||||||
hint: 'Нажмите, или перетащите файл в это окно',
|
hint: "Нажмите, или перетащите файл в это окно",
|
||||||
loading: 'Загружаю……',
|
loading: "Загружаю……",
|
||||||
noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры',
|
noSupported:
|
||||||
success: 'Загрузка выполнена успешно',
|
"Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры",
|
||||||
fail: 'Ошибка загрузки',
|
success: "Загрузка выполнена успешно",
|
||||||
preview: 'Предпросмотр',
|
fail: "Ошибка загрузки",
|
||||||
|
preview: "Предпросмотр",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Отменить',
|
off: "Отменить",
|
||||||
close: 'Закрыть',
|
close: "Закрыть",
|
||||||
back: 'Назад',
|
back: "Назад",
|
||||||
save: 'Сохранить'
|
save: "Сохранить"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Только изображения',
|
onlyImg: "Только изображения",
|
||||||
outOfSize: 'Изображение превышает предельный размер: ',
|
outOfSize: "Изображение превышает предельный размер: ",
|
||||||
lowestPx: 'Минимальный размер изображения: '
|
lowestPx: "Минимальный размер изображения: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'pt-br': {
|
"pt-br": {
|
||||||
hint: 'Clique ou arraste o arquivo aqui para carregar',
|
hint: "Clique ou arraste o arquivo aqui para carregar",
|
||||||
loading: 'Carregando…',
|
loading: "Carregando…",
|
||||||
noSupported: 'Browser não suportado, use o IE10+ ou outro browser',
|
noSupported: "Browser não suportado, use o IE10+ ou outro browser",
|
||||||
success: 'Sucesso ao carregar imagem',
|
success: "Sucesso ao carregar imagem",
|
||||||
fail: 'Falha ao carregar imagem',
|
fail: "Falha ao carregar imagem",
|
||||||
preview: 'Pré-visualizar',
|
preview: "Pré-visualizar",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Cancelar',
|
off: "Cancelar",
|
||||||
close: 'Fechar',
|
close: "Fechar",
|
||||||
back: 'Voltar',
|
back: "Voltar",
|
||||||
save: 'Salvar'
|
save: "Salvar"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Apenas imagens',
|
onlyImg: "Apenas imagens",
|
||||||
outOfSize: 'A imagem excede o limite de tamanho: ',
|
outOfSize: "A imagem excede o limite de tamanho: ",
|
||||||
lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: '
|
lowestPx: "O tamanho da imagem é muito pequeno. Tamanho mínimo: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fr: {
|
fr: {
|
||||||
hint: 'Cliquez ou glissez le fichier ici.',
|
hint: "Cliquez ou glissez le fichier ici.",
|
||||||
loading: 'Téléchargement…',
|
loading: "Téléchargement…",
|
||||||
noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.',
|
noSupported:
|
||||||
success: 'Téléchargement réussit',
|
"Votre navigateur n'est pas supporté. Utilisez IE10 + ou un autre navigateur s'il vous plaît.",
|
||||||
fail: 'Téléchargement echoué',
|
success: "Téléchargement réussit",
|
||||||
preview: 'Aperçu',
|
fail: "Téléchargement echoué",
|
||||||
|
preview: "Aperçu",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Annuler',
|
off: "Annuler",
|
||||||
close: 'Fermer',
|
close: "Fermer",
|
||||||
back: 'Retour',
|
back: "Retour",
|
||||||
save: 'Enregistrer'
|
save: "Enregistrer"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Image uniquement',
|
onlyImg: "Image uniquement",
|
||||||
outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ',
|
outOfSize: "L'image sélectionnée dépasse la taille maximum: ",
|
||||||
lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: '
|
lowestPx: "L'image sélectionnée est trop petite. Dimensions attendues: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nl: {
|
nl: {
|
||||||
hint: 'Klik hier of sleep een afbeelding in dit vlak',
|
hint: "Klik hier of sleep een afbeelding in dit vlak",
|
||||||
loading: 'Uploaden…',
|
loading: "Uploaden…",
|
||||||
noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.',
|
noSupported:
|
||||||
success: 'Upload succesvol',
|
"Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.",
|
||||||
fail: 'Upload mislukt',
|
success: "Upload succesvol",
|
||||||
preview: 'Voorbeeld',
|
fail: "Upload mislukt",
|
||||||
|
preview: "Voorbeeld",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Annuleren',
|
off: "Annuleren",
|
||||||
close: 'Sluiten',
|
close: "Sluiten",
|
||||||
back: 'Terug',
|
back: "Terug",
|
||||||
save: 'Opslaan'
|
save: "Opslaan"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Alleen afbeeldingen',
|
onlyImg: "Alleen afbeeldingen",
|
||||||
outOfSize: 'De afbeelding is groter dan: ',
|
outOfSize: "De afbeelding is groter dan: ",
|
||||||
lowestPx: 'De afbeelding is te klein! Minimale afmetingen: '
|
lowestPx: "De afbeelding is te klein! Minimale afmetingen: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tr: {
|
tr: {
|
||||||
hint: 'Tıkla veya yüklemek istediğini buraya sürükle',
|
hint: "Tıkla veya yüklemek istediğini buraya sürükle",
|
||||||
loading: 'Yükleniyor…',
|
loading: "Yükleniyor…",
|
||||||
noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın',
|
noSupported:
|
||||||
success: 'Yükleme başarılı',
|
"Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın",
|
||||||
fail: 'Yüklemede hata oluştu',
|
success: "Yükleme başarılı",
|
||||||
preview: 'Önizle',
|
fail: "Yüklemede hata oluştu",
|
||||||
|
preview: "Önizle",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'İptal',
|
off: "İptal",
|
||||||
close: 'Kapat',
|
close: "Kapat",
|
||||||
back: 'Geri',
|
back: "Geri",
|
||||||
save: 'Kaydet'
|
save: "Kaydet"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Sadece resim',
|
onlyImg: "Sadece resim",
|
||||||
outOfSize: 'Resim yükleme limitini aşıyor: ',
|
outOfSize: "Resim yükleme limitini aşıyor: ",
|
||||||
lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: '
|
lowestPx: "Resmin boyutu çok küçük. En az olması gereken: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'es-MX': {
|
"es-MX": {
|
||||||
hint: 'Selecciona o arrastra una imagen',
|
hint: "Selecciona o arrastra una imagen",
|
||||||
loading: 'Subiendo...',
|
loading: "Subiendo...",
|
||||||
noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes',
|
noSupported:
|
||||||
success: 'Subido exitosamente',
|
"Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes",
|
||||||
fail: 'Sucedió un error',
|
success: "Subido exitosamente",
|
||||||
preview: 'Vista previa',
|
fail: "Sucedió un error",
|
||||||
|
preview: "Vista previa",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Cancelar',
|
off: "Cancelar",
|
||||||
close: 'Cerrar',
|
close: "Cerrar",
|
||||||
back: 'Atras',
|
back: "Atras",
|
||||||
save: 'Guardar'
|
save: "Guardar"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Unicamente imagenes',
|
onlyImg: "Unicamente imagenes",
|
||||||
outOfSize: 'La imagen excede el tamaño maximo:',
|
outOfSize: "La imagen excede el tamaño maximo:",
|
||||||
lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:'
|
lowestPx: "La imagen es demasiado pequeño. Se espera por lo menos:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen',
|
hint: "Klick hier oder zieh eine Datei hier rein zum Hochladen",
|
||||||
loading: 'Hochladen…',
|
loading: "Hochladen…",
|
||||||
noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser',
|
noSupported:
|
||||||
success: 'Upload erfolgreich',
|
"Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser",
|
||||||
fail: 'Upload fehlgeschlagen',
|
success: "Upload erfolgreich",
|
||||||
preview: 'Vorschau',
|
fail: "Upload fehlgeschlagen",
|
||||||
|
preview: "Vorschau",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'Abbrechen',
|
off: "Abbrechen",
|
||||||
close: 'Schließen',
|
close: "Schließen",
|
||||||
back: 'Zurück',
|
back: "Zurück",
|
||||||
save: 'Speichern'
|
save: "Speichern"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: 'Nur Bilder',
|
onlyImg: "Nur Bilder",
|
||||||
outOfSize: 'Das Bild ist zu groß: ',
|
outOfSize: "Das Bild ist zu groß: ",
|
||||||
lowestPx: 'Das Bild ist zu klein. Mindestens: '
|
lowestPx: "Das Bild ist zu klein. Mindestens: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ja: {
|
ja: {
|
||||||
hint: 'クリック・ドラッグしてファイルをアップロード',
|
hint: "クリック・ドラッグしてファイルをアップロード",
|
||||||
loading: 'アップロード中...',
|
loading: "アップロード中...",
|
||||||
noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。',
|
noSupported:
|
||||||
success: 'アップロード成功',
|
"このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。",
|
||||||
fail: 'アップロード失敗',
|
success: "アップロード成功",
|
||||||
preview: 'プレビュー',
|
fail: "アップロード失敗",
|
||||||
|
preview: "プレビュー",
|
||||||
btn: {
|
btn: {
|
||||||
off: 'キャンセル',
|
off: "キャンセル",
|
||||||
close: '閉じる',
|
close: "閉じる",
|
||||||
back: '戻る',
|
back: "戻る",
|
||||||
save: '保存'
|
save: "保存"
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
onlyImg: '画像のみ',
|
onlyImg: "画像のみ",
|
||||||
outOfSize: '画像サイズが上限を超えています。上限: ',
|
outOfSize: "画像サイズが上限を超えています。上限: ",
|
||||||
lowestPx: '画像が小さすぎます。最小サイズ: '
|
lowestPx: "画像が小さすぎます。最小サイズ: "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
'jpg': 'image/jpeg',
|
jpg: "image/jpeg",
|
||||||
'png': 'image/png',
|
png: "image/png",
|
||||||
'gif': 'image/gif',
|
gif: "image/gif",
|
||||||
'svg': 'image/svg+xml',
|
svg: "image/svg+xml",
|
||||||
'psd': 'image/photoshop'
|
psd: "image/photoshop"
|
||||||
}
|
};
|
||||||
|
|
|
@ -5,57 +5,57 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from "codemirror";
|
||||||
import 'codemirror/addon/lint/lint.css'
|
import "codemirror/addon/lint/lint.css";
|
||||||
import 'codemirror/lib/codemirror.css'
|
import "codemirror/lib/codemirror.css";
|
||||||
import 'codemirror/theme/rubyblue.css'
|
import "codemirror/theme/rubyblue.css";
|
||||||
require('script-loader!jsonlint')
|
require("script-loader!jsonlint");
|
||||||
import 'codemirror/mode/javascript/javascript'
|
import "codemirror/mode/javascript/javascript";
|
||||||
import 'codemirror/addon/lint/lint'
|
import "codemirror/addon/lint/lint";
|
||||||
import 'codemirror/addon/lint/json-lint'
|
import "codemirror/addon/lint/json-lint";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'JsonEditor',
|
name: "JsonEditor",
|
||||||
/* eslint-disable vue/require-prop-types */
|
/* eslint-disable vue/require-prop-types */
|
||||||
props: ['value'],
|
props: ["value"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
jsonEditor: false
|
jsonEditor: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(value) {
|
value(value) {
|
||||||
const editorValue = this.jsonEditor.getValue()
|
const editorValue = this.jsonEditor.getValue();
|
||||||
if (value !== editorValue) {
|
if (value !== editorValue) {
|
||||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
|
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: 'application/json',
|
mode: "application/json",
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
gutters: ["CodeMirror-lint-markers"],
|
||||||
theme: 'rubyblue',
|
theme: "rubyblue",
|
||||||
lint: true
|
lint: true
|
||||||
})
|
});
|
||||||
|
|
||||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
|
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
|
||||||
this.jsonEditor.on('change', cm => {
|
this.jsonEditor.on("change", cm => {
|
||||||
this.$emit('changed', cm.getValue())
|
this.$emit("changed", cm.getValue());
|
||||||
this.$emit('input', cm.getValue())
|
this.$emit("input", cm.getValue());
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getValue() {
|
getValue() {
|
||||||
return this.jsonEditor.getValue()
|
return this.jsonEditor.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.json-editor{
|
.json-editor {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ export default {
|
||||||
height: auto;
|
height: auto;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
.json-editor >>> .CodeMirror-scroll{
|
.json-editor >>> .CodeMirror-scroll {
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
.json-editor >>> .cm-s-rubyblue span.cm-string {
|
.json-editor >>> .cm-s-rubyblue span.cm-string {
|
||||||
color: #F08047;
|
color: #f08047;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,28 +17,28 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from "vuedraggable";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DragKanbanDemo',
|
name: "DragKanbanDemo",
|
||||||
components: {
|
components: {
|
||||||
draggable
|
draggable
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
headerText: {
|
headerText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'Header'
|
default: "Header"
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default() {
|
default() {
|
||||||
return {}
|
return {};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
default() {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -46,10 +46,10 @@ export default {
|
||||||
setData(dataTransfer) {
|
setData(dataTransfer) {
|
||||||
// to avoid Firefox bug
|
// to avoid Firefox bug
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
dataTransfer.setData('Text', '')
|
dataTransfer.setData("Text", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.board-column {
|
.board-column {
|
||||||
|
@ -96,4 +96,3 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="computedClasses" class="material-input__component">
|
<div :class="computedClasses" class="material-input__component">
|
||||||
<div :class="{iconClass:icon}">
|
<div :class="{ iconClass: icon }">
|
||||||
<i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
|
<i
|
||||||
|
v-if="icon"
|
||||||
|
:class="['el-icon-' + icon]"
|
||||||
|
class="el-input__icon material-input__icon"
|
||||||
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'email'"
|
v-if="type === 'email'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -16,7 +20,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'url'"
|
v-if="type === 'url'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -31,7 +35,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'number'"
|
v-if="type === 'number'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -51,7 +55,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'password'"
|
v-if="type === 'password'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -68,7 +72,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'tel'"
|
v-if="type === 'tel'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -83,7 +87,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<input
|
<input
|
||||||
v-if="type === 'text'"
|
v-if="type === 'text'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
|
@ -100,7 +104,7 @@
|
||||||
@focus="handleMdFocus"
|
@focus="handleMdFocus"
|
||||||
@blur="handleMdBlur"
|
@blur="handleMdBlur"
|
||||||
@input="handleModelInput"
|
@input="handleModelInput"
|
||||||
>
|
/>
|
||||||
<span class="material-input-bar" />
|
<span class="material-input-bar" />
|
||||||
<label class="material-label">
|
<label class="material-label">
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -113,14 +117,14 @@
|
||||||
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
|
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MdInput',
|
name: "MdInput",
|
||||||
props: {
|
props: {
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
icon: String,
|
icon: String,
|
||||||
name: String,
|
name: String,
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'text'
|
default: "text"
|
||||||
},
|
},
|
||||||
value: [String, Number],
|
value: [String, Number],
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
|
@ -137,7 +141,7 @@ export default {
|
||||||
},
|
},
|
||||||
autoComplete: {
|
autoComplete: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'off'
|
default: "off"
|
||||||
},
|
},
|
||||||
validateEvent: {
|
validateEvent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -149,94 +153,94 @@ export default {
|
||||||
currentValue: this.value,
|
currentValue: this.value,
|
||||||
focus: false,
|
focus: false,
|
||||||
fillPlaceHolder: null
|
fillPlaceHolder: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
computedClasses() {
|
computedClasses() {
|
||||||
return {
|
return {
|
||||||
'material--active': this.focus,
|
"material--active": this.focus,
|
||||||
'material--disabled': this.disabled,
|
"material--disabled": this.disabled,
|
||||||
'material--raised': Boolean(this.focus || this.currentValue) // has value
|
"material--raised": Boolean(this.focus || this.currentValue) // has value
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(newValue) {
|
value(newValue) {
|
||||||
this.currentValue = newValue
|
this.currentValue = newValue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleModelInput(event) {
|
handleModelInput(event) {
|
||||||
const value = event.target.value
|
const value = event.target.value;
|
||||||
this.$emit('input', value)
|
this.$emit("input", value);
|
||||||
if (this.$parent.$options.componentName === 'ElFormItem') {
|
if (this.$parent.$options.componentName === "ElFormItem") {
|
||||||
if (this.validateEvent) {
|
if (this.validateEvent) {
|
||||||
this.$parent.$emit('el.form.change', [value])
|
this.$parent.$emit("el.form.change", [value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$emit('change', value)
|
this.$emit("change", value);
|
||||||
},
|
},
|
||||||
handleMdFocus(event) {
|
handleMdFocus(event) {
|
||||||
this.focus = true
|
this.focus = true;
|
||||||
this.$emit('focus', event)
|
this.$emit("focus", event);
|
||||||
if (this.placeholder && this.placeholder !== '') {
|
if (this.placeholder && this.placeholder !== "") {
|
||||||
this.fillPlaceHolder = this.placeholder
|
this.fillPlaceHolder = this.placeholder;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleMdBlur(event) {
|
handleMdBlur(event) {
|
||||||
this.focus = false
|
this.focus = false;
|
||||||
this.$emit('blur', event)
|
this.$emit("blur", event);
|
||||||
this.fillPlaceHolder = null
|
this.fillPlaceHolder = null;
|
||||||
if (this.$parent.$options.componentName === 'ElFormItem') {
|
if (this.$parent.$options.componentName === "ElFormItem") {
|
||||||
if (this.validateEvent) {
|
if (this.validateEvent) {
|
||||||
this.$parent.$emit('el.form.blur', [this.currentValue])
|
this.$parent.$emit("el.form.blur", [this.currentValue]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// Fonts:
|
// Fonts:
|
||||||
$font-size-base: 16px;
|
$font-size-base: 16px;
|
||||||
$font-size-small: 18px;
|
$font-size-small: 18px;
|
||||||
$font-size-smallest: 12px;
|
$font-size-smallest: 12px;
|
||||||
$font-weight-normal: normal;
|
$font-weight-normal: normal;
|
||||||
$font-weight-bold: bold;
|
$font-weight-bold: bold;
|
||||||
$apixel: 1px;
|
$apixel: 1px;
|
||||||
// Utils
|
// Utils
|
||||||
$spacer: 12px;
|
$spacer: 12px;
|
||||||
$transition: 0.2s ease all;
|
$transition: 0.2s ease all;
|
||||||
$index: 0px;
|
$index: 0px;
|
||||||
$index-has-icon: 30px;
|
$index-has-icon: 30px;
|
||||||
// Theme:
|
// Theme:
|
||||||
$color-white: white;
|
$color-white: white;
|
||||||
$color-grey: #9E9E9E;
|
$color-grey: #9e9e9e;
|
||||||
$color-grey-light: #E0E0E0;
|
$color-grey-light: #e0e0e0;
|
||||||
$color-blue: #2196F3;
|
$color-blue: #2196f3;
|
||||||
$color-red: #F44336;
|
$color-red: #f44336;
|
||||||
$color-black: black;
|
$color-black: black;
|
||||||
// Base clases:
|
// Base clases:
|
||||||
%base-bar-pseudo {
|
%base-bar-pseudo {
|
||||||
content: '';
|
content: "";
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 0;
|
width: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: $transition;
|
transition: $transition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mixins:
|
// Mixins:
|
||||||
@mixin slided-top() {
|
@mixin slided-top() {
|
||||||
top: - ($font-size-base + $spacer);
|
top: -($font-size-base + $spacer);
|
||||||
left: 0;
|
left: 0;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component:
|
// Component:
|
||||||
.material-input__component {
|
.material-input__component {
|
||||||
margin-top: 36px;
|
margin-top: 36px;
|
||||||
position: relative;
|
position: relative;
|
||||||
* {
|
* {
|
||||||
|
@ -319,9 +323,9 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-input__component {
|
.material-input__component {
|
||||||
background: $color-white;
|
background: $color-white;
|
||||||
.material-input {
|
.material-input {
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -356,5 +360,5 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
|
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
|
||||||
export default {
|
export default {
|
||||||
minHeight: '200px',
|
minHeight: "200px",
|
||||||
previewStyle: 'vertical',
|
previewStyle: "vertical",
|
||||||
useCommandShortcut: true,
|
useCommandShortcut: true,
|
||||||
useDefaultHTMLSanitizer: true,
|
useDefaultHTMLSanitizer: true,
|
||||||
usageStatistics: false,
|
usageStatistics: false,
|
||||||
hideModeSwitch: false,
|
hideModeSwitch: false,
|
||||||
toolbarItems: [
|
toolbarItems: [
|
||||||
'heading',
|
"heading",
|
||||||
'bold',
|
"bold",
|
||||||
'italic',
|
"italic",
|
||||||
'strike',
|
"strike",
|
||||||
'divider',
|
"divider",
|
||||||
'hr',
|
"hr",
|
||||||
'quote',
|
"quote",
|
||||||
'divider',
|
"divider",
|
||||||
'ul',
|
"ul",
|
||||||
'ol',
|
"ol",
|
||||||
'task',
|
"task",
|
||||||
'indent',
|
"indent",
|
||||||
'outdent',
|
"outdent",
|
||||||
'divider',
|
"divider",
|
||||||
'table',
|
"table",
|
||||||
'image',
|
"image",
|
||||||
'link',
|
"link",
|
||||||
'divider',
|
"divider",
|
||||||
'code',
|
"code",
|
||||||
'codeblock'
|
"codeblock"
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
|
|
|
@ -4,115 +4,119 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// deps for editor
|
// deps for editor
|
||||||
import 'codemirror/lib/codemirror.css' // codemirror
|
import "codemirror/lib/codemirror.css"; // codemirror
|
||||||
import 'tui-editor/dist/tui-editor.css' // editor ui
|
import "tui-editor/dist/tui-editor.css"; // editor ui
|
||||||
import 'tui-editor/dist/tui-editor-contents.css' // editor content
|
import "tui-editor/dist/tui-editor-contents.css"; // editor content
|
||||||
|
|
||||||
import Editor from 'tui-editor'
|
import Editor from "tui-editor";
|
||||||
import defaultOptions from './default-options'
|
import defaultOptions from "./default-options";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MarddownEditor',
|
name: "MarddownEditor",
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default() {
|
default() {
|
||||||
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
return (
|
||||||
|
"markdown-editor-" +
|
||||||
|
+new Date() +
|
||||||
|
((Math.random() * 1000).toFixed(0) + "")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default() {
|
default() {
|
||||||
return defaultOptions
|
return defaultOptions;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mode: {
|
mode: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'markdown'
|
default: "markdown"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: '300px'
|
default: "300px"
|
||||||
},
|
},
|
||||||
language: {
|
language: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
|
default: "en_US" // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
editor: null
|
editor: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
editorOptions() {
|
editorOptions() {
|
||||||
const options = Object.assign({}, defaultOptions, this.options)
|
const options = Object.assign({}, defaultOptions, this.options);
|
||||||
options.initialEditType = this.mode
|
options.initialEditType = this.mode;
|
||||||
options.height = this.height
|
options.height = this.height;
|
||||||
options.language = this.language
|
options.language = this.language;
|
||||||
return options
|
return options;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(newValue, preValue) {
|
value(newValue, preValue) {
|
||||||
if (newValue !== preValue && newValue !== this.editor.getValue()) {
|
if (newValue !== preValue && newValue !== this.editor.getValue()) {
|
||||||
this.editor.setValue(newValue)
|
this.editor.setValue(newValue);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
language(val) {
|
language(val) {
|
||||||
this.destroyEditor()
|
this.destroyEditor();
|
||||||
this.initEditor()
|
this.initEditor();
|
||||||
},
|
},
|
||||||
height(newValue) {
|
height(newValue) {
|
||||||
this.editor.height(newValue)
|
this.editor.height(newValue);
|
||||||
},
|
},
|
||||||
mode(newValue) {
|
mode(newValue) {
|
||||||
this.editor.changeMode(newValue)
|
this.editor.changeMode(newValue);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initEditor()
|
this.initEditor();
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.destroyEditor()
|
this.destroyEditor();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initEditor() {
|
initEditor() {
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
el: document.getElementById(this.id),
|
el: document.getElementById(this.id),
|
||||||
...this.editorOptions
|
...this.editorOptions
|
||||||
})
|
});
|
||||||
if (this.value) {
|
if (this.value) {
|
||||||
this.editor.setValue(this.value)
|
this.editor.setValue(this.value);
|
||||||
}
|
}
|
||||||
this.editor.on('change', () => {
|
this.editor.on("change", () => {
|
||||||
this.$emit('input', this.editor.getValue())
|
this.$emit("input", this.editor.getValue());
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
destroyEditor() {
|
destroyEditor() {
|
||||||
if (!this.editor) return
|
if (!this.editor) return;
|
||||||
this.editor.off('change')
|
this.editor.off("change");
|
||||||
this.editor.remove()
|
this.editor.remove();
|
||||||
},
|
},
|
||||||
setValue(value) {
|
setValue(value) {
|
||||||
this.editor.setValue(value)
|
this.editor.setValue(value);
|
||||||
},
|
},
|
||||||
getValue() {
|
getValue() {
|
||||||
return this.editor.getValue()
|
return this.editor.getValue();
|
||||||
},
|
},
|
||||||
setHtml(value) {
|
setHtml(value) {
|
||||||
this.editor.setHtml(value)
|
this.editor.setHtml(value);
|
||||||
},
|
},
|
||||||
getHtml() {
|
getHtml() {
|
||||||
return this.editor.getHtml()
|
return this.editor.getHtml();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
<div :class="{ hidden: hidden }" class="pagination-container">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
:background="background"
|
:background="background"
|
||||||
:current-page.sync="currentPage"
|
:current-page.sync="currentPage"
|
||||||
|
@ -15,10 +15,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { scrollTo } from '@/utils/scroll-to'
|
import { scrollTo } from "@/utils/scroll-to";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Pagination',
|
name: "Pagination",
|
||||||
props: {
|
props: {
|
||||||
total: {
|
total: {
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -35,12 +35,12 @@ export default {
|
||||||
pageSizes: {
|
pageSizes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default() {
|
default() {
|
||||||
return [10, 20, 30, 50]
|
return [10, 20, 30, 50];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'total, sizes, prev, pager, next, jumper'
|
default: "total, sizes, prev, pager, next, jumper"
|
||||||
},
|
},
|
||||||
background: {
|
background: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -58,36 +58,36 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
currentPage: {
|
currentPage: {
|
||||||
get() {
|
get() {
|
||||||
return this.page
|
return this.page;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('update:page', val)
|
this.$emit("update:page", val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pageSize: {
|
pageSize: {
|
||||||
get() {
|
get() {
|
||||||
return this.limit
|
return this.limit;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('update:limit', val)
|
this.$emit("update:limit", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
this.$emit("pagination", { page: this.currentPage, limit: val });
|
||||||
if (this.autoScroll) {
|
if (this.autoScroll) {
|
||||||
scrollTo(0, 800)
|
scrollTo(0, 800);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCurrentChange(val) {
|
handleCurrentChange(val) {
|
||||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
this.$emit("pagination", { page: val, limit: this.pageSize });
|
||||||
if (this.autoScroll) {
|
if (this.autoScroll) {
|
||||||
scrollTo(0, 800)
|
scrollTo(0, 800);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
|
<div
|
||||||
|
:style="{ zIndex: zIndex, height: height, width: width }"
|
||||||
|
class="pan-item"
|
||||||
|
>
|
||||||
<div class="pan-info">
|
<div class="pan-info">
|
||||||
<div class="pan-info-roles-container">
|
<div class="pan-info-roles-container">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- eslint-disable-next-line -->
|
<!-- eslint-disable-next-line -->
|
||||||
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
|
<div :style="{ backgroundImage: `url(${image})` }" class="pan-thumb"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'PanThumb',
|
name: "PanThumb",
|
||||||
props: {
|
props: {
|
||||||
image: {
|
image: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -24,14 +27,14 @@ export default {
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '150px'
|
default: "150px"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '150px'
|
default: "150px"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -93,7 +96,7 @@ export default {
|
||||||
margin: 0 60px;
|
margin: 0 60px;
|
||||||
padding: 22px 0 0 0;
|
padding: 22px 0 0 0;
|
||||||
height: 85px;
|
height: 85px;
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
font-family: "Open Sans", Arial, sans-serif;
|
||||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,9 +124,10 @@ export default {
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
padding-top: 24px;
|
padding-top: 24px;
|
||||||
margin: 7px auto 0;
|
margin: 7px auto 0;
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
font-family: "Open Sans", Arial, sans-serif;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
|
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s,
|
||||||
|
background 0.2s linear 0s;
|
||||||
transform: translateX(60px) rotate(90deg);
|
transform: translateX(60px) rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
<div ref="rightPanel" :class="{ show: show }" class="rightPanel-container">
|
||||||
<div class="rightPanel-background" />
|
<div class="rightPanel-background" />
|
||||||
<div class="rightPanel">
|
<div class="rightPanel">
|
||||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
<div
|
||||||
<i :class="show?'el-icon-close':'el-icon-setting'" />
|
class="handle-button"
|
||||||
|
:style="{ top: buttonTop + 'px', 'background-color': theme }"
|
||||||
|
@click="show = !show"
|
||||||
|
>
|
||||||
|
<i :class="show ? 'el-icon-close' : 'el-icon-setting'" />
|
||||||
</div>
|
</div>
|
||||||
<div class="rightPanel-items">
|
<div class="rightPanel-items">
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -13,10 +17,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { addClass, removeClass } from '@/utils'
|
import { addClass, removeClass } from "@/utils";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RightPanel',
|
name: "RightPanel",
|
||||||
props: {
|
props: {
|
||||||
clickNotClose: {
|
clickNotClose: {
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -30,50 +34,50 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show: false
|
show: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
theme() {
|
theme() {
|
||||||
return this.$store.state.settings.theme
|
return this.$store.state.settings.theme;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
show(value) {
|
show(value) {
|
||||||
if (value && !this.clickNotClose) {
|
if (value && !this.clickNotClose) {
|
||||||
this.addEventClick()
|
this.addEventClick();
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
addClass(document.body, 'showRightPanel')
|
addClass(document.body, "showRightPanel");
|
||||||
} else {
|
} else {
|
||||||
removeClass(document.body, 'showRightPanel')
|
removeClass(document.body, "showRightPanel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.insertToBody()
|
this.insertToBody();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
const elx = this.$refs.rightPanel
|
const elx = this.$refs.rightPanel;
|
||||||
elx.remove()
|
elx.remove();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addEventClick() {
|
addEventClick() {
|
||||||
window.addEventListener('click', this.closeSidebar)
|
window.addEventListener("click", this.closeSidebar);
|
||||||
},
|
},
|
||||||
closeSidebar(evt) {
|
closeSidebar(evt) {
|
||||||
const parent = evt.target.closest('.rightPanel')
|
const parent = evt.target.closest(".rightPanel");
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
this.show = false
|
this.show = false;
|
||||||
window.removeEventListener('click', this.closeSidebar)
|
window.removeEventListener("click", this.closeSidebar);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
insertToBody() {
|
insertToBody() {
|
||||||
const elx = this.$refs.rightPanel
|
const elx = this.$refs.rightPanel;
|
||||||
const body = document.querySelector('body')
|
const body = document.querySelector("body");
|
||||||
body.insertBefore(elx, body.firstChild)
|
body.insertBefore(elx, body.firstChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -90,8 +94,8 @@ export default {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
transition: opacity 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
|
||||||
background: rgba(0, 0, 0, .2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,15 +106,15 @@ export default {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.05);
|
||||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
transition: all 0.25s cubic-bezier(0.7, 0.3, 0.1, 1);
|
||||||
transform: translate(100%);
|
transform: translate(100%);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
z-index: 40000;
|
z-index: 40000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show {
|
.show {
|
||||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
transition: all 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
|
||||||
|
|
||||||
.rightPanel-background {
|
.rightPanel-background {
|
||||||
z-index: 20000;
|
z-index: 20000;
|
||||||
|
|
|
@ -1,58 +1,61 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
|
<svg-icon
|
||||||
|
:icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
|
||||||
|
@click="click"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import screenfull from 'screenfull'
|
import screenfull from "screenfull";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Screenfull',
|
name: "Screenfull",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isFullscreen: false
|
isFullscreen: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.init();
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.destroy()
|
this.destroy();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
click() {
|
click() {
|
||||||
if (!screenfull.enabled) {
|
if (!screenfull.enabled) {
|
||||||
this.$message({
|
this.$message({
|
||||||
message: 'you browser can not work',
|
message: "you browser can not work",
|
||||||
type: 'warning'
|
type: "warning"
|
||||||
})
|
});
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
screenfull.toggle()
|
screenfull.toggle();
|
||||||
},
|
},
|
||||||
change() {
|
change() {
|
||||||
this.isFullscreen = screenfull.isFullscreen
|
this.isFullscreen = screenfull.isFullscreen;
|
||||||
},
|
},
|
||||||
init() {
|
init() {
|
||||||
if (screenfull.enabled) {
|
if (screenfull.enabled) {
|
||||||
screenfull.on('change', this.change)
|
screenfull.on("change", this.change);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
destroy() {
|
destroy() {
|
||||||
if (screenfull.enabled) {
|
if (screenfull.enabled) {
|
||||||
screenfull.off('change', this.change)
|
screenfull.off("change", this.change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.screenfull-svg {
|
.screenfull-svg {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
fill: #5a5e66;;
|
fill: #5a5e66;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
vertical-align: 10px;
|
vertical-align: 10px;
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{active:isActive}" class="share-dropdown-menu">
|
<div :class="{ active: isActive }" class="share-dropdown-menu">
|
||||||
<div class="share-dropdown-menu-wrapper">
|
<div class="share-dropdown-menu-wrapper">
|
||||||
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span>
|
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{
|
||||||
<div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item">
|
title
|
||||||
<a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a>
|
}}</span>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) of items"
|
||||||
|
:key="index"
|
||||||
|
class="share-dropdown-menu-item"
|
||||||
|
>
|
||||||
|
<a v-if="item.href" :href="item.href" target="_blank">{{
|
||||||
|
item.title
|
||||||
|
}}</a>
|
||||||
<span v-else>{{ item.title }}</span>
|
<span v-else>{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,30 +24,30 @@ export default {
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: function() {
|
default: function() {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'vue'
|
default: "vue"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isActive: false
|
isActive: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clickTitle() {
|
clickTitle() {
|
||||||
this.isActive = !this.isActive
|
this.isActive = !this.isActive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" >
|
<style lang="scss">
|
||||||
$n: 9; //和items.length 相同
|
$n: 9; //和items.length 相同
|
||||||
$t: .1s;
|
$t: 0.1s;
|
||||||
.share-dropdown-menu {
|
.share-dropdown-menu {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -55,7 +63,7 @@ $t: .1s;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
transform: translate3d(0,0,0);
|
transform: translate3d(0, 0, 0);
|
||||||
}
|
}
|
||||||
&-wrapper {
|
&-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -78,7 +86,7 @@ $t: .1s;
|
||||||
@for $i from 1 through $n {
|
@for $i from 1 through $n {
|
||||||
&:nth-of-type(#{$i}) {
|
&:nth-of-type(#{$i}) {
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
transition-delay: $i*$t;
|
transition-delay: $i * $t;
|
||||||
transform: translate3d(0, -60px, 0);
|
transform: translate3d(0, -60px, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,8 +98,8 @@ $t: .1s;
|
||||||
.share-dropdown-menu-item {
|
.share-dropdown-menu-item {
|
||||||
@for $i from 1 through $n {
|
@for $i from 1 through $n {
|
||||||
&:nth-of-type(#{$i}) {
|
&:nth-of-type(#{$i}) {
|
||||||
transition-delay: ($n - $i)*$t;
|
transition-delay: ($n - $i) * $t;
|
||||||
transform: translate3d(0, ($i - 1)*60px, 0);
|
transform: translate3d(0, ($i - 1) * 60px, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
<svg-icon class-name="size-icon" icon-class="size" />
|
<svg-icon class-name="size-icon" icon-class="size" />
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
|
<el-dropdown-item
|
||||||
{{
|
v-for="item of sizeOptions"
|
||||||
item.label }}
|
:key="item.value"
|
||||||
|
:disabled="size === item.value"
|
||||||
|
:command="item.value"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
@ -17,41 +21,40 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sizeOptions: [
|
sizeOptions: [
|
||||||
{ label: 'Default', value: 'default' },
|
{ label: "Default", value: "default" },
|
||||||
{ label: 'Medium', value: 'medium' },
|
{ label: "Medium", value: "medium" },
|
||||||
{ label: 'Small', value: 'small' },
|
{ label: "Small", value: "small" },
|
||||||
{ label: 'Mini', value: 'mini' }
|
{ label: "Mini", value: "mini" }
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
size() {
|
size() {
|
||||||
return this.$store.getters.size
|
return this.$store.getters.size;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSetSize(size) {
|
handleSetSize(size) {
|
||||||
this.$ELEMENT.size = size
|
this.$ELEMENT.size = size;
|
||||||
this.$store.dispatch('app/setSize', size)
|
this.$store.dispatch("app/setSize", size);
|
||||||
this.refreshView()
|
this.refreshView();
|
||||||
this.$message({
|
this.$message({
|
||||||
message: 'Switch Size Success',
|
message: "Switch Size Success",
|
||||||
type: 'success'
|
type: "success"
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
refreshView() {
|
refreshView() {
|
||||||
// In order to make the cached page re-rendered
|
// In order to make the cached page re-rendered
|
||||||
this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
|
this.$store.dispatch("tagsView/delAllCachedViews", this.$route);
|
||||||
|
|
||||||
const { fullPath } = this.$route
|
const { fullPath } = this.$route;
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$router.replace({
|
this.$router.replace({
|
||||||
path: '/redirect' + fullPath
|
path: "/redirect" + fullPath
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div :style="{height:height+'px',zIndex:zIndex}">
|
<div :style="{ height: height + 'px', zIndex: zIndex }">
|
||||||
<div
|
<div
|
||||||
:class="className"
|
:class="className"
|
||||||
:style="{top:(isSticky ? stickyTop +'px' : ''),zIndex:zIndex,position:position,width:width,height:height+'px'}"
|
:style="{
|
||||||
|
top: isSticky ? stickyTop + 'px' : '',
|
||||||
|
zIndex: zIndex,
|
||||||
|
position: position,
|
||||||
|
width: width,
|
||||||
|
height: height + 'px'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<slot>
|
<slot>
|
||||||
<div>sticky</div>
|
<div>sticky</div>
|
||||||
|
@ -13,7 +19,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'Sticky',
|
name: "Sticky",
|
||||||
props: {
|
props: {
|
||||||
stickyTop: {
|
stickyTop: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -25,67 +31,67 @@ export default {
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
active: false,
|
active: false,
|
||||||
position: '',
|
position: "",
|
||||||
width: undefined,
|
width: undefined,
|
||||||
height: undefined,
|
height: undefined,
|
||||||
isSticky: false
|
isSticky: false
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.height = this.$el.getBoundingClientRect().height
|
this.height = this.$el.getBoundingClientRect().height;
|
||||||
window.addEventListener('scroll', this.handleScroll)
|
window.addEventListener("scroll", this.handleScroll);
|
||||||
window.addEventListener('resize', this.handleResize)
|
window.addEventListener("resize", this.handleResize);
|
||||||
},
|
},
|
||||||
activated() {
|
activated() {
|
||||||
this.handleScroll()
|
this.handleScroll();
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
window.removeEventListener('scroll', this.handleScroll)
|
window.removeEventListener("scroll", this.handleScroll);
|
||||||
window.removeEventListener('resize', this.handleResize)
|
window.removeEventListener("resize", this.handleResize);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sticky() {
|
sticky() {
|
||||||
if (this.active) {
|
if (this.active) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.position = 'fixed'
|
this.position = "fixed";
|
||||||
this.active = true
|
this.active = true;
|
||||||
this.width = this.width + 'px'
|
this.width = this.width + "px";
|
||||||
this.isSticky = true
|
this.isSticky = true;
|
||||||
},
|
},
|
||||||
handleReset() {
|
handleReset() {
|
||||||
if (!this.active) {
|
if (!this.active) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.reset()
|
this.reset();
|
||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
this.position = ''
|
this.position = "";
|
||||||
this.width = 'auto'
|
this.width = "auto";
|
||||||
this.active = false
|
this.active = false;
|
||||||
this.isSticky = false
|
this.isSticky = false;
|
||||||
},
|
},
|
||||||
handleScroll() {
|
handleScroll() {
|
||||||
const width = this.$el.getBoundingClientRect().width
|
const width = this.$el.getBoundingClientRect().width;
|
||||||
this.width = width || 'auto'
|
this.width = width || "auto";
|
||||||
const offsetTop = this.$el.getBoundingClientRect().top
|
const offsetTop = this.$el.getBoundingClientRect().top;
|
||||||
if (offsetTop < this.stickyTop) {
|
if (offsetTop < this.stickyTop) {
|
||||||
this.sticky()
|
this.sticky();
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.handleReset()
|
this.handleReset();
|
||||||
},
|
},
|
||||||
handleResize() {
|
handleResize() {
|
||||||
if (this.isSticky) {
|
if (this.isSticky) {
|
||||||
this.width = this.$el.getBoundingClientRect().width + 'px'
|
this.width = this.$el.getBoundingClientRect().width + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
<div
|
||||||
|
v-if="isExternal"
|
||||||
|
:style="styleExternalIcon"
|
||||||
|
class="svg-external-icon svg-icon"
|
||||||
|
v-on="$listeners"
|
||||||
|
/>
|
||||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||||
<use :xlink:href="iconName" />
|
<use :xlink:href="iconName" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -7,10 +12,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
||||||
import { isExternal } from '@/utils/validate'
|
import { isExternal } from "@/utils/validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SvgIcon',
|
name: "SvgIcon",
|
||||||
props: {
|
props: {
|
||||||
iconClass: {
|
iconClass: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -18,31 +23,31 @@ export default {
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isExternal() {
|
isExternal() {
|
||||||
return isExternal(this.iconClass)
|
return isExternal(this.iconClass);
|
||||||
},
|
},
|
||||||
iconName() {
|
iconName() {
|
||||||
return `#icon-${this.iconClass}`
|
return `#icon-${this.iconClass}`;
|
||||||
},
|
},
|
||||||
svgClass() {
|
svgClass() {
|
||||||
if (this.className) {
|
if (this.className) {
|
||||||
return 'svg-icon ' + this.className
|
return "svg-icon " + this.className;
|
||||||
} else {
|
} else {
|
||||||
return 'svg-icon'
|
return "svg-icon";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
styleExternalIcon() {
|
styleExternalIcon() {
|
||||||
return {
|
return {
|
||||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
"-webkit-mask": `url(${this.iconClass}) no-repeat 50% 50%`
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -56,7 +61,7 @@ export default {
|
||||||
|
|
||||||
.svg-external-icon {
|
.svg-external-icon {
|
||||||
background-color: currentColor;
|
background-color: currentColor;
|
||||||
mask-size: cover!important;
|
mask-size: cover !important;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,14 +11,14 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
className: {
|
className: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'vue-element-admin'
|
default: "vue-element-admin"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -27,7 +27,7 @@ export default {
|
||||||
.link--mallki {
|
.link--mallki {
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: #4dd9d5;
|
color: #4dd9d5;
|
||||||
font-family: 'Dosis', sans-serif;
|
font-family: "Dosis", sans-serif;
|
||||||
-webkit-transition: color 0.5s 0.25s;
|
-webkit-transition: color 0.5s 0.25s;
|
||||||
transition: color 0.5s 0.25s;
|
transition: color 0.5s 0.25s;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -45,7 +45,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.link--mallki::before {
|
.link--mallki::before {
|
||||||
content: '';
|
content: "";
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
margin: -3px 0 0 0;
|
margin: -3px 0 0 0;
|
||||||
|
|
|
@ -1,160 +1,183 @@
|
||||||
<template>
|
<template>
|
||||||
<el-color-picker
|
<el-color-picker
|
||||||
v-model="theme"
|
v-model="theme"
|
||||||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
|
:predefine="[
|
||||||
|
'#409EFF',
|
||||||
|
'#1890ff',
|
||||||
|
'#304156',
|
||||||
|
'#212121',
|
||||||
|
'#11a983',
|
||||||
|
'#13c2c2',
|
||||||
|
'#6959CD',
|
||||||
|
'#f5222d'
|
||||||
|
]"
|
||||||
class="theme-picker"
|
class="theme-picker"
|
||||||
popper-class="theme-picker-dropdown"
|
popper-class="theme-picker-dropdown"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
const version = require("element-ui/package.json").version; // element-ui version from node_modules
|
||||||
const ORIGINAL_THEME = '#409EFF' // default color
|
const ORIGINAL_THEME = "#409EFF"; // default color
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chalk: '', // content of theme-chalk css
|
chalk: "", // content of theme-chalk css
|
||||||
theme: ''
|
theme: ""
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
defaultTheme() {
|
defaultTheme() {
|
||||||
return this.$store.state.settings.theme
|
return this.$store.state.settings.theme;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
defaultTheme: {
|
defaultTheme: {
|
||||||
handler: function(val, oldVal) {
|
handler: function(val, oldVal) {
|
||||||
this.theme = val
|
this.theme = val;
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
},
|
},
|
||||||
async theme(val) {
|
async theme(val) {
|
||||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME;
|
||||||
if (typeof val !== 'string') return
|
if (typeof val !== "string") return;
|
||||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
const themeCluster = this.getThemeCluster(val.replace("#", ""));
|
||||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
|
||||||
console.log(themeCluster, originalCluster)
|
console.log(themeCluster, originalCluster);
|
||||||
|
|
||||||
const $message = this.$message({
|
const $message = this.$message({
|
||||||
message: ' Compiling the theme',
|
message: " Compiling the theme",
|
||||||
customClass: 'theme-message',
|
customClass: "theme-message",
|
||||||
type: 'success',
|
type: "success",
|
||||||
duration: 0,
|
duration: 0,
|
||||||
iconClass: 'el-icon-loading'
|
iconClass: "el-icon-loading"
|
||||||
})
|
});
|
||||||
|
|
||||||
const getHandler = (variable, id) => {
|
const getHandler = (variable, id) => {
|
||||||
return () => {
|
return () => {
|
||||||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
|
const originalCluster = this.getThemeCluster(
|
||||||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
|
ORIGINAL_THEME.replace("#", "")
|
||||||
|
);
|
||||||
|
const newStyle = this.updateStyle(
|
||||||
|
this[variable],
|
||||||
|
originalCluster,
|
||||||
|
themeCluster
|
||||||
|
);
|
||||||
|
|
||||||
let styleTag = document.getElementById(id)
|
let styleTag = document.getElementById(id);
|
||||||
if (!styleTag) {
|
if (!styleTag) {
|
||||||
styleTag = document.createElement('style')
|
styleTag = document.createElement("style");
|
||||||
styleTag.setAttribute('id', id)
|
styleTag.setAttribute("id", id);
|
||||||
document.head.appendChild(styleTag)
|
document.head.appendChild(styleTag);
|
||||||
}
|
|
||||||
styleTag.innerText = newStyle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
styleTag.innerText = newStyle;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if (!this.chalk) {
|
if (!this.chalk) {
|
||||||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
|
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
|
||||||
await this.getCSSString(url, 'chalk')
|
await this.getCSSString(url, "chalk");
|
||||||
}
|
}
|
||||||
|
|
||||||
const chalkHandler = getHandler('chalk', 'chalk-style')
|
const chalkHandler = getHandler("chalk", "chalk-style");
|
||||||
|
|
||||||
chalkHandler()
|
chalkHandler();
|
||||||
|
|
||||||
const styles = [].slice.call(document.querySelectorAll('style'))
|
const styles = [].slice
|
||||||
|
.call(document.querySelectorAll("style"))
|
||||||
.filter(style => {
|
.filter(style => {
|
||||||
const text = style.innerText
|
const text = style.innerText;
|
||||||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
|
return (
|
||||||
})
|
new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
|
||||||
|
);
|
||||||
|
});
|
||||||
styles.forEach(style => {
|
styles.forEach(style => {
|
||||||
const { innerText } = style
|
const { innerText } = style;
|
||||||
if (typeof innerText !== 'string') return
|
if (typeof innerText !== "string") return;
|
||||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
style.innerText = this.updateStyle(
|
||||||
})
|
innerText,
|
||||||
|
originalCluster,
|
||||||
|
themeCluster
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
this.$emit('change', val)
|
this.$emit("change", val);
|
||||||
|
|
||||||
$message.close()
|
$message.close();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
updateStyle(style, oldCluster, newCluster) {
|
updateStyle(style, oldCluster, newCluster) {
|
||||||
let newStyle = style
|
let newStyle = style;
|
||||||
oldCluster.forEach((color, index) => {
|
oldCluster.forEach((color, index) => {
|
||||||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
|
newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
|
||||||
})
|
});
|
||||||
return newStyle
|
return newStyle;
|
||||||
},
|
},
|
||||||
|
|
||||||
getCSSString(url, variable) {
|
getCSSString(url, variable) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const xhr = new XMLHttpRequest()
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.onreadystatechange = () => {
|
xhr.onreadystatechange = () => {
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
|
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
|
||||||
resolve()
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
xhr.open('GET', url)
|
xhr.open("GET", url);
|
||||||
xhr.send()
|
xhr.send();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getThemeCluster(theme) {
|
getThemeCluster(theme) {
|
||||||
const tintColor = (color, tint) => {
|
const tintColor = (color, tint) => {
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
let red = parseInt(color.slice(0, 2), 16);
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
let green = parseInt(color.slice(2, 4), 16);
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
let blue = parseInt(color.slice(4, 6), 16);
|
||||||
|
|
||||||
if (tint === 0) { // when primary color is in its rgb space
|
if (tint === 0) {
|
||||||
return [red, green, blue].join(',')
|
// when primary color is in its rgb space
|
||||||
|
return [red, green, blue].join(",");
|
||||||
} else {
|
} else {
|
||||||
red += Math.round(tint * (255 - red))
|
red += Math.round(tint * (255 - red));
|
||||||
green += Math.round(tint * (255 - green))
|
green += Math.round(tint * (255 - green));
|
||||||
blue += Math.round(tint * (255 - blue))
|
blue += Math.round(tint * (255 - blue));
|
||||||
|
|
||||||
red = red.toString(16)
|
red = red.toString(16);
|
||||||
green = green.toString(16)
|
green = green.toString(16);
|
||||||
blue = blue.toString(16)
|
blue = blue.toString(16);
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
return `#${red}${green}${blue}`;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const shadeColor = (color, shade) => {
|
const shadeColor = (color, shade) => {
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
let red = parseInt(color.slice(0, 2), 16);
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
let green = parseInt(color.slice(2, 4), 16);
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
let blue = parseInt(color.slice(4, 6), 16);
|
||||||
|
|
||||||
red = Math.round((1 - shade) * red)
|
red = Math.round((1 - shade) * red);
|
||||||
green = Math.round((1 - shade) * green)
|
green = Math.round((1 - shade) * green);
|
||||||
blue = Math.round((1 - shade) * blue)
|
blue = Math.round((1 - shade) * blue);
|
||||||
|
|
||||||
red = red.toString(16)
|
red = red.toString(16);
|
||||||
green = green.toString(16)
|
green = green.toString(16);
|
||||||
blue = blue.toString(16)
|
blue = blue.toString(16);
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
return `#${red}${green}${blue}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
const clusters = [theme]
|
const clusters = [theme];
|
||||||
for (let i = 0; i <= 9; i++) {
|
for (let i = 0; i <= 9; i++) {
|
||||||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
|
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
|
||||||
}
|
}
|
||||||
clusters.push(shadeColor(theme, 0.1))
|
clusters.push(shadeColor(theme, 0.1));
|
||||||
return clusters
|
return clusters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="upload-container">
|
<div class="upload-container">
|
||||||
<el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
|
<el-button
|
||||||
|
:style="{ background: color, borderColor: color }"
|
||||||
|
icon="el-icon-upload"
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
@click="dialogVisible = true"
|
||||||
|
>
|
||||||
upload
|
upload
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-dialog :visible.sync="dialogVisible">
|
<el-dialog :visible.sync="dialogVisible">
|
||||||
|
@ -33,11 +39,11 @@
|
||||||
// import { getToken } from 'api/qiniu'
|
// import { getToken } from 'api/qiniu'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditorSlideUpload',
|
name: "EditorSlideUpload",
|
||||||
props: {
|
props: {
|
||||||
color: {
|
color: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '#1890ff'
|
default: "#1890ff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -45,66 +51,75 @@ export default {
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
listObj: {},
|
listObj: {},
|
||||||
fileList: []
|
fileList: []
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkAllSuccess() {
|
checkAllSuccess() {
|
||||||
return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
|
return Object.keys(this.listObj).every(
|
||||||
|
item => this.listObj[item].hasSuccess
|
||||||
|
);
|
||||||
},
|
},
|
||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
const arr = Object.keys(this.listObj).map(v => this.listObj[v])
|
const arr = Object.keys(this.listObj).map(v => this.listObj[v]);
|
||||||
if (!this.checkAllSuccess()) {
|
if (!this.checkAllSuccess()) {
|
||||||
this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
|
this.$message(
|
||||||
return
|
"Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!"
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('successCBK', arr)
|
this.$emit("successCBK", arr);
|
||||||
this.listObj = {}
|
this.listObj = {};
|
||||||
this.fileList = []
|
this.fileList = [];
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false;
|
||||||
},
|
},
|
||||||
handleSuccess(response, file) {
|
handleSuccess(response, file) {
|
||||||
const uid = file.uid
|
const uid = file.uid;
|
||||||
const objKeyArr = Object.keys(this.listObj)
|
const objKeyArr = Object.keys(this.listObj);
|
||||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||||
this.listObj[objKeyArr[i]].url = response.files.file
|
this.listObj[objKeyArr[i]].url = response.files.file;
|
||||||
this.listObj[objKeyArr[i]].hasSuccess = true
|
this.listObj[objKeyArr[i]].hasSuccess = true;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleRemove(file) {
|
handleRemove(file) {
|
||||||
const uid = file.uid
|
const uid = file.uid;
|
||||||
const objKeyArr = Object.keys(this.listObj)
|
const objKeyArr = Object.keys(this.listObj);
|
||||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||||
delete this.listObj[objKeyArr[i]]
|
delete this.listObj[objKeyArr[i]];
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
const _self = this
|
const _self = this;
|
||||||
const _URL = window.URL || window.webkitURL
|
const _URL = window.URL || window.webkitURL;
|
||||||
const fileName = file.uid
|
const fileName = file.uid;
|
||||||
this.listObj[fileName] = {}
|
this.listObj[fileName] = {};
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const img = new Image()
|
const img = new Image();
|
||||||
img.src = _URL.createObjectURL(file)
|
img.src = _URL.createObjectURL(file);
|
||||||
img.onload = function() {
|
img.onload = function() {
|
||||||
_self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
|
_self.listObj[fileName] = {
|
||||||
}
|
hasSuccess: false,
|
||||||
resolve(true)
|
uid: file.uid,
|
||||||
})
|
width: this.width,
|
||||||
|
height: this.height
|
||||||
|
};
|
||||||
|
};
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.editor-slide-upload {
|
.editor-slide-upload {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
/deep/ .el-upload--picture-card {
|
::v-deep .el-upload--picture-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
let callbacks = []
|
let callbacks = [];
|
||||||
|
|
||||||
function loadedTinymce() {
|
function loadedTinymce() {
|
||||||
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
|
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
|
||||||
// check is successfully downloaded script
|
// check is successfully downloaded script
|
||||||
return window.tinymce
|
return window.tinymce;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dynamicLoadScript = (src, callback) => {
|
const dynamicLoadScript = (src, callback) => {
|
||||||
const existingScript = document.getElementById(src)
|
const existingScript = document.getElementById(src);
|
||||||
const cb = callback || function() {}
|
const cb = callback || function() {};
|
||||||
|
|
||||||
if (!existingScript) {
|
if (!existingScript) {
|
||||||
const script = document.createElement('script')
|
const script = document.createElement("script");
|
||||||
script.src = src // src url for the third-party library being loaded.
|
script.src = src; // src url for the third-party library being loaded.
|
||||||
script.id = src
|
script.id = src;
|
||||||
document.body.appendChild(script)
|
document.body.appendChild(script);
|
||||||
callbacks.push(cb)
|
callbacks.push(cb);
|
||||||
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
|
const onEnd = "onload" in script ? stdOnEnd : ieOnEnd;
|
||||||
onEnd(script)
|
onEnd(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingScript && cb) {
|
if (existingScript && cb) {
|
||||||
if (loadedTinymce()) {
|
if (loadedTinymce()) {
|
||||||
cb(null, existingScript)
|
cb(null, existingScript);
|
||||||
} else {
|
} else {
|
||||||
callbacks.push(cb)
|
callbacks.push(cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,28 +32,29 @@ const dynamicLoadScript = (src, callback) => {
|
||||||
script.onload = function() {
|
script.onload = function() {
|
||||||
// this.onload = null here is necessary
|
// this.onload = null here is necessary
|
||||||
// because even IE9 works not like others
|
// because even IE9 works not like others
|
||||||
this.onerror = this.onload = null
|
this.onerror = this.onload = null;
|
||||||
for (const cb of callbacks) {
|
for (const cb of callbacks) {
|
||||||
cb(null, script)
|
cb(null, script);
|
||||||
}
|
|
||||||
callbacks = null
|
|
||||||
}
|
}
|
||||||
|
callbacks = null;
|
||||||
|
};
|
||||||
script.onerror = function() {
|
script.onerror = function() {
|
||||||
this.onerror = this.onload = null
|
this.onerror = this.onload = null;
|
||||||
cb(new Error('Failed to load ' + src), script)
|
cb(new Error("Failed to load " + src), script);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function ieOnEnd(script) {
|
function ieOnEnd(script) {
|
||||||
script.onreadystatechange = function() {
|
script.onreadystatechange = function() {
|
||||||
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
|
if (this.readyState !== "complete" && this.readyState !== "loaded")
|
||||||
this.onreadystatechange = null
|
return;
|
||||||
|
this.onreadystatechange = null;
|
||||||
for (const cb of callbacks) {
|
for (const cb of callbacks) {
|
||||||
cb(null, script) // there is no way to catch loading errors in IE8
|
cb(null, script); // there is no way to catch loading errors in IE8
|
||||||
}
|
}
|
||||||
callbacks = null
|
callbacks = null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default dynamicLoadScript
|
export default dynamicLoadScript;
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
|
<div
|
||||||
|
:class="{ fullscreen: fullscreen }"
|
||||||
|
class="tinymce-container"
|
||||||
|
:style="{ width: containerWidth }"
|
||||||
|
>
|
||||||
<textarea :id="tinymceId" class="tinymce-textarea" />
|
<textarea :id="tinymceId" class="tinymce-textarea" />
|
||||||
<div class="editor-custom-btn-container">
|
<div class="editor-custom-btn-container">
|
||||||
<editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
|
<editorImage
|
||||||
|
color="#1890ff"
|
||||||
|
class="editor-upload-btn"
|
||||||
|
@successCBK="imageSuccessCBK"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -12,38 +20,43 @@
|
||||||
* docs:
|
* docs:
|
||||||
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
|
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
|
||||||
*/
|
*/
|
||||||
import editorImage from './components/EditorImage'
|
import editorImage from "./components/EditorImage";
|
||||||
import plugins from './plugins'
|
import plugins from "./plugins";
|
||||||
import toolbar from './toolbar'
|
import toolbar from "./toolbar";
|
||||||
import load from './dynamicLoadScript'
|
import load from "./dynamicLoadScript";
|
||||||
|
|
||||||
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
|
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
|
||||||
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
|
const tinymceCDN =
|
||||||
|
"https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Tinymce',
|
name: "Tinymce",
|
||||||
components: { editorImage },
|
components: { editorImage },
|
||||||
props: {
|
props: {
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
default: function() {
|
default: function() {
|
||||||
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
return (
|
||||||
|
"vue-tinymce-" +
|
||||||
|
+new Date() +
|
||||||
|
((Math.random() * 1000).toFixed(0) + "")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
default() {
|
default() {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
menubar: {
|
menubar: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'file edit insert view format table'
|
default: "file edit insert view format table"
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
|
@ -53,7 +66,7 @@ export default {
|
||||||
width: {
|
width: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
required: false,
|
required: false,
|
||||||
default: 'auto'
|
default: "auto"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -63,90 +76,92 @@ export default {
|
||||||
tinymceId: this.id,
|
tinymceId: this.id,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
languageTypeList: {
|
languageTypeList: {
|
||||||
'en': 'en',
|
en: "en",
|
||||||
'zh': 'zh_CN',
|
zh: "zh_CN",
|
||||||
'es': 'es_MX',
|
es: "es_MX",
|
||||||
'ja': 'ja'
|
ja: "ja"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
containerWidth() {
|
containerWidth() {
|
||||||
const width = this.width
|
const width = this.width;
|
||||||
if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
|
if (/^[\d]+(\.[\d]+)?$/.test(width)) {
|
||||||
return `${width}px`
|
// matches `100`, `'100'`
|
||||||
|
return `${width}px`;
|
||||||
}
|
}
|
||||||
return width
|
return width;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
value(val) {
|
||||||
if (!this.hasChange && this.hasInit) {
|
if (!this.hasChange && this.hasInit) {
|
||||||
this.$nextTick(() =>
|
this.$nextTick(() =>
|
||||||
window.tinymce.get(this.tinymceId).setContent(val || ''))
|
window.tinymce.get(this.tinymceId).setContent(val || "")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.init();
|
||||||
},
|
},
|
||||||
activated() {
|
activated() {
|
||||||
if (window.tinymce) {
|
if (window.tinymce) {
|
||||||
this.initTinymce()
|
this.initTinymce();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deactivated() {
|
deactivated() {
|
||||||
this.destroyTinymce()
|
this.destroyTinymce();
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.destroyTinymce()
|
this.destroyTinymce();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
// dynamic load tinymce from cdn
|
// dynamic load tinymce from cdn
|
||||||
load(tinymceCDN, (err) => {
|
load(tinymceCDN, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.$message.error(err.message)
|
this.$message.error(err.message);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.initTinymce()
|
this.initTinymce();
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
initTinymce() {
|
initTinymce() {
|
||||||
const _this = this
|
const _this = this;
|
||||||
window.tinymce.init({
|
window.tinymce.init({
|
||||||
selector: `#${this.tinymceId}`,
|
selector: `#${this.tinymceId}`,
|
||||||
language: this.languageTypeList['en'],
|
language: this.languageTypeList["en"],
|
||||||
height: this.height,
|
height: this.height,
|
||||||
body_class: 'panel-body ',
|
body_class: "panel-body ",
|
||||||
object_resizing: false,
|
object_resizing: false,
|
||||||
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
||||||
menubar: this.menubar,
|
menubar: this.menubar,
|
||||||
plugins: plugins,
|
plugins: plugins,
|
||||||
end_container_on_empty_block: true,
|
end_container_on_empty_block: true,
|
||||||
powerpaste_word_import: 'clean',
|
powerpaste_word_import: "clean",
|
||||||
code_dialog_height: 450,
|
code_dialog_height: 450,
|
||||||
code_dialog_width: 1000,
|
code_dialog_width: 1000,
|
||||||
advlist_bullet_styles: 'square',
|
advlist_bullet_styles: "square",
|
||||||
advlist_number_styles: 'default',
|
advlist_number_styles: "default",
|
||||||
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
|
imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
|
||||||
default_link_target: '_blank',
|
default_link_target: "_blank",
|
||||||
link_title: false,
|
link_title: false,
|
||||||
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
||||||
init_instance_callback: editor => {
|
init_instance_callback: editor => {
|
||||||
if (_this.value) {
|
if (_this.value) {
|
||||||
editor.setContent(_this.value)
|
editor.setContent(_this.value);
|
||||||
}
|
}
|
||||||
_this.hasInit = true
|
_this.hasInit = true;
|
||||||
editor.on('NodeChange Change KeyUp SetContent', () => {
|
editor.on("NodeChange Change KeyUp SetContent", () => {
|
||||||
this.hasChange = true
|
this.hasChange = true;
|
||||||
this.$emit('input', editor.getContent())
|
this.$emit("input", editor.getContent());
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
setup(editor) {
|
setup(editor) {
|
||||||
editor.on('FullscreenStateChanged', (e) => {
|
editor.on("FullscreenStateChanged", e => {
|
||||||
_this.fullscreen = e.state
|
_this.fullscreen = e.state;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
// 整合七牛上传
|
// 整合七牛上传
|
||||||
// images_dataimg_filter(img) {
|
// images_dataimg_filter(img) {
|
||||||
|
@ -181,32 +196,34 @@ export default {
|
||||||
// console.log(err);
|
// console.log(err);
|
||||||
// });
|
// });
|
||||||
// },
|
// },
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
destroyTinymce() {
|
destroyTinymce() {
|
||||||
const tinymce = window.tinymce.get(this.tinymceId)
|
const tinymce = window.tinymce.get(this.tinymceId);
|
||||||
if (this.fullscreen) {
|
if (this.fullscreen) {
|
||||||
tinymce.execCommand('mceFullScreen')
|
tinymce.execCommand("mceFullScreen");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tinymce) {
|
if (tinymce) {
|
||||||
tinymce.destroy()
|
tinymce.destroy();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setContent(value) {
|
setContent(value) {
|
||||||
window.tinymce.get(this.tinymceId).setContent(value)
|
window.tinymce.get(this.tinymceId).setContent(value);
|
||||||
},
|
},
|
||||||
getContent() {
|
getContent() {
|
||||||
window.tinymce.get(this.tinymceId).getContent()
|
window.tinymce.get(this.tinymceId).getContent();
|
||||||
},
|
},
|
||||||
imageSuccessCBK(arr) {
|
imageSuccessCBK(arr) {
|
||||||
const _this = this
|
const _this = this;
|
||||||
arr.forEach(v => {
|
arr.forEach(v => {
|
||||||
window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
|
window.tinymce
|
||||||
})
|
.get(_this.tinymceId)
|
||||||
|
.insertContent(`<img class="wscnph" src="${v.url}" >`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -214,7 +231,7 @@ export default {
|
||||||
position: relative;
|
position: relative;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
.tinymce-container>>>.mce-fullscreen {
|
.tinymce-container >>> .mce-fullscreen {
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
}
|
}
|
||||||
.tinymce-textarea {
|
.tinymce-textarea {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
||||||
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
||||||
|
|
||||||
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
|
const plugins = [
|
||||||
|
"advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount"
|
||||||
|
];
|
||||||
|
|
||||||
export default plugins
|
export default plugins;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// Here is a list of the toolbar
|
// Here is a list of the toolbar
|
||||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||||
|
|
||||||
const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
|
const toolbar = [
|
||||||
|
"searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample",
|
||||||
|
"hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen"
|
||||||
|
];
|
||||||
|
|
||||||
export default toolbar
|
export default toolbar;
|
||||||
|
|
|
@ -10,13 +10,11 @@
|
||||||
action="https://httpbin.org/post"
|
action="https://httpbin.org/post"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload" />
|
<i class="el-icon-upload" />
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
将文件拖到此处,或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div class="image-preview">
|
<div class="image-preview">
|
||||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
<div v-show="imageUrl.length > 1" class="image-preview-wrapper">
|
||||||
<img :src="imageUrl+'?imageView2/1/w/200/h/200'">
|
<img :src="imageUrl + '?imageView2/1/w/200/h/200'" />
|
||||||
<div class="image-preview-action">
|
<div class="image-preview-action">
|
||||||
<i class="el-icon-delete" @click="rmImage" />
|
<i class="el-icon-delete" @click="rmImage" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,60 +24,62 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getToken } from '@/api/qiniu'
|
import { getToken } from "@/api/qiniu";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SingleImageUpload',
|
name: "SingleImageUpload",
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tempUrl: '',
|
tempUrl: "",
|
||||||
dataObj: { token: '', key: '' }
|
dataObj: { token: "", key: "" }
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
imageUrl() {
|
imageUrl() {
|
||||||
return this.value
|
return this.value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
rmImage() {
|
rmImage() {
|
||||||
this.emitInput('')
|
this.emitInput("");
|
||||||
},
|
},
|
||||||
emitInput(val) {
|
emitInput(val) {
|
||||||
this.$emit('input', val)
|
this.$emit("input", val);
|
||||||
},
|
},
|
||||||
handleImageSuccess() {
|
handleImageSuccess() {
|
||||||
this.emitInput(this.tempUrl)
|
this.emitInput(this.tempUrl);
|
||||||
},
|
},
|
||||||
beforeUpload() {
|
beforeUpload() {
|
||||||
const _self = this
|
const _self = this;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getToken().then(response => {
|
getToken()
|
||||||
const key = response.data.qiniu_key
|
.then(response => {
|
||||||
const token = response.data.qiniu_token
|
const key = response.data.qiniu_key;
|
||||||
_self._data.dataObj.token = token
|
const token = response.data.qiniu_token;
|
||||||
_self._data.dataObj.key = key
|
_self._data.dataObj.token = token;
|
||||||
this.tempUrl = response.data.qiniu_url
|
_self._data.dataObj.key = key;
|
||||||
resolve(true)
|
this.tempUrl = response.data.qiniu_url;
|
||||||
}).catch(err => {
|
resolve(true);
|
||||||
console.log(err)
|
|
||||||
reject(false)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "~@/styles/mixin.scss";
|
@import "~@/styles/mixin.scss";
|
||||||
.upload-container {
|
.upload-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
|
@ -114,8 +114,8 @@ export default {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
background-color: rgba(0, 0, 0, .5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
transition: opacity .3s;
|
transition: opacity 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 200px;
|
line-height: 200px;
|
||||||
|
@ -129,6 +129,5 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,13 +10,11 @@
|
||||||
action="https://httpbin.org/post"
|
action="https://httpbin.org/post"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload" />
|
<i class="el-icon-upload" />
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">Drag或<em>点击上传</em></div>
|
||||||
Drag或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div v-show="imageUrl.length>0" class="image-preview">
|
<div v-show="imageUrl.length > 0" class="image-preview">
|
||||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
<div v-show="imageUrl.length > 1" class="image-preview-wrapper">
|
||||||
<img :src="imageUrl">
|
<img :src="imageUrl" />
|
||||||
<div class="image-preview-action">
|
<div class="image-preview-action">
|
||||||
<i class="el-icon-delete" @click="rmImage" />
|
<i class="el-icon-delete" @click="rmImage" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,54 +24,56 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getToken } from '@/api/qiniu'
|
import { getToken } from "@/api/qiniu";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SingleImageUpload2',
|
name: "SingleImageUpload2",
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tempUrl: '',
|
tempUrl: "",
|
||||||
dataObj: { token: '', key: '' }
|
dataObj: { token: "", key: "" }
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
imageUrl() {
|
imageUrl() {
|
||||||
return this.value
|
return this.value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
rmImage() {
|
rmImage() {
|
||||||
this.emitInput('')
|
this.emitInput("");
|
||||||
},
|
},
|
||||||
emitInput(val) {
|
emitInput(val) {
|
||||||
this.$emit('input', val)
|
this.$emit("input", val);
|
||||||
},
|
},
|
||||||
handleImageSuccess() {
|
handleImageSuccess() {
|
||||||
this.emitInput(this.tempUrl)
|
this.emitInput(this.tempUrl);
|
||||||
},
|
},
|
||||||
beforeUpload() {
|
beforeUpload() {
|
||||||
const _self = this
|
const _self = this;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getToken().then(response => {
|
getToken()
|
||||||
const key = response.data.qiniu_key
|
.then(response => {
|
||||||
const token = response.data.qiniu_token
|
const key = response.data.qiniu_key;
|
||||||
_self._data.dataObj.token = token
|
const token = response.data.qiniu_token;
|
||||||
_self._data.dataObj.key = key
|
_self._data.dataObj.token = token;
|
||||||
this.tempUrl = response.data.qiniu_url
|
_self._data.dataObj.key = key;
|
||||||
resolve(true)
|
this.tempUrl = response.data.qiniu_url;
|
||||||
}).catch(() => {
|
resolve(true);
|
||||||
reject(false)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -111,8 +111,8 @@ export default {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
background-color: rgba(0, 0, 0, .5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
transition: opacity .3s;
|
transition: opacity 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 200px;
|
line-height: 200px;
|
||||||
|
|
|
@ -10,21 +10,19 @@
|
||||||
action="https://httpbin.org/post"
|
action="https://httpbin.org/post"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload" />
|
<i class="el-icon-upload" />
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
将文件拖到此处,或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div class="image-preview image-app-preview">
|
<div class="image-preview image-app-preview">
|
||||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
<div v-show="imageUrl.length > 1" class="image-preview-wrapper">
|
||||||
<img :src="imageUrl">
|
<img :src="imageUrl" />
|
||||||
<div class="image-preview-action">
|
<div class="image-preview-action">
|
||||||
<i class="el-icon-delete" @click="rmImage" />
|
<i class="el-icon-delete" @click="rmImage" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="image-preview">
|
<div class="image-preview">
|
||||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
<div v-show="imageUrl.length > 1" class="image-preview-wrapper">
|
||||||
<img :src="imageUrl">
|
<img :src="imageUrl" />
|
||||||
<div class="image-preview-action">
|
<div class="image-preview-action">
|
||||||
<i class="el-icon-delete" @click="rmImage" />
|
<i class="el-icon-delete" @click="rmImage" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,55 +32,57 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getToken } from '@/api/qiniu'
|
import { getToken } from "@/api/qiniu";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SingleImageUpload3',
|
name: "SingleImageUpload3",
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tempUrl: '',
|
tempUrl: "",
|
||||||
dataObj: { token: '', key: '' }
|
dataObj: { token: "", key: "" }
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
imageUrl() {
|
imageUrl() {
|
||||||
return this.value
|
return this.value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
rmImage() {
|
rmImage() {
|
||||||
this.emitInput('')
|
this.emitInput("");
|
||||||
},
|
},
|
||||||
emitInput(val) {
|
emitInput(val) {
|
||||||
this.$emit('input', val)
|
this.$emit("input", val);
|
||||||
},
|
},
|
||||||
handleImageSuccess(file) {
|
handleImageSuccess(file) {
|
||||||
this.emitInput(file.files.file)
|
this.emitInput(file.files.file);
|
||||||
},
|
},
|
||||||
beforeUpload() {
|
beforeUpload() {
|
||||||
const _self = this
|
const _self = this;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getToken().then(response => {
|
getToken()
|
||||||
const key = response.data.qiniu_key
|
.then(response => {
|
||||||
const token = response.data.qiniu_token
|
const key = response.data.qiniu_key;
|
||||||
_self._data.dataObj.token = token
|
const token = response.data.qiniu_token;
|
||||||
_self._data.dataObj.key = key
|
_self._data.dataObj.token = token;
|
||||||
this.tempUrl = response.data.qiniu_url
|
_self._data.dataObj.key = key;
|
||||||
resolve(true)
|
this.tempUrl = response.data.qiniu_url;
|
||||||
}).catch(err => {
|
resolve(true);
|
||||||
console.log(err)
|
|
||||||
reject(false)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -122,8 +122,8 @@ export default {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
background-color: rgba(0, 0, 0, .5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
transition: opacity .3s;
|
transition: opacity 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 200px;
|
line-height: 200px;
|
||||||
|
|
|
@ -1,9 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
|
<input
|
||||||
<div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
|
ref="excel-upload-input"
|
||||||
|
class="excel-upload-input"
|
||||||
|
type="file"
|
||||||
|
accept=".xlsx, .xls"
|
||||||
|
@change="handleClick"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="drop"
|
||||||
|
@drop="handleDrop"
|
||||||
|
@dragover="handleDragover"
|
||||||
|
@dragenter="handleDragover"
|
||||||
|
>
|
||||||
Drop excel file here or
|
Drop excel file here or
|
||||||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">
|
<el-button
|
||||||
|
:loading="loading"
|
||||||
|
style="margin-left:16px;"
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
@click="handleUpload"
|
||||||
|
>
|
||||||
Browse
|
Browse
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,12 +28,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import XLSX from 'xlsx'
|
import XLSX from "xlsx";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
beforeUpload: Function, // eslint-disable-line
|
beforeUpload: Function, // eslint-disable-line
|
||||||
onSuccess: Function// eslint-disable-line
|
onSuccess: Function // eslint-disable-line
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -25,105 +42,108 @@ export default {
|
||||||
header: null,
|
header: null,
|
||||||
results: null
|
results: null
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
generateData({ header, results }) {
|
generateData({ header, results }) {
|
||||||
this.excelData.header = header
|
this.excelData.header = header;
|
||||||
this.excelData.results = results
|
this.excelData.results = results;
|
||||||
this.onSuccess && this.onSuccess(this.excelData)
|
this.onSuccess && this.onSuccess(this.excelData);
|
||||||
},
|
},
|
||||||
handleDrop(e) {
|
handleDrop(e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation();
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
if (this.loading) return
|
if (this.loading) return;
|
||||||
const files = e.dataTransfer.files
|
const files = e.dataTransfer.files;
|
||||||
if (files.length !== 1) {
|
if (files.length !== 1) {
|
||||||
this.$message.error('Only support uploading one file!')
|
this.$message.error("Only support uploading one file!");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
const rawFile = files[0] // only use files[0]
|
const rawFile = files[0]; // only use files[0]
|
||||||
|
|
||||||
if (!this.isExcel(rawFile)) {
|
if (!this.isExcel(rawFile)) {
|
||||||
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
|
this.$message.error(
|
||||||
return false
|
"Only supports upload .xlsx, .xls, .csv suffix files"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
this.upload(rawFile)
|
this.upload(rawFile);
|
||||||
e.stopPropagation()
|
e.stopPropagation();
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
handleDragover(e) {
|
handleDragover(e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation();
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
e.dataTransfer.dropEffect = "copy";
|
||||||
},
|
},
|
||||||
handleUpload() {
|
handleUpload() {
|
||||||
this.$refs['excel-upload-input'].click()
|
this.$refs["excel-upload-input"].click();
|
||||||
},
|
},
|
||||||
handleClick(e) {
|
handleClick(e) {
|
||||||
const files = e.target.files
|
const files = e.target.files;
|
||||||
const rawFile = files[0] // only use files[0]
|
const rawFile = files[0]; // only use files[0]
|
||||||
if (!rawFile) return
|
if (!rawFile) return;
|
||||||
this.upload(rawFile)
|
this.upload(rawFile);
|
||||||
},
|
},
|
||||||
upload(rawFile) {
|
upload(rawFile) {
|
||||||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel
|
this.$refs["excel-upload-input"].value = null; // fix can't select the same excel
|
||||||
|
|
||||||
if (!this.beforeUpload) {
|
if (!this.beforeUpload) {
|
||||||
this.readerData(rawFile)
|
this.readerData(rawFile);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
const before = this.beforeUpload(rawFile)
|
const before = this.beforeUpload(rawFile);
|
||||||
if (before) {
|
if (before) {
|
||||||
this.readerData(rawFile)
|
this.readerData(rawFile);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
readerData(rawFile) {
|
readerData(rawFile) {
|
||||||
this.loading = true
|
this.loading = true;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader();
|
||||||
reader.onload = e => {
|
reader.onload = e => {
|
||||||
const data = e.target.result
|
const data = e.target.result;
|
||||||
const workbook = XLSX.read(data, { type: 'array' })
|
const workbook = XLSX.read(data, { type: "array" });
|
||||||
const firstSheetName = workbook.SheetNames[0]
|
const firstSheetName = workbook.SheetNames[0];
|
||||||
const worksheet = workbook.Sheets[firstSheetName]
|
const worksheet = workbook.Sheets[firstSheetName];
|
||||||
const header = this.getHeaderRow(worksheet)
|
const header = this.getHeaderRow(worksheet);
|
||||||
const results = XLSX.utils.sheet_to_json(worksheet)
|
const results = XLSX.utils.sheet_to_json(worksheet);
|
||||||
this.generateData({ header, results })
|
this.generateData({ header, results });
|
||||||
this.loading = false
|
this.loading = false;
|
||||||
resolve()
|
resolve();
|
||||||
}
|
};
|
||||||
reader.readAsArrayBuffer(rawFile)
|
reader.readAsArrayBuffer(rawFile);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
getHeaderRow(sheet) {
|
getHeaderRow(sheet) {
|
||||||
const headers = []
|
const headers = [];
|
||||||
const range = XLSX.utils.decode_range(sheet['!ref'])
|
const range = XLSX.utils.decode_range(sheet["!ref"]);
|
||||||
let C
|
let C;
|
||||||
const R = range.s.r
|
const R = range.s.r;
|
||||||
/* start in the first row */
|
/* start in the first row */
|
||||||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
|
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
|
/* walk every column in the range */
|
||||||
|
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
|
||||||
/* find the cell in the first row */
|
/* find the cell in the first row */
|
||||||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
|
let hdr = "UNKNOWN " + C; // <-- replace with your desired default
|
||||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
|
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
|
||||||
headers.push(hdr)
|
headers.push(hdr);
|
||||||
}
|
}
|
||||||
return headers
|
return headers;
|
||||||
},
|
},
|
||||||
isExcel(file) {
|
isExcel(file) {
|
||||||
return /\.(xlsx|xls|csv)$/.test(file.name)
|
return /\.(xlsx|xls|csv)$/.test(file.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.excel-upload-input{
|
.excel-upload-input {
|
||||||
display: none;
|
display: none;
|
||||||
z-index: -9999;
|
z-index: -9999;
|
||||||
}
|
}
|
||||||
.drop{
|
.drop {
|
||||||
border: 2px dashed #bbb;
|
border: 2px dashed #bbb;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
height: 160px;
|
height: 160px;
|
||||||
|
|
|
@ -1,49 +1,57 @@
|
||||||
// Inspired by https://github.com/Inndy/vue-clipboard2
|
// Inspired by https://github.com/Inndy/vue-clipboard2
|
||||||
const Clipboard = require('clipboard')
|
const Clipboard = require("clipboard");
|
||||||
if (!Clipboard) {
|
if (!Clipboard) {
|
||||||
throw new Error('you should npm install `clipboard` --save at first ')
|
throw new Error("you should npm install `clipboard` --save at first ");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
bind(el, binding) {
|
bind(el, binding) {
|
||||||
if (binding.arg === 'success') {
|
if (binding.arg === "success") {
|
||||||
el._v_clipboard_success = binding.value
|
el._v_clipboard_success = binding.value;
|
||||||
} else if (binding.arg === 'error') {
|
} else if (binding.arg === "error") {
|
||||||
el._v_clipboard_error = binding.value
|
el._v_clipboard_error = binding.value;
|
||||||
} else {
|
} else {
|
||||||
const clipboard = new Clipboard(el, {
|
const clipboard = new Clipboard(el, {
|
||||||
text() { return binding.value },
|
text() {
|
||||||
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
return binding.value;
|
||||||
})
|
},
|
||||||
clipboard.on('success', e => {
|
action() {
|
||||||
const callback = el._v_clipboard_success
|
return binding.arg === "cut" ? "cut" : "copy";
|
||||||
callback && callback(e) // eslint-disable-line
|
}
|
||||||
})
|
});
|
||||||
clipboard.on('error', e => {
|
clipboard.on("success", e => {
|
||||||
const callback = el._v_clipboard_error
|
const callback = el._v_clipboard_success;
|
||||||
callback && callback(e) // eslint-disable-line
|
callback && callback(e); // eslint-disable-line
|
||||||
})
|
});
|
||||||
el._v_clipboard = clipboard
|
clipboard.on("error", e => {
|
||||||
|
const callback = el._v_clipboard_error;
|
||||||
|
callback && callback(e); // eslint-disable-line
|
||||||
|
});
|
||||||
|
el._v_clipboard = clipboard;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update(el, binding) {
|
update(el, binding) {
|
||||||
if (binding.arg === 'success') {
|
if (binding.arg === "success") {
|
||||||
el._v_clipboard_success = binding.value
|
el._v_clipboard_success = binding.value;
|
||||||
} else if (binding.arg === 'error') {
|
} else if (binding.arg === "error") {
|
||||||
el._v_clipboard_error = binding.value
|
el._v_clipboard_error = binding.value;
|
||||||
} else {
|
} else {
|
||||||
el._v_clipboard.text = function() { return binding.value }
|
el._v_clipboard.text = function() {
|
||||||
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
return binding.value;
|
||||||
|
};
|
||||||
|
el._v_clipboard.action = function() {
|
||||||
|
return binding.arg === "cut" ? "cut" : "copy";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
unbind(el, binding) {
|
unbind(el, binding) {
|
||||||
if (binding.arg === 'success') {
|
if (binding.arg === "success") {
|
||||||
delete el._v_clipboard_success
|
delete el._v_clipboard_success;
|
||||||
} else if (binding.arg === 'error') {
|
} else if (binding.arg === "error") {
|
||||||
delete el._v_clipboard_error
|
delete el._v_clipboard_error;
|
||||||
} else {
|
} else {
|
||||||
el._v_clipboard.destroy()
|
el._v_clipboard.destroy();
|
||||||
delete el._v_clipboard
|
delete el._v_clipboard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import Clipboard from './clipboard'
|
import Clipboard from "./clipboard";
|
||||||
|
|
||||||
const install = function(Vue) {
|
const install = function(Vue) {
|
||||||
Vue.directive('Clipboard', Clipboard)
|
Vue.directive("Clipboard", Clipboard);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (window.Vue) {
|
if (window.Vue) {
|
||||||
window.clipboard = Clipboard
|
window.clipboard = Clipboard;
|
||||||
Vue.use(install); // eslint-disable-line
|
Vue.use(install); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipboard.install = install
|
Clipboard.install = install;
|
||||||
export default Clipboard
|
export default Clipboard;
|
||||||
|
|
|
@ -1,77 +1,77 @@
|
||||||
export default {
|
export default {
|
||||||
bind(el, binding, vnode) {
|
bind(el, binding, vnode) {
|
||||||
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
const dialogHeaderEl = el.querySelector(".el-dialog__header");
|
||||||
const dragDom = el.querySelector('.el-dialog')
|
const dragDom = el.querySelector(".el-dialog");
|
||||||
dialogHeaderEl.style.cssText += ';cursor:move;'
|
dialogHeaderEl.style.cssText += ";cursor:move;";
|
||||||
dragDom.style.cssText += ';top:0px;'
|
dragDom.style.cssText += ";top:0px;";
|
||||||
|
|
||||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||||
const getStyle = (function() {
|
const getStyle = (function() {
|
||||||
if (window.document.currentStyle) {
|
if (window.document.currentStyle) {
|
||||||
return (dom, attr) => dom.currentStyle[attr]
|
return (dom, attr) => dom.currentStyle[attr];
|
||||||
} else {
|
} else {
|
||||||
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
return (dom, attr) => getComputedStyle(dom, false)[attr];
|
||||||
}
|
}
|
||||||
})()
|
})();
|
||||||
|
|
||||||
dialogHeaderEl.onmousedown = (e) => {
|
dialogHeaderEl.onmousedown = e => {
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离
|
// 鼠标按下,计算当前元素距离可视区的距离
|
||||||
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
||||||
const disY = e.clientY - dialogHeaderEl.offsetTop
|
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
||||||
|
|
||||||
const dragDomWidth = dragDom.offsetWidth
|
const dragDomWidth = dragDom.offsetWidth;
|
||||||
const dragDomHeight = dragDom.offsetHeight
|
const dragDomHeight = dragDom.offsetHeight;
|
||||||
|
|
||||||
const screenWidth = document.body.clientWidth
|
const screenWidth = document.body.clientWidth;
|
||||||
const screenHeight = document.body.clientHeight
|
const screenHeight = document.body.clientHeight;
|
||||||
|
|
||||||
const minDragDomLeft = dragDom.offsetLeft
|
const minDragDomLeft = dragDom.offsetLeft;
|
||||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
|
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
|
||||||
|
|
||||||
const minDragDomTop = dragDom.offsetTop
|
const minDragDomTop = dragDom.offsetTop;
|
||||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
|
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight;
|
||||||
|
|
||||||
// 获取到的值带px 正则匹配替换
|
// 获取到的值带px 正则匹配替换
|
||||||
let styL = getStyle(dragDom, 'left')
|
let styL = getStyle(dragDom, "left");
|
||||||
let styT = getStyle(dragDom, 'top')
|
let styT = getStyle(dragDom, "top");
|
||||||
|
|
||||||
if (styL.includes('%')) {
|
if (styL.includes("%")) {
|
||||||
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
styL = +document.body.clientWidth * (+styL.replace(/\%/g, "") / 100);
|
||||||
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
styT = +document.body.clientHeight * (+styT.replace(/\%/g, "") / 100);
|
||||||
} else {
|
} else {
|
||||||
styL = +styL.replace(/\px/g, '')
|
styL = +styL.replace(/\px/g, "");
|
||||||
styT = +styT.replace(/\px/g, '')
|
styT = +styT.replace(/\px/g, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
document.onmousemove = function(e) {
|
document.onmousemove = function(e) {
|
||||||
// 通过事件委托,计算移动的距离
|
// 通过事件委托,计算移动的距离
|
||||||
let left = e.clientX - disX
|
let left = e.clientX - disX;
|
||||||
let top = e.clientY - disY
|
let top = e.clientY - disY;
|
||||||
|
|
||||||
// 边界处理
|
// 边界处理
|
||||||
if (-(left) > minDragDomLeft) {
|
if (-left > minDragDomLeft) {
|
||||||
left = -minDragDomLeft
|
left = -minDragDomLeft;
|
||||||
} else if (left > maxDragDomLeft) {
|
} else if (left > maxDragDomLeft) {
|
||||||
left = maxDragDomLeft
|
left = maxDragDomLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-(top) > minDragDomTop) {
|
if (-top > minDragDomTop) {
|
||||||
top = -minDragDomTop
|
top = -minDragDomTop;
|
||||||
} else if (top > maxDragDomTop) {
|
} else if (top > maxDragDomTop) {
|
||||||
top = maxDragDomTop
|
top = maxDragDomTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移动当前元素
|
// 移动当前元素
|
||||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
|
||||||
|
|
||||||
// emit onDrag event
|
// emit onDrag event
|
||||||
vnode.child.$emit('dragDialog')
|
vnode.child.$emit("dragDialog");
|
||||||
}
|
};
|
||||||
|
|
||||||
document.onmouseup = function(e) {
|
document.onmouseup = function(e) {
|
||||||
document.onmousemove = null
|
document.onmousemove = null;
|
||||||
document.onmouseup = null
|
document.onmouseup = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import drag from './drag'
|
import drag from "./drag";
|
||||||
|
|
||||||
const install = function(Vue) {
|
const install = function(Vue) {
|
||||||
Vue.directive('el-drag-dialog', drag)
|
Vue.directive("el-drag-dialog", drag);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (window.Vue) {
|
if (window.Vue) {
|
||||||
window['el-drag-dialog'] = drag
|
window["el-drag-dialog"] = drag;
|
||||||
Vue.use(install); // eslint-disable-line
|
Vue.use(install); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
drag.install = install
|
drag.install = install;
|
||||||
export default drag
|
export default drag;
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
|
import {
|
||||||
|
addResizeListener,
|
||||||
|
removeResizeListener
|
||||||
|
} from "element-ui/src/utils/resize-event";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How to use
|
* How to use
|
||||||
|
@ -8,34 +11,35 @@ import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/re
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const doResize = (el, binding, vnode) => {
|
const doResize = (el, binding, vnode) => {
|
||||||
const { componentInstance: $table } = vnode
|
const { componentInstance: $table } = vnode;
|
||||||
|
|
||||||
const { value } = binding
|
const { value } = binding;
|
||||||
|
|
||||||
if (!$table.height) {
|
if (!$table.height) {
|
||||||
throw new Error(`el-$table must set the height. Such as height='100px'`)
|
throw new Error(`el-$table must set the height. Such as height='100px'`);
|
||||||
}
|
}
|
||||||
const bottomOffset = (value && value.bottomOffset) || 30
|
const bottomOffset = (value && value.bottomOffset) || 30;
|
||||||
|
|
||||||
if (!$table) return
|
if (!$table) return;
|
||||||
|
|
||||||
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
|
const height =
|
||||||
$table.layout.setHeight(height)
|
window.innerHeight - el.getBoundingClientRect().top - bottomOffset;
|
||||||
$table.doLayout()
|
$table.layout.setHeight(height);
|
||||||
}
|
$table.doLayout();
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
bind(el, binding, vnode) {
|
bind(el, binding, vnode) {
|
||||||
el.resizeListener = () => {
|
el.resizeListener = () => {
|
||||||
doResize(el, binding, vnode)
|
doResize(el, binding, vnode);
|
||||||
}
|
};
|
||||||
// parameter 1 is must be "Element" type
|
// parameter 1 is must be "Element" type
|
||||||
addResizeListener(window.document.body, el.resizeListener)
|
addResizeListener(window.document.body, el.resizeListener);
|
||||||
},
|
},
|
||||||
inserted(el, binding, vnode) {
|
inserted(el, binding, vnode) {
|
||||||
doResize(el, binding, vnode)
|
doResize(el, binding, vnode);
|
||||||
},
|
},
|
||||||
unbind(el) {
|
unbind(el) {
|
||||||
removeResizeListener(window.document.body, el.resizeListener)
|
removeResizeListener(window.document.body, el.resizeListener);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import adaptive from './adaptive'
|
import adaptive from "./adaptive";
|
||||||
|
|
||||||
const install = function(Vue) {
|
const install = function(Vue) {
|
||||||
Vue.directive('el-height-adaptive-table', adaptive)
|
Vue.directive("el-height-adaptive-table", adaptive);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (window.Vue) {
|
if (window.Vue) {
|
||||||
window['el-height-adaptive-table'] = adaptive
|
window["el-height-adaptive-table"] = adaptive;
|
||||||
Vue.use(install); // eslint-disable-line
|
Vue.use(install); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
adaptive.install = install
|
adaptive.install = install;
|
||||||
export default adaptive
|
export default adaptive;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import permission from './permission'
|
import permission from "./permission";
|
||||||
|
|
||||||
const install = function(Vue) {
|
const install = function(Vue) {
|
||||||
Vue.directive('permission', permission)
|
Vue.directive("permission", permission);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (window.Vue) {
|
if (window.Vue) {
|
||||||
window['permission'] = permission
|
window["permission"] = permission;
|
||||||
Vue.use(install); // eslint-disable-line
|
Vue.use(install); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
permission.install = install
|
permission.install = install;
|
||||||
export default permission
|
export default permission;
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import store from '@/store'
|
import store from "@/store";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inserted(el, binding, vnode) {
|
inserted(el, binding, vnode) {
|
||||||
const { value } = binding
|
const { value } = binding;
|
||||||
const roles = store.getters && store.getters.roles
|
const roles = store.getters && store.getters.roles;
|
||||||
|
|
||||||
if (value && value instanceof Array && value.length > 0) {
|
if (value && value instanceof Array && value.length > 0) {
|
||||||
const permissionRoles = value
|
const permissionRoles = value;
|
||||||
|
|
||||||
const hasPermission = roles.some(role => {
|
const hasPermission = roles.some(role => {
|
||||||
return permissionRoles.includes(role)
|
return permissionRoles.includes(role);
|
||||||
})
|
});
|
||||||
|
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
el.parentNode && el.parentNode.removeChild(el)
|
el.parentNode && el.parentNode.removeChild(el);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
|
throw new Error(`need roles! Like v-permission="['admin','editor']"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,91 +1,90 @@
|
||||||
const vueSticky = {}
|
const vueSticky = {};
|
||||||
let listenAction
|
let listenAction;
|
||||||
vueSticky.install = Vue => {
|
vueSticky.install = Vue => {
|
||||||
Vue.directive('sticky', {
|
Vue.directive("sticky", {
|
||||||
inserted(el, binding) {
|
inserted(el, binding) {
|
||||||
const params = binding.value || {}
|
const params = binding.value || {};
|
||||||
const stickyTop = params.stickyTop || 0
|
const stickyTop = params.stickyTop || 0;
|
||||||
const zIndex = params.zIndex || 1000
|
const zIndex = params.zIndex || 1000;
|
||||||
const elStyle = el.style
|
const elStyle = el.style;
|
||||||
|
|
||||||
elStyle.position = '-webkit-sticky'
|
elStyle.position = "-webkit-sticky";
|
||||||
elStyle.position = 'sticky'
|
elStyle.position = "sticky";
|
||||||
// if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
|
// if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
|
||||||
// if (~elStyle.position.indexOf('sticky')) {
|
// if (~elStyle.position.indexOf('sticky')) {
|
||||||
// elStyle.top = `${stickyTop}px`;
|
// elStyle.top = `${stickyTop}px`;
|
||||||
// elStyle.zIndex = zIndex;
|
// elStyle.zIndex = zIndex;
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
const elHeight = el.getBoundingClientRect().height
|
const elHeight = el.getBoundingClientRect().height;
|
||||||
const elWidth = el.getBoundingClientRect().width
|
const elWidth = el.getBoundingClientRect().width;
|
||||||
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
|
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`;
|
||||||
|
|
||||||
const parentElm = el.parentNode || document.documentElement
|
const parentElm = el.parentNode || document.documentElement;
|
||||||
const placeholder = document.createElement('div')
|
const placeholder = document.createElement("div");
|
||||||
placeholder.style.display = 'none'
|
placeholder.style.display = "none";
|
||||||
placeholder.style.width = `${elWidth}px`
|
placeholder.style.width = `${elWidth}px`;
|
||||||
placeholder.style.height = `${elHeight}px`
|
placeholder.style.height = `${elHeight}px`;
|
||||||
parentElm.insertBefore(placeholder, el)
|
parentElm.insertBefore(placeholder, el);
|
||||||
|
|
||||||
let active = false
|
let active = false;
|
||||||
|
|
||||||
const getScroll = (target, top) => {
|
const getScroll = (target, top) => {
|
||||||
const prop = top ? 'pageYOffset' : 'pageXOffset'
|
const prop = top ? "pageYOffset" : "pageXOffset";
|
||||||
const method = top ? 'scrollTop' : 'scrollLeft'
|
const method = top ? "scrollTop" : "scrollLeft";
|
||||||
let ret = target[prop]
|
let ret = target[prop];
|
||||||
if (typeof ret !== 'number') {
|
if (typeof ret !== "number") {
|
||||||
ret = window.document.documentElement[method]
|
ret = window.document.documentElement[method];
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
const sticky = () => {
|
const sticky = () => {
|
||||||
if (active) {
|
if (active) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
if (!elStyle.height) {
|
if (!elStyle.height) {
|
||||||
elStyle.height = `${el.offsetHeight}px`
|
elStyle.height = `${el.offsetHeight}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
elStyle.position = 'fixed'
|
elStyle.position = "fixed";
|
||||||
elStyle.width = `${elWidth}px`
|
elStyle.width = `${elWidth}px`;
|
||||||
placeholder.style.display = 'inline-block'
|
placeholder.style.display = "inline-block";
|
||||||
active = true
|
active = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
elStyle.position = ''
|
elStyle.position = "";
|
||||||
placeholder.style.display = 'none'
|
placeholder.style.display = "none";
|
||||||
active = false
|
active = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
const check = () => {
|
const check = () => {
|
||||||
const scrollTop = getScroll(window, true)
|
const scrollTop = getScroll(window, true);
|
||||||
const offsetTop = el.getBoundingClientRect().top
|
const offsetTop = el.getBoundingClientRect().top;
|
||||||
if (offsetTop < stickyTop) {
|
if (offsetTop < stickyTop) {
|
||||||
sticky()
|
sticky();
|
||||||
} else {
|
} else {
|
||||||
if (scrollTop < elHeight + stickyTop) {
|
if (scrollTop < elHeight + stickyTop) {
|
||||||
reset()
|
reset();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
listenAction = () => {
|
listenAction = () => {
|
||||||
check()
|
check();
|
||||||
}
|
};
|
||||||
|
|
||||||
window.addEventListener('scroll', listenAction)
|
window.addEventListener("scroll", listenAction);
|
||||||
},
|
},
|
||||||
|
|
||||||
unbind() {
|
unbind() {
|
||||||
window.removeEventListener('scroll', listenAction)
|
window.removeEventListener("scroll", listenAction);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export default vueSticky
|
|
||||||
|
|
||||||
|
export default vueSticky;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import waves from './waves'
|
import waves from "./waves";
|
||||||
|
|
||||||
const install = function(Vue) {
|
const install = function(Vue) {
|
||||||
Vue.directive('waves', waves)
|
Vue.directive("waves", waves);
|
||||||
}
|
};
|
||||||
|
|
||||||
if (window.Vue) {
|
if (window.Vue) {
|
||||||
window.waves = waves
|
window.waves = waves;
|
||||||
Vue.use(install); // eslint-disable-line
|
Vue.use(install); // eslint-disable-line
|
||||||
}
|
}
|
||||||
|
|
||||||
waves.install = install
|
waves.install = install;
|
||||||
export default waves
|
export default waves;
|
||||||
|
|
|
@ -1,72 +1,80 @@
|
||||||
import './waves.css'
|
import "./waves.css";
|
||||||
|
|
||||||
const context = '@@wavesContext'
|
const context = "@@wavesContext";
|
||||||
|
|
||||||
function handleClick(el, binding) {
|
function handleClick(el, binding) {
|
||||||
function handle(e) {
|
function handle(e) {
|
||||||
const customOpts = Object.assign({}, binding.value)
|
const customOpts = Object.assign({}, binding.value);
|
||||||
const opts = Object.assign({
|
const opts = Object.assign(
|
||||||
|
{
|
||||||
ele: el, // 波纹作用元素
|
ele: el, // 波纹作用元素
|
||||||
type: 'hit', // hit 点击位置扩散 center中心点扩展
|
type: "hit", // hit 点击位置扩散 center中心点扩展
|
||||||
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
color: "rgba(0, 0, 0, 0.15)" // 波纹颜色
|
||||||
},
|
},
|
||||||
customOpts
|
customOpts
|
||||||
)
|
);
|
||||||
const target = opts.ele
|
const target = opts.ele;
|
||||||
if (target) {
|
if (target) {
|
||||||
target.style.position = 'relative'
|
target.style.position = "relative";
|
||||||
target.style.overflow = 'hidden'
|
target.style.overflow = "hidden";
|
||||||
const rect = target.getBoundingClientRect()
|
const rect = target.getBoundingClientRect();
|
||||||
let ripple = target.querySelector('.waves-ripple')
|
let ripple = target.querySelector(".waves-ripple");
|
||||||
if (!ripple) {
|
if (!ripple) {
|
||||||
ripple = document.createElement('span')
|
ripple = document.createElement("span");
|
||||||
ripple.className = 'waves-ripple'
|
ripple.className = "waves-ripple";
|
||||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
|
ripple.style.height = ripple.style.width =
|
||||||
target.appendChild(ripple)
|
Math.max(rect.width, rect.height) + "px";
|
||||||
|
target.appendChild(ripple);
|
||||||
} else {
|
} else {
|
||||||
ripple.className = 'waves-ripple'
|
ripple.className = "waves-ripple";
|
||||||
}
|
}
|
||||||
switch (opts.type) {
|
switch (opts.type) {
|
||||||
case 'center':
|
case "center":
|
||||||
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
|
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + "px";
|
||||||
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
|
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + "px";
|
||||||
break
|
break;
|
||||||
default:
|
default:
|
||||||
ripple.style.top =
|
ripple.style.top =
|
||||||
(e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop ||
|
(e.pageY -
|
||||||
document.body.scrollTop) + 'px'
|
rect.top -
|
||||||
|
ripple.offsetHeight / 2 -
|
||||||
|
document.documentElement.scrollTop || document.body.scrollTop) +
|
||||||
|
"px";
|
||||||
ripple.style.left =
|
ripple.style.left =
|
||||||
(e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft ||
|
(e.pageX -
|
||||||
document.body.scrollLeft) + 'px'
|
rect.left -
|
||||||
|
ripple.offsetWidth / 2 -
|
||||||
|
document.documentElement.scrollLeft || document.body.scrollLeft) +
|
||||||
|
"px";
|
||||||
}
|
}
|
||||||
ripple.style.backgroundColor = opts.color
|
ripple.style.backgroundColor = opts.color;
|
||||||
ripple.className = 'waves-ripple z-active'
|
ripple.className = "waves-ripple z-active";
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!el[context]) {
|
if (!el[context]) {
|
||||||
el[context] = {
|
el[context] = {
|
||||||
removeHandle: handle
|
removeHandle: handle
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
el[context].removeHandle = handle
|
el[context].removeHandle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
bind(el, binding) {
|
bind(el, binding) {
|
||||||
el.addEventListener('click', handleClick(el, binding), false)
|
el.addEventListener("click", handleClick(el, binding), false);
|
||||||
},
|
},
|
||||||
update(el, binding) {
|
update(el, binding) {
|
||||||
el.removeEventListener('click', el[context].removeHandle, false)
|
el.removeEventListener("click", el[context].removeHandle, false);
|
||||||
el.addEventListener('click', handleClick(el, binding), false)
|
el.addEventListener("click", handleClick(el, binding), false);
|
||||||
},
|
},
|
||||||
unbind(el) {
|
unbind(el) {
|
||||||
el.removeEventListener('click', el[context].removeHandle, false)
|
el.removeEventListener("click", el[context].removeHandle, false);
|
||||||
el[context] = null
|
el[context] = null;
|
||||||
delete el[context]
|
delete el[context];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// import parseTime, formatTime and set to filter
|
// import parseTime, formatTime and set to filter
|
||||||
export { parseTime, formatTime } from '@/utils'
|
export { parseTime, formatTime } from "@/utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show plural label if time is plural number
|
* Show plural label if time is plural number
|
||||||
|
@ -9,22 +9,22 @@ export { parseTime, formatTime } from '@/utils'
|
||||||
*/
|
*/
|
||||||
function pluralize(time, label) {
|
function pluralize(time, label) {
|
||||||
if (time === 1) {
|
if (time === 1) {
|
||||||
return time + label
|
return time + label;
|
||||||
}
|
}
|
||||||
return time + label + 's'
|
return time + label + "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} time
|
* @param {number} time
|
||||||
*/
|
*/
|
||||||
export function timeAgo(time) {
|
export function timeAgo(time) {
|
||||||
const between = Date.now() / 1000 - Number(time)
|
const between = Date.now() / 1000 - Number(time);
|
||||||
if (between < 3600) {
|
if (between < 3600) {
|
||||||
return pluralize(~~(between / 60), ' minute')
|
return pluralize(~~(between / 60), " minute");
|
||||||
} else if (between < 86400) {
|
} else if (between < 86400) {
|
||||||
return pluralize(~~(between / 3600), ' hour')
|
return pluralize(~~(between / 3600), " hour");
|
||||||
} else {
|
} else {
|
||||||
return pluralize(~~(between / 86400), ' day')
|
return pluralize(~~(between / 86400), " day");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,19 +36,23 @@ export function timeAgo(time) {
|
||||||
*/
|
*/
|
||||||
export function numberFormatter(num, digits) {
|
export function numberFormatter(num, digits) {
|
||||||
const si = [
|
const si = [
|
||||||
{ value: 1E18, symbol: 'E' },
|
{ value: 1e18, symbol: "E" },
|
||||||
{ value: 1E15, symbol: 'P' },
|
{ value: 1e15, symbol: "P" },
|
||||||
{ value: 1E12, symbol: 'T' },
|
{ value: 1e12, symbol: "T" },
|
||||||
{ value: 1E9, symbol: 'G' },
|
{ value: 1e9, symbol: "G" },
|
||||||
{ value: 1E6, symbol: 'M' },
|
{ value: 1e6, symbol: "M" },
|
||||||
{ value: 1E3, symbol: 'k' }
|
{ value: 1e3, symbol: "k" }
|
||||||
]
|
];
|
||||||
for (let i = 0; i < si.length; i++) {
|
for (let i = 0; i < si.length; i++) {
|
||||||
if (num >= si[i].value) {
|
if (num >= si[i].value) {
|
||||||
return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
|
return (
|
||||||
|
(num / si[i].value + 0.1)
|
||||||
|
.toFixed(digits)
|
||||||
|
.replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1") + si[i].symbol
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return num.toString()
|
return num.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +60,9 @@ export function numberFormatter(num, digits) {
|
||||||
* @param {number} num
|
* @param {number} num
|
||||||
*/
|
*/
|
||||||
export function toThousandFilter(num) {
|
export function toThousandFilter(num) {
|
||||||
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
return (+num || 0)
|
||||||
|
.toString()
|
||||||
|
.replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ","));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,5 +70,5 @@ export function toThousandFilter(num) {
|
||||||
* @param {String} string
|
* @param {String} string
|
||||||
*/
|
*/
|
||||||
export function uppercaseFirst(string) {
|
export function uppercaseFirst(string) {
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
import SvgIcon from '@/components/SvgIcon'// svg component
|
import SvgIcon from "@/components/SvgIcon"; // svg component
|
||||||
|
|
||||||
// register globally
|
// register globally
|
||||||
Vue.component('svg-icon', SvgIcon)
|
Vue.component("svg-icon", SvgIcon);
|
||||||
|
|
||||||
const req = require.context('./svg', false, /\.svg$/)
|
const req = require.context("./svg", false, /\.svg$/);
|
||||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
const requireAll = requireContext => requireContext.keys().map(requireContext);
|
||||||
requireAll(req)
|
requireAll(req);
|
||||||
|
|
|
@ -10,16 +10,16 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'AppMain',
|
name: "AppMain",
|
||||||
computed: {
|
computed: {
|
||||||
cachedViews() {
|
cachedViews() {
|
||||||
return this.$store.state.tagsView.cachedViews
|
return this.$store.state.tagsView.cachedViews;
|
||||||
},
|
},
|
||||||
key() {
|
key() {
|
||||||
return this.$route.path
|
return this.$route.path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -31,7 +31,7 @@ export default {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header+.app-main {
|
.fixed-header + .app-main {
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ export default {
|
||||||
min-height: calc(100vh - 84px);
|
min-height: calc(100vh - 84px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header+.app-main {
|
.fixed-header + .app-main {
|
||||||
padding-top: 84px;
|
padding-top: 84px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
<hamburger
|
||||||
|
id="hamburger-container"
|
||||||
|
:is-active="sidebar.opened"
|
||||||
|
class="hamburger-container"
|
||||||
|
@toggleClick="toggleSideBar"
|
||||||
|
/>
|
||||||
|
|
||||||
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
|
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
|
||||||
|
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
<template v-if="device!=='mobile'">
|
<template v-if="device !== 'mobile'">
|
||||||
<search id="header-search" class="right-menu-item" />
|
<search id="header-search" class="right-menu-item" />
|
||||||
|
|
||||||
<error-log class="errLog-container right-menu-item hover-effect" />
|
<error-log class="errLog-container right-menu-item hover-effect" />
|
||||||
|
@ -15,12 +20,14 @@
|
||||||
<el-tooltip content="Global Size" effect="dark" placement="bottom">
|
<el-tooltip content="Global Size" effect="dark" placement="bottom">
|
||||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
|
<el-dropdown
|
||||||
|
class="avatar-container right-menu-item hover-effect"
|
||||||
|
trigger="click"
|
||||||
|
>
|
||||||
<div class="avatar-wrapper">
|
<div class="avatar-wrapper">
|
||||||
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
|
<img :src="avatar + '?imageView2/1/w/80/h/80'" class="user-avatar" />
|
||||||
<i class="el-icon-caret-bottom" />
|
<i class="el-icon-caret-bottom" />
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
@ -30,10 +37,16 @@
|
||||||
<router-link to="/">
|
<router-link to="/">
|
||||||
<el-dropdown-item>Dashboard</el-dropdown-item>
|
<el-dropdown-item>Dashboard</el-dropdown-item>
|
||||||
</router-link>
|
</router-link>
|
||||||
<a target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://github.com/PanJiaChen/vue-element-admin/"
|
||||||
|
>
|
||||||
<el-dropdown-item>Github</el-dropdown-item>
|
<el-dropdown-item>Github</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://panjiachen.github.io/vue-element-admin-site/#/"
|
||||||
|
>
|
||||||
<el-dropdown-item>Docs</el-dropdown-item>
|
<el-dropdown-item>Docs</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<el-dropdown-item divided>
|
<el-dropdown-item divided>
|
||||||
|
@ -46,13 +59,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from "vuex";
|
||||||
import Breadcrumb from '@/components/Breadcrumb'
|
import Breadcrumb from "@/components/Breadcrumb";
|
||||||
import Hamburger from '@/components/Hamburger'
|
import Hamburger from "@/components/Hamburger";
|
||||||
import ErrorLog from '@/components/ErrorLog'
|
import ErrorLog from "@/components/ErrorLog";
|
||||||
import Screenfull from '@/components/Screenfull'
|
import Screenfull from "@/components/Screenfull";
|
||||||
import SizeSelect from '@/components/SizeSelect'
|
import SizeSelect from "@/components/SizeSelect";
|
||||||
import Search from '@/components/HeaderSearch'
|
import Search from "@/components/HeaderSearch";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -64,22 +77,18 @@ export default {
|
||||||
Search
|
Search
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters(["sidebar", "avatar", "device"])
|
||||||
'sidebar',
|
|
||||||
'avatar',
|
|
||||||
'device'
|
|
||||||
])
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleSideBar() {
|
toggleSideBar() {
|
||||||
this.$store.dispatch('app/toggleSideBar')
|
this.$store.dispatch("app/toggleSideBar");
|
||||||
},
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
await this.$store.dispatch('user/logout')
|
await this.$store.dispatch("user/logout");
|
||||||
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
|
this.$router.push(`/login?redirect=${this.$route.fullPath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -88,18 +97,18 @@ export default {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
|
|
||||||
.hamburger-container {
|
.hamburger-container {
|
||||||
line-height: 46px;
|
line-height: 46px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
float: left;
|
float: left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .3s;
|
transition: background 0.3s;
|
||||||
-webkit-tap-highlight-color:transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, .025)
|
background: rgba(0, 0, 0, 0.025);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,10 +140,10 @@ export default {
|
||||||
|
|
||||||
&.hover-effect {
|
&.hover-effect {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background .3s;
|
transition: background 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(0, 0, 0, .025)
|
background: rgba(0, 0, 0, 0.025);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
<span>Theme Color</span>
|
<span>Theme Color</span>
|
||||||
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
|
<theme-picker
|
||||||
|
style="float: right;height: 26px;margin: -3px 8px 0 0;"
|
||||||
|
@change="themeChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="drawer-item">
|
<div class="drawer-item">
|
||||||
|
@ -22,63 +25,62 @@
|
||||||
<span>Sidebar Logo</span>
|
<span>Sidebar Logo</span>
|
||||||
<el-switch v-model="sidebarLogo" class="drawer-switch" />
|
<el-switch v-model="sidebarLogo" class="drawer-switch" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ThemePicker from '@/components/ThemePicker'
|
import ThemePicker from "@/components/ThemePicker";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ThemePicker },
|
components: { ThemePicker },
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
fixedHeader: {
|
fixedHeader: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.fixedHeader
|
return this.$store.state.settings.fixedHeader;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
this.$store.dispatch("settings/changeSetting", {
|
||||||
key: 'fixedHeader',
|
key: "fixedHeader",
|
||||||
value: val
|
value: val
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tagsView: {
|
tagsView: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.tagsView
|
return this.$store.state.settings.tagsView;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
this.$store.dispatch("settings/changeSetting", {
|
||||||
key: 'tagsView',
|
key: "tagsView",
|
||||||
value: val
|
value: val
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sidebarLogo: {
|
sidebarLogo: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.state.settings.sidebarLogo
|
return this.$store.state.settings.sidebarLogo;
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
this.$store.dispatch("settings/changeSetting", {
|
||||||
key: 'sidebarLogo',
|
key: "sidebarLogo",
|
||||||
value: val
|
value: val
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
themeChange(val) {
|
themeChange(val) {
|
||||||
this.$store.dispatch('settings/changeSetting', {
|
this.$store.dispatch("settings/changeSetting", {
|
||||||
key: 'theme',
|
key: "theme",
|
||||||
value: val
|
value: val
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -90,19 +92,19 @@ export default {
|
||||||
|
|
||||||
.drawer-title {
|
.drawer-title {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
color: rgba(0, 0, 0, .85);
|
color: rgba(0, 0, 0, 0.85);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-item {
|
.drawer-item {
|
||||||
color: rgba(0, 0, 0, .65);
|
color: rgba(0, 0, 0, 0.65);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-switch {
|
.drawer-switch {
|
||||||
float: right
|
float: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
device() {
|
device() {
|
||||||
return this.$store.state.app.device
|
return this.$store.state.app.device;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// In order to fix the click on menu on the ios device will trigger the mouseleave bug
|
// In order to fix the click on menu on the ios device will trigger the mouseleave bug
|
||||||
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
|
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
|
||||||
this.fixBugIniOS()
|
this.fixBugIniOS();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fixBugIniOS() {
|
fixBugIniOS() {
|
||||||
const $subMenu = this.$refs.subMenu
|
const $subMenu = this.$refs.subMenu;
|
||||||
if ($subMenu) {
|
if ($subMenu) {
|
||||||
const handleMouseleave = $subMenu.handleMouseleave
|
const handleMouseleave = $subMenu.handleMouseleave;
|
||||||
$subMenu.handleMouseleave = (e) => {
|
$subMenu.handleMouseleave = e => {
|
||||||
if (this.device === 'mobile') {
|
if (this.device === "mobile") {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
handleMouseleave(e)
|
handleMouseleave(e);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'MenuItem',
|
name: "MenuItem",
|
||||||
functional: true,
|
functional: true,
|
||||||
props: {
|
props: {
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render(h, context) {
|
render(h, context) {
|
||||||
const { icon, title } = context.props
|
const { icon, title } = context.props;
|
||||||
const vnodes = []
|
const vnodes = [];
|
||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
vnodes.push(<svg-icon icon-class={icon}/>)
|
vnodes.push(<svg-icon icon-class={icon} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
vnodes.push(<span slot='title'>{(title)}</span>)
|
vnodes.push(<span slot="title">{title}</span>);
|
||||||
}
|
}
|
||||||
return vnodes
|
return vnodes;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- eslint-disable vue/require-component-is -->
|
<!-- eslint-disable vue/require-component-is -->
|
||||||
<component v-bind="linkProps(to)">
|
<component v-bind="linkProps(to)">
|
||||||
|
@ -7,7 +6,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { isExternal } from '@/utils/validate'
|
import { isExternal } from "@/utils/validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
@ -20,17 +19,17 @@ export default {
|
||||||
linkProps(url) {
|
linkProps(url) {
|
||||||
if (isExternal(url)) {
|
if (isExternal(url)) {
|
||||||
return {
|
return {
|
||||||
is: 'a',
|
is: "a",
|
||||||
href: url,
|
href: url,
|
||||||
target: '_blank',
|
target: "_blank",
|
||||||
rel: 'noopener'
|
rel: "noopener"
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
is: 'router-link',
|
is: "router-link",
|
||||||
to: url
|
to: url
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
|
<div class="sidebar-logo-container" :class="{ collapse: collapse }">
|
||||||
<transition name="sidebarLogoFade">
|
<transition name="sidebarLogoFade">
|
||||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
<router-link
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
v-if="collapse"
|
||||||
<h1 v-else class="sidebar-title">{{ title }} </h1>
|
key="collapse"
|
||||||
|
class="sidebar-logo-link"
|
||||||
|
to="/"
|
||||||
|
>
|
||||||
|
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||||
|
<h1 v-else class="sidebar-title">{{ title }}</h1>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||||
<h1 class="sidebar-title">{{ title }} </h1>
|
<h1 class="sidebar-title">{{ title }}</h1>
|
||||||
</router-link>
|
</router-link>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,7 +20,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'SidebarLogo',
|
name: "SidebarLogo",
|
||||||
props: {
|
props: {
|
||||||
collapse: {
|
collapse: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -24,11 +29,12 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: 'Vue Element Admin',
|
title: "Vue Element Admin",
|
||||||
logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
|
logo:
|
||||||
|
"https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -1,16 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!item.hidden" class="menu-wrapper">
|
<div v-if="!item.hidden" class="menu-wrapper">
|
||||||
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
<template
|
||||||
|
v-if="
|
||||||
|
hasOneShowingChild(item.children, item) &&
|
||||||
|
(!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
|
||||||
|
!item.alwaysShow
|
||||||
|
"
|
||||||
|
>
|
||||||
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
|
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
|
||||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
<el-menu-item
|
||||||
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
|
:index="resolvePath(onlyOneChild.path)"
|
||||||
|
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||||
|
>
|
||||||
|
<item
|
||||||
|
:icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"
|
||||||
|
:title="onlyOneChild.meta.title"
|
||||||
|
/>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</app-link>
|
</app-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
<el-submenu
|
||||||
|
v-else
|
||||||
|
ref="subMenu"
|
||||||
|
:index="resolvePath(item.path)"
|
||||||
|
popper-append-to-body
|
||||||
|
>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
|
<item
|
||||||
|
v-if="item.meta"
|
||||||
|
:icon="item.meta && item.meta.icon"
|
||||||
|
:title="item.meta.title"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<sidebar-item
|
<sidebar-item
|
||||||
v-for="child in item.children"
|
v-for="child in item.children"
|
||||||
|
@ -25,14 +46,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import path from 'path'
|
import path from "path";
|
||||||
import { isExternal } from '@/utils/validate'
|
import { isExternal } from "@/utils/validate";
|
||||||
import Item from './Item'
|
import Item from "./Item";
|
||||||
import AppLink from './Link'
|
import AppLink from "./Link";
|
||||||
import FixiOSBug from './FixiOSBug'
|
import FixiOSBug from "./FixiOSBug";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SidebarItem',
|
name: "SidebarItem",
|
||||||
components: { Item, AppLink },
|
components: { Item, AppLink },
|
||||||
mixins: [FixiOSBug],
|
mixins: [FixiOSBug],
|
||||||
props: {
|
props: {
|
||||||
|
@ -47,49 +68,49 @@ export default {
|
||||||
},
|
},
|
||||||
basePath: {
|
basePath: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
|
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
|
||||||
// TODO: refactor with render function
|
// TODO: refactor with render function
|
||||||
this.onlyOneChild = null
|
this.onlyOneChild = null;
|
||||||
return {}
|
return {};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hasOneShowingChild(children = [], parent) {
|
hasOneShowingChild(children = [], parent) {
|
||||||
const showingChildren = children.filter(item => {
|
const showingChildren = children.filter(item => {
|
||||||
if (item.hidden) {
|
if (item.hidden) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// Temp set(will be used if only has one showing child)
|
// Temp set(will be used if only has one showing child)
|
||||||
this.onlyOneChild = item
|
this.onlyOneChild = item;
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// When there is only one child router, the child router is displayed by default
|
// When there is only one child router, the child router is displayed by default
|
||||||
if (showingChildren.length === 1) {
|
if (showingChildren.length === 1) {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show parent if there are no child router to display
|
// Show parent if there are no child router to display
|
||||||
if (showingChildren.length === 0) {
|
if (showingChildren.length === 0) {
|
||||||
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
|
this.onlyOneChild = { ...parent, path: "", noShowingChildren: true };
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false;
|
||||||
},
|
},
|
||||||
resolvePath(routePath) {
|
resolvePath(routePath) {
|
||||||
if (isExternal(routePath)) {
|
if (isExternal(routePath)) {
|
||||||
return routePath
|
return routePath;
|
||||||
}
|
}
|
||||||
if (isExternal(this.basePath)) {
|
if (isExternal(this.basePath)) {
|
||||||
return this.basePath
|
return this.basePath;
|
||||||
}
|
}
|
||||||
return path.resolve(this.basePath, routePath)
|
return path.resolve(this.basePath, routePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{'has-logo':showLogo}">
|
<div :class="{ 'has-logo': showLogo }">
|
||||||
<logo v-if="showLogo" :collapse="isCollapse" />
|
<logo v-if="showLogo" :collapse="isCollapse" />
|
||||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||||
<el-menu
|
<el-menu
|
||||||
|
@ -12,43 +12,45 @@
|
||||||
:collapse-transition="false"
|
:collapse-transition="false"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
>
|
>
|
||||||
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
|
<sidebar-item
|
||||||
|
v-for="route in permission_routes"
|
||||||
|
:key="route.path"
|
||||||
|
:item="route"
|
||||||
|
:base-path="route.path"
|
||||||
|
/>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from "vuex";
|
||||||
import Logo from './Logo'
|
import Logo from "./Logo";
|
||||||
import SidebarItem from './SidebarItem'
|
import SidebarItem from "./SidebarItem";
|
||||||
import variables from '@/styles/variables.scss'
|
import variables from "@/styles/variables.scss";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { SidebarItem, Logo },
|
components: { SidebarItem, Logo },
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters(["permission_routes", "sidebar"]),
|
||||||
'permission_routes',
|
|
||||||
'sidebar'
|
|
||||||
]),
|
|
||||||
activeMenu() {
|
activeMenu() {
|
||||||
const route = this.$route
|
const route = this.$route;
|
||||||
const { meta, path } = route
|
const { meta, path } = route;
|
||||||
// if set path, the sidebar will highlight the path you set
|
// if set path, the sidebar will highlight the path you set
|
||||||
if (meta.activeMenu) {
|
if (meta.activeMenu) {
|
||||||
return meta.activeMenu
|
return meta.activeMenu;
|
||||||
}
|
}
|
||||||
return path
|
return path;
|
||||||
},
|
},
|
||||||
showLogo() {
|
showLogo() {
|
||||||
return this.$store.state.settings.sidebarLogo
|
return this.$store.state.settings.sidebarLogo;
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return variables
|
return variables;
|
||||||
},
|
},
|
||||||
isCollapse() {
|
isCollapse() {
|
||||||
return !this.sidebar.opened
|
return !this.sidebar.opened;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,70 +1,81 @@
|
||||||
<template>
|
<template>
|
||||||
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
|
<el-scrollbar
|
||||||
|
ref="scrollContainer"
|
||||||
|
:vertical="false"
|
||||||
|
class="scroll-container"
|
||||||
|
@wheel.native.prevent="handleScroll"
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const tagAndTagSpacing = 4 // tagAndTagSpacing
|
const tagAndTagSpacing = 4; // tagAndTagSpacing
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ScrollPane',
|
name: "ScrollPane",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
left: 0
|
left: 0
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
scrollWrapper() {
|
scrollWrapper() {
|
||||||
return this.$refs.scrollContainer.$refs.wrap
|
return this.$refs.scrollContainer.$refs.wrap;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll(e) {
|
handleScroll(e) {
|
||||||
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
const eventDelta = e.wheelDelta || -e.deltaY * 40;
|
||||||
const $scrollWrapper = this.scrollWrapper
|
const $scrollWrapper = this.scrollWrapper;
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4;
|
||||||
},
|
},
|
||||||
moveToTarget(currentTag) {
|
moveToTarget(currentTag) {
|
||||||
const $container = this.$refs.scrollContainer.$el
|
const $container = this.$refs.scrollContainer.$el;
|
||||||
const $containerWidth = $container.offsetWidth
|
const $containerWidth = $container.offsetWidth;
|
||||||
const $scrollWrapper = this.scrollWrapper
|
const $scrollWrapper = this.scrollWrapper;
|
||||||
const tagList = this.$parent.$refs.tag
|
const tagList = this.$parent.$refs.tag;
|
||||||
|
|
||||||
let firstTag = null
|
let firstTag = null;
|
||||||
let lastTag = null
|
let lastTag = null;
|
||||||
|
|
||||||
// find first tag and last tag
|
// find first tag and last tag
|
||||||
if (tagList.length > 0) {
|
if (tagList.length > 0) {
|
||||||
firstTag = tagList[0]
|
firstTag = tagList[0];
|
||||||
lastTag = tagList[tagList.length - 1]
|
lastTag = tagList[tagList.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstTag === currentTag) {
|
if (firstTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = 0
|
$scrollWrapper.scrollLeft = 0;
|
||||||
} else if (lastTag === currentTag) {
|
} else if (lastTag === currentTag) {
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
|
$scrollWrapper.scrollLeft =
|
||||||
|
$scrollWrapper.scrollWidth - $containerWidth;
|
||||||
} else {
|
} else {
|
||||||
// find preTag and nextTag
|
// find preTag and nextTag
|
||||||
const currentIndex = tagList.findIndex(item => item === currentTag)
|
const currentIndex = tagList.findIndex(item => item === currentTag);
|
||||||
const prevTag = tagList[currentIndex - 1]
|
const prevTag = tagList[currentIndex - 1];
|
||||||
const nextTag = tagList[currentIndex + 1]
|
const nextTag = tagList[currentIndex + 1];
|
||||||
|
|
||||||
// the tag's offsetLeft after of nextTag
|
// the tag's offsetLeft after of nextTag
|
||||||
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
|
const afterNextTagOffsetLeft =
|
||||||
|
nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing;
|
||||||
|
|
||||||
// the tag's offsetLeft before of prevTag
|
// the tag's offsetLeft before of prevTag
|
||||||
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
|
const beforePrevTagOffsetLeft =
|
||||||
|
prevTag.$el.offsetLeft - tagAndTagSpacing;
|
||||||
|
|
||||||
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
if (
|
||||||
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
|
afterNextTagOffsetLeft >
|
||||||
|
$scrollWrapper.scrollLeft + $containerWidth
|
||||||
|
) {
|
||||||
|
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth;
|
||||||
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
||||||
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
|
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -73,7 +84,7 @@ export default {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/deep/ {
|
::v-deep {
|
||||||
.el-scrollbar__bar {
|
.el-scrollbar__bar {
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,33 @@
|
||||||
v-for="tag in visitedViews"
|
v-for="tag in visitedViews"
|
||||||
ref="tag"
|
ref="tag"
|
||||||
:key="tag.path"
|
:key="tag.path"
|
||||||
:class="isActive(tag)?'active':''"
|
:class="isActive(tag) ? 'active' : ''"
|
||||||
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||||
tag="span"
|
tag="span"
|
||||||
class="tags-view-item"
|
class="tags-view-item"
|
||||||
@click.middle.native="closeSelectedTag(tag)"
|
@click.middle.native="closeSelectedTag(tag)"
|
||||||
@contextmenu.prevent.native="openMenu(tag,$event)"
|
@contextmenu.prevent.native="openMenu(tag, $event)"
|
||||||
>
|
>
|
||||||
{{ tag.title }}
|
{{ tag.title }}
|
||||||
<span v-if="!tag.meta.affix" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
|
<span
|
||||||
|
v-if="!tag.meta.affix"
|
||||||
|
class="el-icon-close"
|
||||||
|
@click.prevent.stop="closeSelectedTag(tag)"
|
||||||
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</scroll-pane>
|
</scroll-pane>
|
||||||
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
|
<ul
|
||||||
|
v-show="visible"
|
||||||
|
:style="{ left: left + 'px', top: top + 'px' }"
|
||||||
|
class="contextmenu"
|
||||||
|
>
|
||||||
<li @click="refreshSelectedTag(selectedTag)">Refresh</li>
|
<li @click="refreshSelectedTag(selectedTag)">Refresh</li>
|
||||||
<li v-if="!(selectedTag.meta&&selectedTag.meta.affix)" @click="closeSelectedTag(selectedTag)">Close</li>
|
<li
|
||||||
|
v-if="!(selectedTag.meta && selectedTag.meta.affix)"
|
||||||
|
@click="closeSelectedTag(selectedTag)"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</li>
|
||||||
<li @click="closeOthersTags">Close Others</li>
|
<li @click="closeOthersTags">Close Others</li>
|
||||||
<li @click="closeAllTags(selectedTag)">Close All</li>
|
<li @click="closeAllTags(selectedTag)">Close All</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -26,8 +39,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ScrollPane from './ScrollPane'
|
import ScrollPane from "./ScrollPane";
|
||||||
import path from 'path'
|
import path from "path";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ScrollPane },
|
components: { ScrollPane },
|
||||||
|
@ -38,157 +51,161 @@ export default {
|
||||||
left: 0,
|
left: 0,
|
||||||
selectedTag: {},
|
selectedTag: {},
|
||||||
affixTags: []
|
affixTags: []
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
visitedViews() {
|
visitedViews() {
|
||||||
return this.$store.state.tagsView.visitedViews
|
return this.$store.state.tagsView.visitedViews;
|
||||||
},
|
},
|
||||||
routes() {
|
routes() {
|
||||||
return this.$store.state.permission.routes
|
return this.$store.state.permission.routes;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
$route() {
|
$route() {
|
||||||
this.addTags()
|
this.addTags();
|
||||||
this.moveToCurrentTag()
|
this.moveToCurrentTag();
|
||||||
},
|
},
|
||||||
visible(value) {
|
visible(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
document.body.addEventListener('click', this.closeMenu)
|
document.body.addEventListener("click", this.closeMenu);
|
||||||
} else {
|
} else {
|
||||||
document.body.removeEventListener('click', this.closeMenu)
|
document.body.removeEventListener("click", this.closeMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initTags()
|
this.initTags();
|
||||||
this.addTags()
|
this.addTags();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isActive(route) {
|
isActive(route) {
|
||||||
return route.path === this.$route.path
|
return route.path === this.$route.path;
|
||||||
},
|
},
|
||||||
filterAffixTags(routes, basePath = '/') {
|
filterAffixTags(routes, basePath = "/") {
|
||||||
let tags = []
|
let tags = [];
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
if (route.meta && route.meta.affix) {
|
if (route.meta && route.meta.affix) {
|
||||||
const tagPath = path.resolve(basePath, route.path)
|
const tagPath = path.resolve(basePath, route.path);
|
||||||
tags.push({
|
tags.push({
|
||||||
fullPath: tagPath,
|
fullPath: tagPath,
|
||||||
path: tagPath,
|
path: tagPath,
|
||||||
name: route.name,
|
name: route.name,
|
||||||
meta: { ...route.meta }
|
meta: { ...route.meta }
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
if (route.children) {
|
if (route.children) {
|
||||||
const tempTags = this.filterAffixTags(route.children, route.path)
|
const tempTags = this.filterAffixTags(route.children, route.path);
|
||||||
if (tempTags.length >= 1) {
|
if (tempTags.length >= 1) {
|
||||||
tags = [...tags, ...tempTags]
|
tags = [...tags, ...tempTags];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
return tags
|
return tags;
|
||||||
},
|
},
|
||||||
initTags() {
|
initTags() {
|
||||||
const affixTags = this.affixTags = this.filterAffixTags(this.routes)
|
const affixTags = (this.affixTags = this.filterAffixTags(this.routes));
|
||||||
for (const tag of affixTags) {
|
for (const tag of affixTags) {
|
||||||
// Must have tag name
|
// Must have tag name
|
||||||
if (tag.name) {
|
if (tag.name) {
|
||||||
this.$store.dispatch('tagsView/addVisitedView', tag)
|
this.$store.dispatch("tagsView/addVisitedView", tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addTags() {
|
addTags() {
|
||||||
const { name } = this.$route
|
const { name } = this.$route;
|
||||||
if (name) {
|
if (name) {
|
||||||
this.$store.dispatch('tagsView/addView', this.$route)
|
this.$store.dispatch("tagsView/addView", this.$route);
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
},
|
},
|
||||||
moveToCurrentTag() {
|
moveToCurrentTag() {
|
||||||
const tags = this.$refs.tag
|
const tags = this.$refs.tag;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
if (tag.to.path === this.$route.path) {
|
if (tag.to.path === this.$route.path) {
|
||||||
this.$refs.scrollPane.moveToTarget(tag)
|
this.$refs.scrollPane.moveToTarget(tag);
|
||||||
// when query is different then update
|
// when query is different then update
|
||||||
if (tag.to.fullPath !== this.$route.fullPath) {
|
if (tag.to.fullPath !== this.$route.fullPath) {
|
||||||
this.$store.dispatch('tagsView/updateVisitedView', this.$route)
|
this.$store.dispatch("tagsView/updateVisitedView", this.$route);
|
||||||
}
|
}
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
refreshSelectedTag(view) {
|
refreshSelectedTag(view) {
|
||||||
this.$store.dispatch('tagsView/delCachedView', view).then(() => {
|
this.$store.dispatch("tagsView/delCachedView", view).then(() => {
|
||||||
const { fullPath } = view
|
const { fullPath } = view;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$router.replace({
|
this.$router.replace({
|
||||||
path: '/redirect' + fullPath
|
path: "/redirect" + fullPath
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
closeSelectedTag(view) {
|
closeSelectedTag(view) {
|
||||||
this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
|
this.$store
|
||||||
|
.dispatch("tagsView/delView", view)
|
||||||
|
.then(({ visitedViews }) => {
|
||||||
if (this.isActive(view)) {
|
if (this.isActive(view)) {
|
||||||
this.toLastView(visitedViews, view)
|
this.toLastView(visitedViews, view);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
closeOthersTags() {
|
closeOthersTags() {
|
||||||
this.$router.push(this.selectedTag)
|
this.$router.push(this.selectedTag);
|
||||||
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
|
this.$store
|
||||||
this.moveToCurrentTag()
|
.dispatch("tagsView/delOthersViews", this.selectedTag)
|
||||||
})
|
.then(() => {
|
||||||
|
this.moveToCurrentTag();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
closeAllTags(view) {
|
closeAllTags(view) {
|
||||||
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
|
this.$store.dispatch("tagsView/delAllViews").then(({ visitedViews }) => {
|
||||||
if (this.affixTags.some(tag => tag.path === view.path)) {
|
if (this.affixTags.some(tag => tag.path === view.path)) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.toLastView(visitedViews, view)
|
this.toLastView(visitedViews, view);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
toLastView(visitedViews, view) {
|
toLastView(visitedViews, view) {
|
||||||
const latestView = visitedViews.slice(-1)[0]
|
const latestView = visitedViews.slice(-1)[0];
|
||||||
if (latestView) {
|
if (latestView) {
|
||||||
this.$router.push(latestView)
|
this.$router.push(latestView);
|
||||||
} else {
|
} else {
|
||||||
// now the default is to redirect to the home page if there is no tags-view,
|
// now the default is to redirect to the home page if there is no tags-view,
|
||||||
// you can adjust it according to your needs.
|
// you can adjust it according to your needs.
|
||||||
if (view.name === 'Dashboard') {
|
if (view.name === "Dashboard") {
|
||||||
// to reload home page
|
// to reload home page
|
||||||
this.$router.replace({ path: '/redirect' + view.fullPath })
|
this.$router.replace({ path: "/redirect" + view.fullPath });
|
||||||
} else {
|
} else {
|
||||||
this.$router.push('/')
|
this.$router.push("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openMenu(tag, e) {
|
openMenu(tag, e) {
|
||||||
const menuMinWidth = 105
|
const menuMinWidth = 105;
|
||||||
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
|
const offsetLeft = this.$el.getBoundingClientRect().left; // container margin left
|
||||||
const offsetWidth = this.$el.offsetWidth // container width
|
const offsetWidth = this.$el.offsetWidth; // container width
|
||||||
const maxLeft = offsetWidth - menuMinWidth // left boundary
|
const maxLeft = offsetWidth - menuMinWidth; // left boundary
|
||||||
const left = e.clientX - offsetLeft + 15 // 15: margin right
|
const left = e.clientX - offsetLeft + 15; // 15: margin right
|
||||||
|
|
||||||
if (left > maxLeft) {
|
if (left > maxLeft) {
|
||||||
this.left = maxLeft
|
this.left = maxLeft;
|
||||||
} else {
|
} else {
|
||||||
this.left = left
|
this.left = left;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.top = e.clientY
|
this.top = e.clientY;
|
||||||
this.visible = true
|
this.visible = true;
|
||||||
this.selectedTag = tag
|
this.selectedTag = tag;
|
||||||
},
|
},
|
||||||
closeMenu() {
|
closeMenu() {
|
||||||
this.visible = false
|
this.visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -197,7 +214,7 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-bottom: 1px solid #d8dce5;
|
border-bottom: 1px solid #d8dce5;
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
|
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
|
||||||
.tags-view-wrapper {
|
.tags-view-wrapper {
|
||||||
.tags-view-item {
|
.tags-view-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -223,7 +240,7 @@ export default {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-color: #42b983;
|
border-color: #42b983;
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: "";
|
||||||
background: #fff;
|
background: #fff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
@ -246,7 +263,7 @@ export default {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #333;
|
color: #333;
|
||||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
|
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
||||||
li {
|
li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 7px 16px;
|
padding: 7px 16px;
|
||||||
|
@ -269,10 +286,10 @@ export default {
|
||||||
vertical-align: 2px;
|
vertical-align: 2px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: all .3s cubic-bezier(.645, .045, .355, 1);
|
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
transform-origin: 100% 50%;
|
transform-origin: 100% 50%;
|
||||||
&:before {
|
&:before {
|
||||||
transform: scale(.6);
|
transform: scale(0.6);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: -3px;
|
vertical-align: -3px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export { default as AppMain } from './AppMain'
|
export { default as AppMain } from "./AppMain";
|
||||||
export { default as Navbar } from './Navbar'
|
export { default as Navbar } from "./Navbar";
|
||||||
export { default as Settings } from './Settings'
|
export { default as Settings } from "./Settings";
|
||||||
export { default as Sidebar } from './Sidebar/index.vue'
|
export { default as Sidebar } from "./Sidebar/index.vue";
|
||||||
export { default as TagsView } from './TagsView/index.vue'
|
export { default as TagsView } from "./TagsView/index.vue";
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="classObj" class="app-wrapper">
|
<div :class="classObj" class="app-wrapper">
|
||||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
<div
|
||||||
|
v-if="device === 'mobile' && sidebar.opened"
|
||||||
|
class="drawer-bg"
|
||||||
|
@click="handleClickOutside"
|
||||||
|
/>
|
||||||
<sidebar class="sidebar-container" />
|
<sidebar class="sidebar-container" />
|
||||||
<div :class="{hasTagsView:needTagsView}" class="main-container">
|
<div :class="{ hasTagsView: needTagsView }" class="main-container">
|
||||||
<div :class="{'fixed-header':fixedHeader}">
|
<div :class="{ 'fixed-header': fixedHeader }">
|
||||||
<navbar />
|
<navbar />
|
||||||
<tags-view v-if="needTagsView" />
|
<tags-view v-if="needTagsView" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,13 +20,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import RightPanel from '@/components/RightPanel'
|
import RightPanel from "@/components/RightPanel";
|
||||||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
|
import { AppMain, Navbar, Settings, Sidebar, TagsView } from "./components";
|
||||||
import ResizeMixin from './mixin/ResizeHandler'
|
import ResizeMixin from "./mixin/ResizeHandler";
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Layout',
|
name: "Layout",
|
||||||
components: {
|
components: {
|
||||||
AppMain,
|
AppMain,
|
||||||
Navbar,
|
Navbar,
|
||||||
|
@ -45,23 +49,23 @@ export default {
|
||||||
hideSidebar: !this.sidebar.opened,
|
hideSidebar: !this.sidebar.opened,
|
||||||
openSidebar: this.sidebar.opened,
|
openSidebar: this.sidebar.opened,
|
||||||
withoutAnimation: this.sidebar.withoutAnimation,
|
withoutAnimation: this.sidebar.withoutAnimation,
|
||||||
mobile: this.device === 'mobile'
|
mobile: this.device === "mobile"
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClickOutside() {
|
handleClickOutside() {
|
||||||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "~@/styles/mixin.scss";
|
@import "~@/styles/mixin.scss";
|
||||||
@import "~@/styles/variables.scss";
|
@import "~@/styles/variables.scss";
|
||||||
|
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -71,9 +75,9 @@ export default {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-bg {
|
.drawer-bg {
|
||||||
background: #000;
|
background: #000;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -81,22 +85,22 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fixed-header {
|
.fixed-header {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
width: calc(100% - #{$sideBarWidth});
|
width: calc(100% - #{$sideBarWidth});
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hideSidebar .fixed-header {
|
.hideSidebar .fixed-header {
|
||||||
width: calc(100% - 54px)
|
width: calc(100% - 54px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile .fixed-header {
|
.mobile .fixed-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
import store from '@/store'
|
import store from "@/store";
|
||||||
|
|
||||||
const { body } = document
|
const { body } = document;
|
||||||
const WIDTH = 992 // refer to Bootstrap's responsive design
|
const WIDTH = 992; // refer to Bootstrap's responsive design
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
watch: {
|
watch: {
|
||||||
$route(route) {
|
$route(route) {
|
||||||
if (this.device === 'mobile' && this.sidebar.opened) {
|
if (this.device === "mobile" && this.sidebar.opened) {
|
||||||
store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
store.dispatch("app/closeSideBar", { withoutAnimation: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
window.addEventListener('resize', this.$_resizeHandler)
|
window.addEventListener("resize", this.$_resizeHandler);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('resize', this.$_resizeHandler)
|
window.removeEventListener("resize", this.$_resizeHandler);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const isMobile = this.$_isMobile()
|
const isMobile = this.$_isMobile();
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
store.dispatch('app/toggleDevice', 'mobile')
|
store.dispatch("app/toggleDevice", "mobile");
|
||||||
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
store.dispatch("app/closeSideBar", { withoutAnimation: true });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// use $_ for mixins properties
|
// use $_ for mixins properties
|
||||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||||
$_isMobile() {
|
$_isMobile() {
|
||||||
const rect = body.getBoundingClientRect()
|
const rect = body.getBoundingClientRect();
|
||||||
return rect.width - 1 < WIDTH
|
return rect.width - 1 < WIDTH;
|
||||||
},
|
},
|
||||||
$_resizeHandler() {
|
$_resizeHandler() {
|
||||||
if (!document.hidden) {
|
if (!document.hidden) {
|
||||||
const isMobile = this.$_isMobile()
|
const isMobile = this.$_isMobile();
|
||||||
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
|
store.dispatch("app/toggleDevice", isMobile ? "mobile" : "desktop");
|
||||||
|
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
store.dispatch("app/closeSideBar", { withoutAnimation: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
46
src/main.js
46
src/main.js
|
@ -1,23 +1,23 @@
|
||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
|
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
import 'normalize.css/normalize.css' // a modern alternative to CSS resets
|
import "normalize.css/normalize.css"; // a modern alternative to CSS resets
|
||||||
|
|
||||||
import Element from 'element-ui'
|
import Element from "element-ui";
|
||||||
import './styles/element-variables.scss'
|
import "./styles/element-variables.scss";
|
||||||
|
|
||||||
import '@/styles/index.scss' // global css
|
import "@/styles/index.scss"; // global css
|
||||||
|
|
||||||
import App from './App'
|
import App from "./App";
|
||||||
import store from './store'
|
import store from "./store";
|
||||||
import router from './router'
|
import router from "./router";
|
||||||
|
|
||||||
import './icons' // icon
|
import "./icons"; // icon
|
||||||
import './permission' // permission control
|
import "./permission"; // permission control
|
||||||
import './utils/error-log' // error log
|
import "./utils/error-log"; // error log
|
||||||
|
|
||||||
import * as filters from './filters' // global filters
|
import * as filters from "./filters"; // global filters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you don't want to use mock-server
|
* If you don't want to use mock-server
|
||||||
|
@ -27,25 +27,25 @@ import * as filters from './filters' // global filters
|
||||||
* Currently MockJs will be used in the production environment,
|
* Currently MockJs will be used in the production environment,
|
||||||
* please remove it before going online! ! !
|
* please remove it before going online! ! !
|
||||||
*/
|
*/
|
||||||
import { mockXHR } from '../mock'
|
import { mockXHR } from "../mock";
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === "production") {
|
||||||
mockXHR()
|
mockXHR();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.use(Element, {
|
Vue.use(Element, {
|
||||||
size: Cookies.get('size') || 'medium' // set element-ui default size
|
size: Cookies.get("size") || "medium" // set element-ui default size
|
||||||
})
|
});
|
||||||
|
|
||||||
// register global utility filters
|
// register global utility filters
|
||||||
Object.keys(filters).forEach(key => {
|
Object.keys(filters).forEach(key => {
|
||||||
Vue.filter(key, filters[key])
|
Vue.filter(key, filters[key]);
|
||||||
})
|
});
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: "#app",
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,56 +1,59 @@
|
||||||
import router from './router'
|
import router from "./router";
|
||||||
import store from './store'
|
import store from "./store";
|
||||||
import { Message } from 'element-ui'
|
import { Message } from "element-ui";
|
||||||
import NProgress from 'nprogress' // progress bar
|
import NProgress from "nprogress"; // progress bar
|
||||||
import 'nprogress/nprogress.css' // progress bar style
|
import "nprogress/nprogress.css"; // progress bar style
|
||||||
import { getToken } from '@/utils/auth' // get token from cookie
|
import { getToken } from "@/utils/auth"; // get token from cookie
|
||||||
import getPageTitle from '@/utils/get-page-title'
|
import getPageTitle from "@/utils/get-page-title";
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false }) // NProgress Configuration
|
NProgress.configure({ showSpinner: false }); // NProgress Configuration
|
||||||
|
|
||||||
const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
|
const whiteList = ["/login", "/auth-redirect"]; // no redirect whitelist
|
||||||
|
|
||||||
router.beforeEach(async(to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
// start progress bar
|
// start progress bar
|
||||||
NProgress.start()
|
NProgress.start();
|
||||||
|
|
||||||
// set page title
|
// set page title
|
||||||
document.title = getPageTitle(to.meta.title)
|
document.title = getPageTitle(to.meta.title);
|
||||||
|
|
||||||
// determine whether the user has logged in
|
// determine whether the user has logged in
|
||||||
const hasToken = getToken()
|
const hasToken = getToken();
|
||||||
|
|
||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
if (to.path === '/login') {
|
if (to.path === "/login") {
|
||||||
// if is logged in, redirect to the home page
|
// if is logged in, redirect to the home page
|
||||||
next({ path: '/' })
|
next({ path: "/" });
|
||||||
NProgress.done()
|
NProgress.done();
|
||||||
} else {
|
} else {
|
||||||
// determine whether the user has obtained his permission roles through getInfo
|
// determine whether the user has obtained his permission roles through getInfo
|
||||||
const hasRoles = store.getters.roles && store.getters.roles.length > 0
|
const hasRoles = store.getters.roles && store.getters.roles.length > 0;
|
||||||
if (hasRoles) {
|
if (hasRoles) {
|
||||||
next()
|
next();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// get user info
|
// get user info
|
||||||
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
|
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
|
||||||
const { roles } = await store.dispatch('user/getInfo')
|
const { roles } = await store.dispatch("user/getInfo");
|
||||||
|
|
||||||
// generate accessible routes map based on roles
|
// generate accessible routes map based on roles
|
||||||
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
|
const accessRoutes = await store.dispatch(
|
||||||
|
"permission/generateRoutes",
|
||||||
|
roles
|
||||||
|
);
|
||||||
|
|
||||||
// dynamically add accessible routes
|
// dynamically add accessible routes
|
||||||
router.addRoutes(accessRoutes)
|
router.addRoutes(accessRoutes);
|
||||||
|
|
||||||
// hack method to ensure that addRoutes is complete
|
// hack method to ensure that addRoutes is complete
|
||||||
// set the replace: true, so the navigation will not leave a history record
|
// set the replace: true, so the navigation will not leave a history record
|
||||||
next({ ...to, replace: true })
|
next({ ...to, replace: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// remove token and go to login page to re-login
|
// remove token and go to login page to re-login
|
||||||
await store.dispatch('user/resetToken')
|
await store.dispatch("user/resetToken");
|
||||||
Message.error(error || 'Has Error')
|
Message.error(error || "Has Error");
|
||||||
next(`/login?redirect=${to.path}`)
|
next(`/login?redirect=${to.path}`);
|
||||||
NProgress.done()
|
NProgress.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,16 +62,16 @@ router.beforeEach(async(to, from, next) => {
|
||||||
|
|
||||||
if (whiteList.indexOf(to.path) !== -1) {
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
// in the free login whitelist, go directly
|
// in the free login whitelist, go directly
|
||||||
next()
|
next();
|
||||||
} else {
|
} else {
|
||||||
// other pages that do not have permission to access are redirected to the login page.
|
// other pages that do not have permission to access are redirected to the login page.
|
||||||
next(`/login?redirect=${to.path}`)
|
next(`/login?redirect=${to.path}`);
|
||||||
NProgress.done()
|
NProgress.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
router.afterEach(() => {
|
router.afterEach(() => {
|
||||||
// finish progress bar
|
// finish progress bar
|
||||||
NProgress.done()
|
NProgress.done();
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
import Router from 'vue-router'
|
import Router from "vue-router";
|
||||||
|
|
||||||
Vue.use(Router)
|
Vue.use(Router);
|
||||||
|
|
||||||
/* Layout */
|
/* Layout */
|
||||||
import Layout from '@/layout'
|
import Layout from "@/layout";
|
||||||
|
|
||||||
/* Router Modules */
|
/* Router Modules */
|
||||||
import componentsRouter from './modules/components'
|
import componentsRouter from "./modules/components";
|
||||||
import chartsRouter from './modules/charts'
|
import chartsRouter from "./modules/charts";
|
||||||
import tableRouter from './modules/table'
|
import tableRouter from "./modules/table";
|
||||||
import nestedRouter from './modules/nested'
|
import nestedRouter from "./modules/nested";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: sub-menu only appear when route children.length >= 1
|
* Note: sub-menu only appear when route children.length >= 1
|
||||||
|
@ -40,89 +40,89 @@ import nestedRouter from './modules/nested'
|
||||||
*/
|
*/
|
||||||
export const constantRoutes = [
|
export const constantRoutes = [
|
||||||
{
|
{
|
||||||
path: '/redirect',
|
path: "/redirect",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
hidden: true,
|
hidden: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/redirect/:path*',
|
path: "/redirect/:path*",
|
||||||
component: () => import('@/views/redirect/index')
|
component: () => import("@/views/redirect/index")
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: "/login",
|
||||||
component: () => import('@/views/login/index'),
|
component: () => import("@/views/login/index"),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth-redirect',
|
path: "/auth-redirect",
|
||||||
component: () => import('@/views/login/auth-redirect'),
|
component: () => import("@/views/login/auth-redirect"),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/404',
|
path: "/404",
|
||||||
component: () => import('@/views/error-page/404'),
|
component: () => import("@/views/error-page/404"),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/401',
|
path: "/401",
|
||||||
component: () => import('@/views/error-page/401'),
|
component: () => import("@/views/error-page/401"),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: "/",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/dashboard',
|
redirect: "/dashboard",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: "dashboard",
|
||||||
component: () => import('@/views/dashboard/index'),
|
component: () => import("@/views/dashboard/index"),
|
||||||
name: 'Dashboard',
|
name: "Dashboard",
|
||||||
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
|
meta: { title: "Dashboard", icon: "dashboard", affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/documentation',
|
path: "/documentation",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/documentation/index'),
|
component: () => import("@/views/documentation/index"),
|
||||||
name: 'Documentation',
|
name: "Documentation",
|
||||||
meta: { title: 'Documentation', icon: 'documentation', affix: true }
|
meta: { title: "Documentation", icon: "documentation", affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/guide',
|
path: "/guide",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/guide/index',
|
redirect: "/guide/index",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/guide/index'),
|
component: () => import("@/views/guide/index"),
|
||||||
name: 'Guide',
|
name: "Guide",
|
||||||
meta: { title: 'Guide', icon: 'guide', noCache: true }
|
meta: { title: "Guide", icon: "guide", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/profile',
|
path: "/profile",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/profile/index',
|
redirect: "/profile/index",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/profile/index'),
|
component: () => import("@/views/profile/index"),
|
||||||
name: 'Profile',
|
name: "Profile",
|
||||||
meta: { title: 'Profile', icon: 'user', noCache: true }
|
meta: { title: "Profile", icon: "user", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* asyncRoutes
|
* asyncRoutes
|
||||||
|
@ -130,56 +130,56 @@ export const constantRoutes = [
|
||||||
*/
|
*/
|
||||||
export const asyncRoutes = [
|
export const asyncRoutes = [
|
||||||
{
|
{
|
||||||
path: '/permission',
|
path: "/permission",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/permission/page',
|
redirect: "/permission/page",
|
||||||
alwaysShow: true, // will always show the root menu
|
alwaysShow: true, // will always show the root menu
|
||||||
name: 'Permission',
|
name: "Permission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Permission',
|
title: "Permission",
|
||||||
icon: 'lock',
|
icon: "lock",
|
||||||
roles: ['admin', 'editor'] // you can set roles in root nav
|
roles: ["admin", "editor"] // you can set roles in root nav
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'page',
|
path: "page",
|
||||||
component: () => import('@/views/permission/page'),
|
component: () => import("@/views/permission/page"),
|
||||||
name: 'PagePermission',
|
name: "PagePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Page Permission',
|
title: "Page Permission",
|
||||||
roles: ['admin'] // or you can only set roles in sub nav
|
roles: ["admin"] // or you can only set roles in sub nav
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'directive',
|
path: "directive",
|
||||||
component: () => import('@/views/permission/directive'),
|
component: () => import("@/views/permission/directive"),
|
||||||
name: 'DirectivePermission',
|
name: "DirectivePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Directive Permission'
|
title: "Directive Permission"
|
||||||
// if do not set roles, means: this page does not require permission
|
// if do not set roles, means: this page does not require permission
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'role',
|
path: "role",
|
||||||
component: () => import('@/views/permission/role'),
|
component: () => import("@/views/permission/role"),
|
||||||
name: 'RolePermission',
|
name: "RolePermission",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Role Permission',
|
title: "Role Permission",
|
||||||
roles: ['admin']
|
roles: ["admin"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/icon',
|
path: "/icon",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/icons/index'),
|
component: () => import("@/views/icons/index"),
|
||||||
name: 'Icons',
|
name: "Icons",
|
||||||
meta: { title: 'Icons', icon: 'icon', noCache: true }
|
meta: { title: "Icons", icon: "icon", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -191,214 +191,219 @@ export const asyncRoutes = [
|
||||||
tableRouter,
|
tableRouter,
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/example',
|
path: "/example",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/example/list',
|
redirect: "/example/list",
|
||||||
name: 'Example',
|
name: "Example",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Example',
|
title: "Example",
|
||||||
icon: 'example'
|
icon: "example"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: "create",
|
||||||
component: () => import('@/views/example/create'),
|
component: () => import("@/views/example/create"),
|
||||||
name: 'CreateArticle',
|
name: "CreateArticle",
|
||||||
meta: { title: 'Create Article', icon: 'edit' }
|
meta: { title: "Create Article", icon: "edit" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'edit/:id(\\d+)',
|
path: "edit/:id(\\d+)",
|
||||||
component: () => import('@/views/example/edit'),
|
component: () => import("@/views/example/edit"),
|
||||||
name: 'EditArticle',
|
name: "EditArticle",
|
||||||
meta: { title: 'Edit Article', noCache: true, activeMenu: '/example/list' },
|
meta: {
|
||||||
|
title: "Edit Article",
|
||||||
|
noCache: true,
|
||||||
|
activeMenu: "/example/list"
|
||||||
|
},
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: "list",
|
||||||
component: () => import('@/views/example/list'),
|
component: () => import("@/views/example/list"),
|
||||||
name: 'ArticleList',
|
name: "ArticleList",
|
||||||
meta: { title: 'Article List', icon: 'list' }
|
meta: { title: "Article List", icon: "list" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/tab',
|
path: "/tab",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/tab/index'),
|
component: () => import("@/views/tab/index"),
|
||||||
name: 'Tab',
|
name: "Tab",
|
||||||
meta: { title: 'Tab', icon: 'tab' }
|
meta: { title: "Tab", icon: "tab" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/error',
|
path: "/error",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'ErrorPages',
|
name: "ErrorPages",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Error Pages',
|
title: "Error Pages",
|
||||||
icon: '404'
|
icon: "404"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '401',
|
path: "401",
|
||||||
component: () => import('@/views/error-page/401'),
|
component: () => import("@/views/error-page/401"),
|
||||||
name: 'Page401',
|
name: "Page401",
|
||||||
meta: { title: '401', noCache: true }
|
meta: { title: "401", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '404',
|
path: "404",
|
||||||
component: () => import('@/views/error-page/404'),
|
component: () => import("@/views/error-page/404"),
|
||||||
name: 'Page404',
|
name: "Page404",
|
||||||
meta: { title: '404', noCache: true }
|
meta: { title: "404", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/error-log',
|
path: "/error-log",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'log',
|
path: "log",
|
||||||
component: () => import('@/views/error-log/index'),
|
component: () => import("@/views/error-log/index"),
|
||||||
name: 'ErrorLog',
|
name: "ErrorLog",
|
||||||
meta: { title: 'Error Log', icon: 'bug' }
|
meta: { title: "Error Log", icon: "bug" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/excel',
|
path: "/excel",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/excel/export-excel',
|
redirect: "/excel/export-excel",
|
||||||
name: 'Excel',
|
name: "Excel",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Excel',
|
title: "Excel",
|
||||||
icon: 'excel'
|
icon: "excel"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'export-excel',
|
path: "export-excel",
|
||||||
component: () => import('@/views/excel/export-excel'),
|
component: () => import("@/views/excel/export-excel"),
|
||||||
name: 'ExportExcel',
|
name: "ExportExcel",
|
||||||
meta: { title: 'Export Excel' }
|
meta: { title: "Export Excel" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'export-selected-excel',
|
path: "export-selected-excel",
|
||||||
component: () => import('@/views/excel/select-excel'),
|
component: () => import("@/views/excel/select-excel"),
|
||||||
name: 'SelectExcel',
|
name: "SelectExcel",
|
||||||
meta: { title: 'Export Selected' }
|
meta: { title: "Export Selected" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'export-merge-header',
|
path: "export-merge-header",
|
||||||
component: () => import('@/views/excel/merge-header'),
|
component: () => import("@/views/excel/merge-header"),
|
||||||
name: 'MergeHeader',
|
name: "MergeHeader",
|
||||||
meta: { title: 'Merge Header' }
|
meta: { title: "Merge Header" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'upload-excel',
|
path: "upload-excel",
|
||||||
component: () => import('@/views/excel/upload-excel'),
|
component: () => import("@/views/excel/upload-excel"),
|
||||||
name: 'UploadExcel',
|
name: "UploadExcel",
|
||||||
meta: { title: 'Upload Excel' }
|
meta: { title: "Upload Excel" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/zip',
|
path: "/zip",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/zip/download',
|
redirect: "/zip/download",
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
name: 'Zip',
|
name: "Zip",
|
||||||
meta: { title: 'Zip', icon: 'zip' },
|
meta: { title: "Zip", icon: "zip" },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'download',
|
path: "download",
|
||||||
component: () => import('@/views/zip/index'),
|
component: () => import("@/views/zip/index"),
|
||||||
name: 'ExportZip',
|
name: "ExportZip",
|
||||||
meta: { title: 'Export Zip' }
|
meta: { title: "Export Zip" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/pdf',
|
path: "/pdf",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/pdf/index',
|
redirect: "/pdf/index",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/pdf/index'),
|
component: () => import("@/views/pdf/index"),
|
||||||
name: 'PDF',
|
name: "PDF",
|
||||||
meta: { title: 'PDF', icon: 'pdf' }
|
meta: { title: "PDF", icon: "pdf" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/pdf/download',
|
path: "/pdf/download",
|
||||||
component: () => import('@/views/pdf/download'),
|
component: () => import("@/views/pdf/download"),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/theme',
|
path: "/theme",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/theme/index'),
|
component: () => import("@/views/theme/index"),
|
||||||
name: 'Theme',
|
name: "Theme",
|
||||||
meta: { title: 'Theme', icon: 'theme' }
|
meta: { title: "Theme", icon: "theme" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/clipboard',
|
path: "/clipboard",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: "index",
|
||||||
component: () => import('@/views/clipboard/index'),
|
component: () => import("@/views/clipboard/index"),
|
||||||
name: 'ClipboardDemo',
|
name: "ClipboardDemo",
|
||||||
meta: { title: 'Clipboard', icon: 'clipboard' }
|
meta: { title: "Clipboard", icon: "clipboard" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: 'external-link',
|
path: "external-link",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'https://github.com/PanJiaChen/vue-element-admin',
|
path: "https://github.com/PanJiaChen/vue-element-admin",
|
||||||
meta: { title: 'External Link', icon: 'link' }
|
meta: { title: "External Link", icon: "link" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// 404 page must be placed at the end !!!
|
// 404 page must be placed at the end !!!
|
||||||
{ path: '*', redirect: '/404', hidden: true }
|
{ path: "*", redirect: "/404", hidden: true }
|
||||||
]
|
];
|
||||||
|
|
||||||
const createRouter = () => new Router({
|
const createRouter = () =>
|
||||||
|
new Router({
|
||||||
// mode: 'history', // require service support
|
// mode: 'history', // require service support
|
||||||
scrollBehavior: () => ({ y: 0 }),
|
scrollBehavior: () => ({ y: 0 }),
|
||||||
routes: constantRoutes
|
routes: constantRoutes
|
||||||
})
|
});
|
||||||
|
|
||||||
const router = createRouter()
|
const router = createRouter();
|
||||||
|
|
||||||
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
|
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
|
||||||
export function resetRouter() {
|
export function resetRouter() {
|
||||||
const newRouter = createRouter()
|
const newRouter = createRouter();
|
||||||
router.matcher = newRouter.matcher // reset router
|
router.matcher = newRouter.matcher; // reset router
|
||||||
}
|
}
|
||||||
|
|
||||||
export default router
|
export default router;
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
/** When your routing table is too long, you can split it into small modules**/
|
/** When your routing table is too long, you can split it into small modules**/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from "@/layout";
|
||||||
|
|
||||||
const chartsRouter = {
|
const chartsRouter = {
|
||||||
path: '/charts',
|
path: "/charts",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'Charts',
|
name: "Charts",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Charts',
|
title: "Charts",
|
||||||
icon: 'chart'
|
icon: "chart"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'keyboard',
|
path: "keyboard",
|
||||||
component: () => import('@/views/charts/keyboard'),
|
component: () => import("@/views/charts/keyboard"),
|
||||||
name: 'KeyboardChart',
|
name: "KeyboardChart",
|
||||||
meta: { title: 'Keyboard Chart', noCache: true }
|
meta: { title: "Keyboard Chart", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'line',
|
path: "line",
|
||||||
component: () => import('@/views/charts/line'),
|
component: () => import("@/views/charts/line"),
|
||||||
name: 'LineChart',
|
name: "LineChart",
|
||||||
meta: { title: 'Line Chart', noCache: true }
|
meta: { title: "Line Chart", noCache: true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'mix-chart',
|
path: "mix-chart",
|
||||||
component: () => import('@/views/charts/mix-chart'),
|
component: () => import("@/views/charts/mix-chart"),
|
||||||
name: 'MixChart',
|
name: "MixChart",
|
||||||
meta: { title: 'Mix Chart', noCache: true }
|
meta: { title: "Mix Chart", noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
|
|
||||||
export default chartsRouter
|
export default chartsRouter;
|
||||||
|
|
|
@ -1,102 +1,102 @@
|
||||||
/** When your routing table is too long, you can split it into small modules **/
|
/** When your routing table is too long, you can split it into small modules **/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from "@/layout";
|
||||||
|
|
||||||
const componentsRouter = {
|
const componentsRouter = {
|
||||||
path: '/components',
|
path: "/components",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: 'noRedirect',
|
redirect: "noRedirect",
|
||||||
name: 'ComponentDemo',
|
name: "ComponentDemo",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Components',
|
title: "Components",
|
||||||
icon: 'component'
|
icon: "component"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'tinymce',
|
path: "tinymce",
|
||||||
component: () => import('@/views/components-demo/tinymce'),
|
component: () => import("@/views/components-demo/tinymce"),
|
||||||
name: 'TinymceDemo',
|
name: "TinymceDemo",
|
||||||
meta: { title: 'Tinymce' }
|
meta: { title: "Tinymce" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'markdown',
|
path: "markdown",
|
||||||
component: () => import('@/views/components-demo/markdown'),
|
component: () => import("@/views/components-demo/markdown"),
|
||||||
name: 'MarkdownDemo',
|
name: "MarkdownDemo",
|
||||||
meta: { title: 'Markdown' }
|
meta: { title: "Markdown" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'json-editor',
|
path: "json-editor",
|
||||||
component: () => import('@/views/components-demo/json-editor'),
|
component: () => import("@/views/components-demo/json-editor"),
|
||||||
name: 'JsonEditorDemo',
|
name: "JsonEditorDemo",
|
||||||
meta: { title: 'JSON Editor' }
|
meta: { title: "JSON Editor" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'split-pane',
|
path: "split-pane",
|
||||||
component: () => import('@/views/components-demo/split-pane'),
|
component: () => import("@/views/components-demo/split-pane"),
|
||||||
name: 'SplitpaneDemo',
|
name: "SplitpaneDemo",
|
||||||
meta: { title: 'SplitPane' }
|
meta: { title: "SplitPane" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'avatar-upload',
|
path: "avatar-upload",
|
||||||
component: () => import('@/views/components-demo/avatar-upload'),
|
component: () => import("@/views/components-demo/avatar-upload"),
|
||||||
name: 'AvatarUploadDemo',
|
name: "AvatarUploadDemo",
|
||||||
meta: { title: 'Upload' }
|
meta: { title: "Upload" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dropzone',
|
path: "dropzone",
|
||||||
component: () => import('@/views/components-demo/dropzone'),
|
component: () => import("@/views/components-demo/dropzone"),
|
||||||
name: 'DropzoneDemo',
|
name: "DropzoneDemo",
|
||||||
meta: { title: 'Dropzone' }
|
meta: { title: "Dropzone" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'sticky',
|
path: "sticky",
|
||||||
component: () => import('@/views/components-demo/sticky'),
|
component: () => import("@/views/components-demo/sticky"),
|
||||||
name: 'StickyDemo',
|
name: "StickyDemo",
|
||||||
meta: { title: 'Sticky' }
|
meta: { title: "Sticky" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'count-to',
|
path: "count-to",
|
||||||
component: () => import('@/views/components-demo/count-to'),
|
component: () => import("@/views/components-demo/count-to"),
|
||||||
name: 'CountToDemo',
|
name: "CountToDemo",
|
||||||
meta: { title: 'Count To' }
|
meta: { title: "Count To" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'mixin',
|
path: "mixin",
|
||||||
component: () => import('@/views/components-demo/mixin'),
|
component: () => import("@/views/components-demo/mixin"),
|
||||||
name: 'ComponentMixinDemo',
|
name: "ComponentMixinDemo",
|
||||||
meta: { title: 'Component Mixin' }
|
meta: { title: "Component Mixin" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'back-to-top',
|
path: "back-to-top",
|
||||||
component: () => import('@/views/components-demo/back-to-top'),
|
component: () => import("@/views/components-demo/back-to-top"),
|
||||||
name: 'BackToTopDemo',
|
name: "BackToTopDemo",
|
||||||
meta: { title: 'Back To Top' }
|
meta: { title: "Back To Top" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-dialog',
|
path: "drag-dialog",
|
||||||
component: () => import('@/views/components-demo/drag-dialog'),
|
component: () => import("@/views/components-demo/drag-dialog"),
|
||||||
name: 'DragDialogDemo',
|
name: "DragDialogDemo",
|
||||||
meta: { title: 'Drag Dialog' }
|
meta: { title: "Drag Dialog" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-select',
|
path: "drag-select",
|
||||||
component: () => import('@/views/components-demo/drag-select'),
|
component: () => import("@/views/components-demo/drag-select"),
|
||||||
name: 'DragSelectDemo',
|
name: "DragSelectDemo",
|
||||||
meta: { title: 'Drag Select' }
|
meta: { title: "Drag Select" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dnd-list',
|
path: "dnd-list",
|
||||||
component: () => import('@/views/components-demo/dnd-list'),
|
component: () => import("@/views/components-demo/dnd-list"),
|
||||||
name: 'DndListDemo',
|
name: "DndListDemo",
|
||||||
meta: { title: 'Dnd List' }
|
meta: { title: "Dnd List" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-kanban',
|
path: "drag-kanban",
|
||||||
component: () => import('@/views/components-demo/drag-kanban'),
|
component: () => import("@/views/components-demo/drag-kanban"),
|
||||||
name: 'DragKanbanDemo',
|
name: "DragKanbanDemo",
|
||||||
meta: { title: 'Drag Kanban' }
|
meta: { title: "Drag Kanban" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
|
|
||||||
export default componentsRouter
|
export default componentsRouter;
|
||||||
|
|
|
@ -1,66 +1,66 @@
|
||||||
/** When your routing table is too long, you can split it into small modules **/
|
/** When your routing table is too long, you can split it into small modules **/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from "@/layout";
|
||||||
|
|
||||||
const nestedRouter = {
|
const nestedRouter = {
|
||||||
path: '/nested',
|
path: "/nested",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/nested/menu1/menu1-1',
|
redirect: "/nested/menu1/menu1-1",
|
||||||
name: 'Nested',
|
name: "Nested",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Nested Routes',
|
title: "Nested Routes",
|
||||||
icon: 'nested'
|
icon: "nested"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1',
|
path: "menu1",
|
||||||
component: () => import('@/views/nested/menu1/index'), // Parent router-view
|
component: () => import("@/views/nested/menu1/index"), // Parent router-view
|
||||||
name: 'Menu1',
|
name: "Menu1",
|
||||||
meta: { title: 'Menu 1' },
|
meta: { title: "Menu 1" },
|
||||||
redirect: '/nested/menu1/menu1-1',
|
redirect: "/nested/menu1/menu1-1",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1-1',
|
path: "menu1-1",
|
||||||
component: () => import('@/views/nested/menu1/menu1-1'),
|
component: () => import("@/views/nested/menu1/menu1-1"),
|
||||||
name: 'Menu1-1',
|
name: "Menu1-1",
|
||||||
meta: { title: 'Menu 1-1' }
|
meta: { title: "Menu 1-1" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-2',
|
path: "menu1-2",
|
||||||
component: () => import('@/views/nested/menu1/menu1-2'),
|
component: () => import("@/views/nested/menu1/menu1-2"),
|
||||||
name: 'Menu1-2',
|
name: "Menu1-2",
|
||||||
redirect: '/nested/menu1/menu1-2/menu1-2-1',
|
redirect: "/nested/menu1/menu1-2/menu1-2-1",
|
||||||
meta: { title: 'Menu 1-2' },
|
meta: { title: "Menu 1-2" },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'menu1-2-1',
|
path: "menu1-2-1",
|
||||||
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
|
component: () => import("@/views/nested/menu1/menu1-2/menu1-2-1"),
|
||||||
name: 'Menu1-2-1',
|
name: "Menu1-2-1",
|
||||||
meta: { title: 'Menu 1-2-1' }
|
meta: { title: "Menu 1-2-1" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-2-2',
|
path: "menu1-2-2",
|
||||||
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
|
component: () => import("@/views/nested/menu1/menu1-2/menu1-2-2"),
|
||||||
name: 'Menu1-2-2',
|
name: "Menu1-2-2",
|
||||||
meta: { title: 'Menu 1-2-2' }
|
meta: { title: "Menu 1-2-2" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu1-3',
|
path: "menu1-3",
|
||||||
component: () => import('@/views/nested/menu1/menu1-3'),
|
component: () => import("@/views/nested/menu1/menu1-3"),
|
||||||
name: 'Menu1-3',
|
name: "Menu1-3",
|
||||||
meta: { title: 'Menu 1-3' }
|
meta: { title: "Menu 1-3" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'menu2',
|
path: "menu2",
|
||||||
name: 'Menu2',
|
name: "Menu2",
|
||||||
component: () => import('@/views/nested/menu2/index'),
|
component: () => import("@/views/nested/menu2/index"),
|
||||||
meta: { title: 'Menu 2' }
|
meta: { title: "Menu 2" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
|
|
||||||
export default nestedRouter
|
export default nestedRouter;
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
/** When your routing table is too long, you can split it into small modules **/
|
/** When your routing table is too long, you can split it into small modules **/
|
||||||
|
|
||||||
import Layout from '@/layout'
|
import Layout from "@/layout";
|
||||||
|
|
||||||
const tableRouter = {
|
const tableRouter = {
|
||||||
path: '/table',
|
path: "/table",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/table/complex-table',
|
redirect: "/table/complex-table",
|
||||||
name: 'Table',
|
name: "Table",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Table',
|
title: "Table",
|
||||||
icon: 'table'
|
icon: "table"
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'dynamic-table',
|
path: "dynamic-table",
|
||||||
component: () => import('@/views/table/dynamic-table/index'),
|
component: () => import("@/views/table/dynamic-table/index"),
|
||||||
name: 'DynamicTable',
|
name: "DynamicTable",
|
||||||
meta: { title: 'Dynamic Table' }
|
meta: { title: "Dynamic Table" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'drag-table',
|
path: "drag-table",
|
||||||
component: () => import('@/views/table/drag-table'),
|
component: () => import("@/views/table/drag-table"),
|
||||||
name: 'DragTable',
|
name: "DragTable",
|
||||||
meta: { title: 'Drag Table' }
|
meta: { title: "Drag Table" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'inline-edit-table',
|
path: "inline-edit-table",
|
||||||
component: () => import('@/views/table/inline-edit-table'),
|
component: () => import("@/views/table/inline-edit-table"),
|
||||||
name: 'InlineEditTable',
|
name: "InlineEditTable",
|
||||||
meta: { title: 'Inline Edit' }
|
meta: { title: "Inline Edit" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'complex-table',
|
path: "complex-table",
|
||||||
component: () => import('@/views/table/complex-table'),
|
component: () => import("@/views/table/complex-table"),
|
||||||
name: 'ComplexTable',
|
name: "ComplexTable",
|
||||||
meta: { title: 'Complex Table' }
|
meta: { title: "Complex Table" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
};
|
||||||
export default tableRouter
|
export default tableRouter;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
title: 'Vue Element Admin',
|
title: "Vue Element Admin",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {boolean} true | false
|
* @type {boolean} true | false
|
||||||
|
@ -31,5 +31,5 @@ module.exports = {
|
||||||
* The default is only used in the production env
|
* The default is only used in the production env
|
||||||
* If you want to also use it in dev, you can pass ['production', 'development']
|
* If you want to also use it in dev, you can pass ['production', 'development']
|
||||||
*/
|
*/
|
||||||
errorLog: 'production'
|
errorLog: "production"
|
||||||
}
|
};
|
||||||
|
|
|
@ -11,5 +11,5 @@ const getters = {
|
||||||
roles: state => state.user.roles,
|
roles: state => state.user.roles,
|
||||||
permission_routes: state => state.permission.routes,
|
permission_routes: state => state.permission.routes,
|
||||||
errorLogs: state => state.errorLog.logs
|
errorLogs: state => state.errorLog.logs
|
||||||
}
|
};
|
||||||
export default getters
|
export default getters;
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
import Vuex from 'vuex'
|
import Vuex from "vuex";
|
||||||
import getters from './getters'
|
import getters from "./getters";
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex);
|
||||||
|
|
||||||
// https://webpack.js.org/guides/dependency-management/#requirecontext
|
// https://webpack.js.org/guides/dependency-management/#requirecontext
|
||||||
const modulesFiles = require.context('./modules', true, /\.js$/)
|
const modulesFiles = require.context("./modules", true, /\.js$/);
|
||||||
|
|
||||||
// you do not need `import app from './modules/app'`
|
// you do not need `import app from './modules/app'`
|
||||||
// it will auto require all vuex module from modules file
|
// it will auto require all vuex module from modules file
|
||||||
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
|
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
|
||||||
// set './app.js' => 'app'
|
// set './app.js' => 'app'
|
||||||
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
|
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, "$1");
|
||||||
const value = modulesFiles(modulePath)
|
const value = modulesFiles(modulePath);
|
||||||
modules[moduleName] = value.default
|
modules[moduleName] = value.default;
|
||||||
return modules
|
return modules;
|
||||||
}, {})
|
}, {});
|
||||||
|
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
modules,
|
modules,
|
||||||
getters
|
getters
|
||||||
})
|
});
|
||||||
|
|
||||||
export default store
|
export default store;
|
||||||
|
|
|
@ -1,56 +1,58 @@
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
|
opened: Cookies.get("sidebarStatus")
|
||||||
|
? !!+Cookies.get("sidebarStatus")
|
||||||
|
: true,
|
||||||
withoutAnimation: false
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
device: 'desktop',
|
device: "desktop",
|
||||||
size: Cookies.get('size') || 'medium'
|
size: Cookies.get("size") || "medium"
|
||||||
}
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
TOGGLE_SIDEBAR: state => {
|
TOGGLE_SIDEBAR: state => {
|
||||||
state.sidebar.opened = !state.sidebar.opened
|
state.sidebar.opened = !state.sidebar.opened;
|
||||||
state.sidebar.withoutAnimation = false
|
state.sidebar.withoutAnimation = false;
|
||||||
if (state.sidebar.opened) {
|
if (state.sidebar.opened) {
|
||||||
Cookies.set('sidebarStatus', 1)
|
Cookies.set("sidebarStatus", 1);
|
||||||
} else {
|
} else {
|
||||||
Cookies.set('sidebarStatus', 0)
|
Cookies.set("sidebarStatus", 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||||
Cookies.set('sidebarStatus', 0)
|
Cookies.set("sidebarStatus", 0);
|
||||||
state.sidebar.opened = false
|
state.sidebar.opened = false;
|
||||||
state.sidebar.withoutAnimation = withoutAnimation
|
state.sidebar.withoutAnimation = withoutAnimation;
|
||||||
},
|
},
|
||||||
TOGGLE_DEVICE: (state, device) => {
|
TOGGLE_DEVICE: (state, device) => {
|
||||||
state.device = device
|
state.device = device;
|
||||||
},
|
},
|
||||||
SET_SIZE: (state, size) => {
|
SET_SIZE: (state, size) => {
|
||||||
state.size = size
|
state.size = size;
|
||||||
Cookies.set('size', size)
|
Cookies.set("size", size);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
toggleSideBar({ commit }) {
|
toggleSideBar({ commit }) {
|
||||||
commit('TOGGLE_SIDEBAR')
|
commit("TOGGLE_SIDEBAR");
|
||||||
},
|
},
|
||||||
closeSideBar({ commit }, { withoutAnimation }) {
|
closeSideBar({ commit }, { withoutAnimation }) {
|
||||||
commit('CLOSE_SIDEBAR', withoutAnimation)
|
commit("CLOSE_SIDEBAR", withoutAnimation);
|
||||||
},
|
},
|
||||||
toggleDevice({ commit }, device) {
|
toggleDevice({ commit }, device) {
|
||||||
commit('TOGGLE_DEVICE', device)
|
commit("TOGGLE_DEVICE", device);
|
||||||
},
|
},
|
||||||
setSize({ commit }, size) {
|
setSize({ commit }, size) {
|
||||||
commit('SET_SIZE', size)
|
commit("SET_SIZE", size);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions
|
actions
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
const state = {
|
const state = {
|
||||||
logs: []
|
logs: []
|
||||||
}
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
ADD_ERROR_LOG: (state, log) => {
|
ADD_ERROR_LOG: (state, log) => {
|
||||||
state.logs.push(log)
|
state.logs.push(log);
|
||||||
},
|
},
|
||||||
CLEAR_ERROR_LOG: (state) => {
|
CLEAR_ERROR_LOG: state => {
|
||||||
state.logs.splice(0)
|
state.logs.splice(0);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
addErrorLog({ commit }, log) {
|
addErrorLog({ commit }, log) {
|
||||||
commit('ADD_ERROR_LOG', log)
|
commit("ADD_ERROR_LOG", log);
|
||||||
},
|
},
|
||||||
clearErrorLog({ commit }) {
|
clearErrorLog({ commit }) {
|
||||||
commit('CLEAR_ERROR_LOG')
|
commit("CLEAR_ERROR_LOG");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions
|
actions
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { asyncRoutes, constantRoutes } from '@/router'
|
import { asyncRoutes, constantRoutes } from "@/router";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use meta.role to determine if the current user has permission
|
* Use meta.role to determine if the current user has permission
|
||||||
|
@ -7,9 +7,9 @@ import { asyncRoutes, constantRoutes } from '@/router'
|
||||||
*/
|
*/
|
||||||
function hasPermission(roles, route) {
|
function hasPermission(roles, route) {
|
||||||
if (route.meta && route.meta.roles) {
|
if (route.meta && route.meta.roles) {
|
||||||
return roles.some(role => route.meta.roles.includes(role))
|
return roles.some(role => route.meta.roles.includes(role));
|
||||||
} else {
|
} else {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,51 +19,51 @@ function hasPermission(roles, route) {
|
||||||
* @param roles
|
* @param roles
|
||||||
*/
|
*/
|
||||||
export function filterAsyncRoutes(routes, roles) {
|
export function filterAsyncRoutes(routes, roles) {
|
||||||
const res = []
|
const res = [];
|
||||||
|
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
const tmp = { ...route }
|
const tmp = { ...route };
|
||||||
if (hasPermission(roles, tmp)) {
|
if (hasPermission(roles, tmp)) {
|
||||||
if (tmp.children) {
|
if (tmp.children) {
|
||||||
tmp.children = filterAsyncRoutes(tmp.children, roles)
|
tmp.children = filterAsyncRoutes(tmp.children, roles);
|
||||||
}
|
}
|
||||||
res.push(tmp)
|
res.push(tmp);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
return res
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
routes: [],
|
routes: [],
|
||||||
addRoutes: []
|
addRoutes: []
|
||||||
}
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
SET_ROUTES: (state, routes) => {
|
SET_ROUTES: (state, routes) => {
|
||||||
state.addRoutes = routes
|
state.addRoutes = routes;
|
||||||
state.routes = constantRoutes.concat(routes)
|
state.routes = constantRoutes.concat(routes);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
generateRoutes({ commit }, roles) {
|
generateRoutes({ commit }, roles) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let accessedRoutes
|
let accessedRoutes;
|
||||||
if (roles.includes('admin')) {
|
if (roles.includes("admin")) {
|
||||||
accessedRoutes = asyncRoutes || []
|
accessedRoutes = asyncRoutes || [];
|
||||||
} else {
|
} else {
|
||||||
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
|
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
|
||||||
}
|
}
|
||||||
commit('SET_ROUTES', accessedRoutes)
|
commit("SET_ROUTES", accessedRoutes);
|
||||||
resolve(accessedRoutes)
|
resolve(accessedRoutes);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions
|
actions
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,165 +1,165 @@
|
||||||
const state = {
|
const state = {
|
||||||
visitedViews: [],
|
visitedViews: [],
|
||||||
cachedViews: []
|
cachedViews: []
|
||||||
}
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
ADD_VISITED_VIEW: (state, view) => {
|
ADD_VISITED_VIEW: (state, view) => {
|
||||||
if (state.visitedViews.some(v => v.path === view.path)) return
|
if (state.visitedViews.some(v => v.path === view.path)) return;
|
||||||
state.visitedViews.push(
|
state.visitedViews.push(
|
||||||
Object.assign({}, view, {
|
Object.assign({}, view, {
|
||||||
title: view.meta.title || 'no-name'
|
title: view.meta.title || "no-name"
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
},
|
},
|
||||||
ADD_CACHED_VIEW: (state, view) => {
|
ADD_CACHED_VIEW: (state, view) => {
|
||||||
if (state.cachedViews.includes(view.name)) return
|
if (state.cachedViews.includes(view.name)) return;
|
||||||
if (!view.meta.noCache) {
|
if (!view.meta.noCache) {
|
||||||
state.cachedViews.push(view.name)
|
state.cachedViews.push(view.name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DEL_VISITED_VIEW: (state, view) => {
|
DEL_VISITED_VIEW: (state, view) => {
|
||||||
for (const [i, v] of state.visitedViews.entries()) {
|
for (const [i, v] of state.visitedViews.entries()) {
|
||||||
if (v.path === view.path) {
|
if (v.path === view.path) {
|
||||||
state.visitedViews.splice(i, 1)
|
state.visitedViews.splice(i, 1);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DEL_CACHED_VIEW: (state, view) => {
|
DEL_CACHED_VIEW: (state, view) => {
|
||||||
for (const i of state.cachedViews) {
|
for (const i of state.cachedViews) {
|
||||||
if (i === view.name) {
|
if (i === view.name) {
|
||||||
const index = state.cachedViews.indexOf(i)
|
const index = state.cachedViews.indexOf(i);
|
||||||
state.cachedViews.splice(index, 1)
|
state.cachedViews.splice(index, 1);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
|
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
|
||||||
state.visitedViews = state.visitedViews.filter(v => {
|
state.visitedViews = state.visitedViews.filter(v => {
|
||||||
return v.meta.affix || v.path === view.path
|
return v.meta.affix || v.path === view.path;
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
|
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
|
||||||
for (const i of state.cachedViews) {
|
for (const i of state.cachedViews) {
|
||||||
if (i === view.name) {
|
if (i === view.name) {
|
||||||
const index = state.cachedViews.indexOf(i)
|
const index = state.cachedViews.indexOf(i);
|
||||||
state.cachedViews = state.cachedViews.slice(index, index + 1)
|
state.cachedViews = state.cachedViews.slice(index, index + 1);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DEL_ALL_VISITED_VIEWS: state => {
|
DEL_ALL_VISITED_VIEWS: state => {
|
||||||
// keep affix tags
|
// keep affix tags
|
||||||
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
|
const affixTags = state.visitedViews.filter(tag => tag.meta.affix);
|
||||||
state.visitedViews = affixTags
|
state.visitedViews = affixTags;
|
||||||
},
|
},
|
||||||
DEL_ALL_CACHED_VIEWS: state => {
|
DEL_ALL_CACHED_VIEWS: state => {
|
||||||
state.cachedViews = []
|
state.cachedViews = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
UPDATE_VISITED_VIEW: (state, view) => {
|
UPDATE_VISITED_VIEW: (state, view) => {
|
||||||
for (let v of state.visitedViews) {
|
for (let v of state.visitedViews) {
|
||||||
if (v.path === view.path) {
|
if (v.path === view.path) {
|
||||||
v = Object.assign(v, view)
|
v = Object.assign(v, view);
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
addView({ dispatch }, view) {
|
addView({ dispatch }, view) {
|
||||||
dispatch('addVisitedView', view)
|
dispatch("addVisitedView", view);
|
||||||
dispatch('addCachedView', view)
|
dispatch("addCachedView", view);
|
||||||
},
|
},
|
||||||
addVisitedView({ commit }, view) {
|
addVisitedView({ commit }, view) {
|
||||||
commit('ADD_VISITED_VIEW', view)
|
commit("ADD_VISITED_VIEW", view);
|
||||||
},
|
},
|
||||||
addCachedView({ commit }, view) {
|
addCachedView({ commit }, view) {
|
||||||
commit('ADD_CACHED_VIEW', view)
|
commit("ADD_CACHED_VIEW", view);
|
||||||
},
|
},
|
||||||
|
|
||||||
delView({ dispatch, state }, view) {
|
delView({ dispatch, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
dispatch('delVisitedView', view)
|
dispatch("delVisitedView", view);
|
||||||
dispatch('delCachedView', view)
|
dispatch("delCachedView", view);
|
||||||
resolve({
|
resolve({
|
||||||
visitedViews: [...state.visitedViews],
|
visitedViews: [...state.visitedViews],
|
||||||
cachedViews: [...state.cachedViews]
|
cachedViews: [...state.cachedViews]
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delVisitedView({ commit, state }, view) {
|
delVisitedView({ commit, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_VISITED_VIEW', view)
|
commit("DEL_VISITED_VIEW", view);
|
||||||
resolve([...state.visitedViews])
|
resolve([...state.visitedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delCachedView({ commit, state }, view) {
|
delCachedView({ commit, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_CACHED_VIEW', view)
|
commit("DEL_CACHED_VIEW", view);
|
||||||
resolve([...state.cachedViews])
|
resolve([...state.cachedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
delOthersViews({ dispatch, state }, view) {
|
delOthersViews({ dispatch, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
dispatch('delOthersVisitedViews', view)
|
dispatch("delOthersVisitedViews", view);
|
||||||
dispatch('delOthersCachedViews', view)
|
dispatch("delOthersCachedViews", view);
|
||||||
resolve({
|
resolve({
|
||||||
visitedViews: [...state.visitedViews],
|
visitedViews: [...state.visitedViews],
|
||||||
cachedViews: [...state.cachedViews]
|
cachedViews: [...state.cachedViews]
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delOthersVisitedViews({ commit, state }, view) {
|
delOthersVisitedViews({ commit, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_OTHERS_VISITED_VIEWS', view)
|
commit("DEL_OTHERS_VISITED_VIEWS", view);
|
||||||
resolve([...state.visitedViews])
|
resolve([...state.visitedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delOthersCachedViews({ commit, state }, view) {
|
delOthersCachedViews({ commit, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_OTHERS_CACHED_VIEWS', view)
|
commit("DEL_OTHERS_CACHED_VIEWS", view);
|
||||||
resolve([...state.cachedViews])
|
resolve([...state.cachedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
delAllViews({ dispatch, state }, view) {
|
delAllViews({ dispatch, state }, view) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
dispatch('delAllVisitedViews', view)
|
dispatch("delAllVisitedViews", view);
|
||||||
dispatch('delAllCachedViews', view)
|
dispatch("delAllCachedViews", view);
|
||||||
resolve({
|
resolve({
|
||||||
visitedViews: [...state.visitedViews],
|
visitedViews: [...state.visitedViews],
|
||||||
cachedViews: [...state.cachedViews]
|
cachedViews: [...state.cachedViews]
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delAllVisitedViews({ commit, state }) {
|
delAllVisitedViews({ commit, state }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_ALL_VISITED_VIEWS')
|
commit("DEL_ALL_VISITED_VIEWS");
|
||||||
resolve([...state.visitedViews])
|
resolve([...state.visitedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
delAllCachedViews({ commit, state }) {
|
delAllCachedViews({ commit, state }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('DEL_ALL_CACHED_VIEWS')
|
commit("DEL_ALL_CACHED_VIEWS");
|
||||||
resolve([...state.cachedViews])
|
resolve([...state.cachedViews]);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateVisitedView({ commit }, view) {
|
updateVisitedView({ commit }, view) {
|
||||||
commit('UPDATE_VISITED_VIEW', view)
|
commit("UPDATE_VISITED_VIEW", view);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions
|
actions
|
||||||
}
|
};
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue