mirror of https://github.com/longtai-cn/hippo4j
parent
9d2d325c84
commit
c4f9a31806
@ -1,14 +0,0 @@
|
|||||||
# https://editorconfig.org
|
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
insert_final_newline = false
|
|
||||||
trim_trailing_whitespace = false
|
|
@ -1,17 +0,0 @@
|
|||||||
# just a flag
|
|
||||||
ENV = 'development'
|
|
||||||
|
|
||||||
# base api
|
|
||||||
VUE_APP_BASE_API = ''
|
|
||||||
|
|
||||||
# no mock api
|
|
||||||
VUE_APP_API = ''
|
|
||||||
|
|
||||||
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
|
|
||||||
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
|
|
||||||
# It only does one thing by converting all import() to require().
|
|
||||||
# This configuration can significantly increase the speed of hot updates,
|
|
||||||
# when you have a large number of pages.
|
|
||||||
# Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
|
|
||||||
|
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
|
@ -1,5 +0,0 @@
|
|||||||
# just a flag
|
|
||||||
ENV = 'production'
|
|
||||||
|
|
||||||
# base api
|
|
||||||
VUE_APP_BASE_API = '/'
|
|
@ -1,8 +0,0 @@
|
|||||||
NODE_ENV = production
|
|
||||||
|
|
||||||
# just a flag
|
|
||||||
ENV = 'staging'
|
|
||||||
|
|
||||||
# base api
|
|
||||||
VUE_APP_BASE_API = '/stage-api'
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
build/*.js
|
|
||||||
src/assets
|
|
||||||
public
|
|
||||||
dist
|
|
||||||
*.vue
|
|
@ -1,198 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
parserOptions: {
|
|
||||||
parser: 'babel-eslint',
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
node: true,
|
|
||||||
es6: true,
|
|
||||||
},
|
|
||||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
|
||||||
|
|
||||||
// add your custom rules here
|
|
||||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
|
||||||
rules: {
|
|
||||||
"vue/max-attributes-per-line": [2, {
|
|
||||||
"singleline": 10,
|
|
||||||
"multiline": {
|
|
||||||
"max": 1,
|
|
||||||
"allowFirstLine": false
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"vue/singleline-html-element-content-newline": "off",
|
|
||||||
"vue/multiline-html-element-content-newline":"off",
|
|
||||||
"vue/name-property-casing": ["error", "PascalCase"],
|
|
||||||
"vue/no-v-html": "off",
|
|
||||||
'accessor-pairs': 2,
|
|
||||||
'arrow-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'block-spacing': [2, 'always'],
|
|
||||||
'brace-style': [2, '1tbs', {
|
|
||||||
'allowSingleLine': true
|
|
||||||
}],
|
|
||||||
'camelcase': [0, {
|
|
||||||
'properties': 'always'
|
|
||||||
}],
|
|
||||||
'comma-dangle': [2, 'never'],
|
|
||||||
'comma-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'comma-style': [2, 'last'],
|
|
||||||
'constructor-super': 2,
|
|
||||||
'curly': [2, 'multi-line'],
|
|
||||||
'dot-location': [2, 'property'],
|
|
||||||
'eol-last': 2,
|
|
||||||
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
|
||||||
'generator-star-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'handle-callback-err': [2, '^(err|error)$'],
|
|
||||||
'indent': [2, 2, {
|
|
||||||
'SwitchCase': 1
|
|
||||||
}],
|
|
||||||
'jsx-quotes': [2, 'prefer-single'],
|
|
||||||
'key-spacing': [2, {
|
|
||||||
'beforeColon': false,
|
|
||||||
'afterColon': true
|
|
||||||
}],
|
|
||||||
'keyword-spacing': [2, {
|
|
||||||
'before': true,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'new-cap': [2, {
|
|
||||||
'newIsCap': true,
|
|
||||||
'capIsNew': false
|
|
||||||
}],
|
|
||||||
'new-parens': 2,
|
|
||||||
'no-array-constructor': 2,
|
|
||||||
'no-caller': 2,
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-class-assign': 2,
|
|
||||||
'no-cond-assign': 2,
|
|
||||||
'no-const-assign': 2,
|
|
||||||
'no-control-regex': 0,
|
|
||||||
'no-delete-var': 2,
|
|
||||||
'no-dupe-args': 2,
|
|
||||||
'no-dupe-class-members': 2,
|
|
||||||
'no-dupe-keys': 2,
|
|
||||||
'no-duplicate-case': 2,
|
|
||||||
'no-empty-character-class': 2,
|
|
||||||
'no-empty-pattern': 2,
|
|
||||||
'no-eval': 2,
|
|
||||||
'no-ex-assign': 2,
|
|
||||||
'no-extend-native': 2,
|
|
||||||
'no-extra-bind': 2,
|
|
||||||
'no-extra-boolean-cast': 2,
|
|
||||||
'no-extra-parens': [2, 'functions'],
|
|
||||||
'no-fallthrough': 2,
|
|
||||||
'no-floating-decimal': 2,
|
|
||||||
'no-func-assign': 2,
|
|
||||||
'no-implied-eval': 2,
|
|
||||||
'no-inner-declarations': [2, 'functions'],
|
|
||||||
'no-invalid-regexp': 2,
|
|
||||||
'no-irregular-whitespace': 2,
|
|
||||||
'no-iterator': 2,
|
|
||||||
'no-label-var': 2,
|
|
||||||
'no-labels': [2, {
|
|
||||||
'allowLoop': false,
|
|
||||||
'allowSwitch': false
|
|
||||||
}],
|
|
||||||
'no-lone-blocks': 2,
|
|
||||||
'no-mixed-spaces-and-tabs': 2,
|
|
||||||
'no-multi-spaces': 2,
|
|
||||||
'no-multi-str': 2,
|
|
||||||
'no-multiple-empty-lines': [2, {
|
|
||||||
'max': 1
|
|
||||||
}],
|
|
||||||
'no-native-reassign': 2,
|
|
||||||
'no-negated-in-lhs': 2,
|
|
||||||
'no-new-object': 2,
|
|
||||||
'no-new-require': 2,
|
|
||||||
'no-new-symbol': 2,
|
|
||||||
'no-new-wrappers': 2,
|
|
||||||
'no-obj-calls': 2,
|
|
||||||
'no-octal': 2,
|
|
||||||
'no-octal-escape': 2,
|
|
||||||
'no-path-concat': 2,
|
|
||||||
'no-proto': 2,
|
|
||||||
'no-redeclare': 2,
|
|
||||||
'no-regex-spaces': 2,
|
|
||||||
'no-return-assign': [2, 'except-parens'],
|
|
||||||
'no-self-assign': 2,
|
|
||||||
'no-self-compare': 2,
|
|
||||||
'no-sequences': 2,
|
|
||||||
'no-shadow-restricted-names': 2,
|
|
||||||
'no-spaced-func': 2,
|
|
||||||
'no-sparse-arrays': 2,
|
|
||||||
'no-this-before-super': 2,
|
|
||||||
'no-throw-literal': 2,
|
|
||||||
'no-trailing-spaces': 2,
|
|
||||||
'no-undef': 2,
|
|
||||||
'no-undef-init': 2,
|
|
||||||
'no-unexpected-multiline': 2,
|
|
||||||
'no-unmodified-loop-condition': 2,
|
|
||||||
'no-unneeded-ternary': [2, {
|
|
||||||
'defaultAssignment': false
|
|
||||||
}],
|
|
||||||
'no-unreachable': 2,
|
|
||||||
'no-unsafe-finally': 2,
|
|
||||||
'no-unused-vars': [2, {
|
|
||||||
'vars': 'all',
|
|
||||||
'args': 'none'
|
|
||||||
}],
|
|
||||||
'no-useless-call': 2,
|
|
||||||
'no-useless-computed-key': 2,
|
|
||||||
'no-useless-constructor': 2,
|
|
||||||
'no-useless-escape': 0,
|
|
||||||
'no-whitespace-before-property': 2,
|
|
||||||
'no-with': 2,
|
|
||||||
'one-var': [2, {
|
|
||||||
'initialized': 'never'
|
|
||||||
}],
|
|
||||||
'operator-linebreak': [2, 'after', {
|
|
||||||
'overrides': {
|
|
||||||
'?': 'before',
|
|
||||||
':': 'before'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
'padded-blocks': [2, 'never'],
|
|
||||||
'quotes': [2, 'single', {
|
|
||||||
'avoidEscape': true,
|
|
||||||
'allowTemplateLiterals': true
|
|
||||||
}],
|
|
||||||
'semi': [2, 'never'],
|
|
||||||
'semi-spacing': [2, {
|
|
||||||
'before': false,
|
|
||||||
'after': true
|
|
||||||
}],
|
|
||||||
'space-before-blocks': [2, 'always'],
|
|
||||||
'space-before-function-paren': [2, 'never'],
|
|
||||||
'space-in-parens': [2, 'never'],
|
|
||||||
'space-infix-ops': 2,
|
|
||||||
'space-unary-ops': [2, {
|
|
||||||
'words': true,
|
|
||||||
'nonwords': false
|
|
||||||
}],
|
|
||||||
'spaced-comment': [2, 'always', {
|
|
||||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
|
||||||
}],
|
|
||||||
'template-curly-spacing': [2, 'never'],
|
|
||||||
'use-isnan': 2,
|
|
||||||
'valid-typeof': 2,
|
|
||||||
'wrap-iife': [2, 'any'],
|
|
||||||
'yield-star-spacing': [2, 'both'],
|
|
||||||
'yoda': [2, 'never'],
|
|
||||||
'prefer-const': 2,
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
|
||||||
'object-curly-spacing': [2, 'always', {
|
|
||||||
objectsInObjects: false
|
|
||||||
}],
|
|
||||||
'array-bracket-spacing': [2, 'never']
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
.DS_Store
|
|
||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
**/*.log
|
|
||||||
|
|
||||||
tests/**/coverage/
|
|
||||||
tests/e2e/reports
|
|
||||||
selenium-debug.log
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.idea
|
|
||||||
.vscode
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.local
|
|
||||||
|
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
|
@ -1,5 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js: 10
|
|
||||||
script: npm run test
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 WeiYe
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,39 +0,0 @@
|
|||||||
# Hippo4J Console UI
|
|
||||||
|
|
||||||
## 说明
|
|
||||||
|
|
||||||
该项目由 [datax-web-ui](https://github.com/WeiYe-Jing/datax-web-ui)、[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) 修改而来
|
|
||||||
|
|
||||||
|
|
||||||
## Build Setup
|
|
||||||
|
|
||||||
运行
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install [ 慢的话用 npm install --registry https://registry.npm.taobao.org]
|
|
||||||
```
|
|
||||||
|
|
||||||
修改配置
|
|
||||||
|
|
||||||
找到 `vue.config.js` 修改 `proxy` 里的属性即可
|
|
||||||
|
|
||||||
```
|
|
||||||
[process.env.VUE_APP_API]: {
|
|
||||||
target: `http://localhost:${apiPort}/api`,
|
|
||||||
changeOrigin: true,
|
|
||||||
pathRewrite: {
|
|
||||||
['^' + process.env.VUE_APP_API]: ''
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
启动
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
打包
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run build:prod
|
|
||||||
```
|
|
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
'@vue/app'
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
|
|
||||||
transform: {
|
|
||||||
'^.+\\.vue$': 'vue-jest',
|
|
||||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
|
|
||||||
'jest-transform-stub',
|
|
||||||
'^.+\\.jsx?$': 'babel-jest'
|
|
||||||
},
|
|
||||||
moduleNameMapper: {
|
|
||||||
'^@/(.*)$': '<rootDir>/src/$1'
|
|
||||||
},
|
|
||||||
snapshotSerializers: ['jest-serializer-vue'],
|
|
||||||
testMatch: [
|
|
||||||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
|
||||||
],
|
|
||||||
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
|
|
||||||
coverageDirectory: '<rootDir>/tests/unit/coverage',
|
|
||||||
// 'collectCoverage': true,
|
|
||||||
'coverageReporters': [
|
|
||||||
'lcov',
|
|
||||||
'text-summary'
|
|
||||||
],
|
|
||||||
testURL: 'http://localhost/'
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
import Mock from 'mockjs'
|
|
||||||
import { param2Obj } from '../src/utils'
|
|
||||||
|
|
||||||
import user from './user'
|
|
||||||
import role from './role'
|
|
||||||
import search from './remote-search'
|
|
||||||
|
|
||||||
const mocks = [
|
|
||||||
...user,
|
|
||||||
...role,
|
|
||||||
...search
|
|
||||||
]
|
|
||||||
|
|
||||||
// for front mock
|
|
||||||
// please use it cautiously, it will redefine XMLHttpRequest,
|
|
||||||
// which will cause many of your third-party libraries to be invalidated(like progress event).
|
|
||||||
export function mockXHR() {
|
|
||||||
// mock patch
|
|
||||||
// https://github.com/nuysoft/Mock/issues/300
|
|
||||||
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
|
||||||
Mock.XHR.prototype.send = function() {
|
|
||||||
if (this.custom.xhr) {
|
|
||||||
this.custom.xhr.withCredentials = this.withCredentials || false
|
|
||||||
|
|
||||||
if (this.responseType) {
|
|
||||||
this.custom.xhr.responseType = this.responseType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.proxy_send(...arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
function XHR2ExpressReqWrap(respond) {
|
|
||||||
return function(options) {
|
|
||||||
let result = null
|
|
||||||
if (respond instanceof Function) {
|
|
||||||
const { body, type, url } = options
|
|
||||||
// https://expressjs.com/en/4x/api.html#req
|
|
||||||
result = respond({
|
|
||||||
method: type,
|
|
||||||
body: JSON.parse(body),
|
|
||||||
query: param2Obj(url)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
result = respond
|
|
||||||
}
|
|
||||||
return Mock.mock(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const i of mocks) {
|
|
||||||
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for mock server
|
|
||||||
const responseFake = (url, type, respond) => {
|
|
||||||
return {
|
|
||||||
url: new RegExp(`/mock${url}`),
|
|
||||||
type: type || 'get',
|
|
||||||
response(req, res) {
|
|
||||||
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default mocks.map(route => {
|
|
||||||
return responseFake(route.url, route.type, route.response)
|
|
||||||
})
|
|
@ -1,68 +0,0 @@
|
|||||||
const chokidar = require('chokidar')
|
|
||||||
const bodyParser = require('body-parser')
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
const mockDir = path.join(process.cwd(), 'mock')
|
|
||||||
|
|
||||||
function registerRoutes(app) {
|
|
||||||
let mockLastIndex
|
|
||||||
const { default: mocks } = require('./index.js')
|
|
||||||
for (const mock of mocks) {
|
|
||||||
app[mock.type](mock.url, mock.response)
|
|
||||||
mockLastIndex = app._router.stack.length
|
|
||||||
}
|
|
||||||
const mockRoutesLength = Object.keys(mocks).length
|
|
||||||
return {
|
|
||||||
mockRoutesLength: mockRoutesLength,
|
|
||||||
mockStartIndex: mockLastIndex - mockRoutesLength
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function unregisterRoutes() {
|
|
||||||
Object.keys(require.cache).forEach(i => {
|
|
||||||
if (i.includes(mockDir)) {
|
|
||||||
delete require.cache[require.resolve(i)]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = app => {
|
|
||||||
// es6 polyfill
|
|
||||||
require('@babel/register')
|
|
||||||
|
|
||||||
// parse app.body
|
|
||||||
// https://expressjs.com/en/4x/api.html#req.body
|
|
||||||
app.use(bodyParser.json())
|
|
||||||
app.use(bodyParser.urlencoded({
|
|
||||||
extended: true
|
|
||||||
}))
|
|
||||||
|
|
||||||
const mockRoutes = registerRoutes(app)
|
|
||||||
var mockRoutesLength = mockRoutes.mockRoutesLength
|
|
||||||
var mockStartIndex = mockRoutes.mockStartIndex
|
|
||||||
|
|
||||||
// watch files, hot reload mock server
|
|
||||||
chokidar.watch(mockDir, {
|
|
||||||
ignored: /mock-server/,
|
|
||||||
ignoreInitial: true
|
|
||||||
}).on('all', (event, path) => {
|
|
||||||
if (event === 'change' || event === 'add') {
|
|
||||||
try {
|
|
||||||
// remove mock routes stack
|
|
||||||
app._router.stack.splice(mockStartIndex, mockRoutesLength)
|
|
||||||
|
|
||||||
// clear routes cache
|
|
||||||
unregisterRoutes()
|
|
||||||
|
|
||||||
const mockRoutes = registerRoutes(app)
|
|
||||||
mockRoutesLength = mockRoutes.mockRoutesLength
|
|
||||||
mockStartIndex = mockRoutes.mockStartIndex
|
|
||||||
|
|
||||||
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
|
||||||
} catch (error) {
|
|
||||||
console.log(chalk.redBright(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
import Mock from 'mockjs'
|
|
||||||
|
|
||||||
const NameList = []
|
|
||||||
const count = 100
|
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
|
||||||
NameList.push(Mock.mock({
|
|
||||||
name: '@first'
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
NameList.push({ name: 'mock-Pan' })
|
|
||||||
|
|
||||||
export default [
|
|
||||||
// username search
|
|
||||||
{
|
|
||||||
url: '/search/user',
|
|
||||||
type: 'get',
|
|
||||||
response: config => {
|
|
||||||
const { name } = config.query
|
|
||||||
const mockNameList = NameList.filter(item => {
|
|
||||||
const lowerCaseName = item.name.toLowerCase()
|
|
||||||
return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
code: 20000,
|
|
||||||
data: { items: mockNameList }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// transaction list
|
|
||||||
{
|
|
||||||
url: '/transaction/list',
|
|
||||||
type: 'get',
|
|
||||||
response: _ => {
|
|
||||||
return {
|
|
||||||
code: 20000,
|
|
||||||
data: {
|
|
||||||
total: 20,
|
|
||||||
'items|20': [{
|
|
||||||
order_no: '@guid()',
|
|
||||||
timestamp: +Mock.Random.date('T'),
|
|
||||||
username: '@name()',
|
|
||||||
price: '@float(1000, 15000, 0, 2)',
|
|
||||||
'status|1': ['success', 'pending']
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,98 +0,0 @@
|
|||||||
import Mock from 'mockjs'
|
|
||||||
import { deepClone } from '../../src/utils/index.js'
|
|
||||||
import { asyncRoutes, constantRoutes } from './routes.js'
|
|
||||||
|
|
||||||
const routes = deepClone([...constantRoutes, ...asyncRoutes])
|
|
||||||
|
|
||||||
const roles = [
|
|
||||||
{
|
|
||||||
key: 'admin',
|
|
||||||
name: 'admin',
|
|
||||||
description: 'Super Administrator. Have access to view all pages.',
|
|
||||||
routes: routes
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'editor',
|
|
||||||
name: 'editor',
|
|
||||||
description: 'Normal Editor. Can see all pages except permission page',
|
|
||||||
routes: routes.filter(i => i.path !== '/permission')// just a mock
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'visitor',
|
|
||||||
name: 'visitor',
|
|
||||||
description: 'Just a visitor. Can only see the home page and the document page',
|
|
||||||
routes: [{
|
|
||||||
path: '',
|
|
||||||
redirect: 'dashboard',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'dashboard',
|
|
||||||
name: 'Dashboard',
|
|
||||||
meta: { title: 'dashboard', icon: 'dashboard' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export default [
|
|
||||||
// mock get all routes form server
|
|
||||||
{
|
|
||||||
url: '/routes',
|
|
||||||
type: 'get',
|
|
||||||
response: _ => {
|
|
||||||
return {
|
|
||||||
code: 20000,
|
|
||||||
data: routes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// mock get all roles form server
|
|
||||||
{
|
|
||||||
url: '/roles',
|
|
||||||
type: 'get',
|
|
||||||
response: _ => {
|
|
||||||
return {
|
|
||||||
code: 20000,
|
|
||||||
data: roles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// add role
|
|
||||||
{
|
|
||||||
url: '/role',
|
|
||||||
type: 'post',
|
|
||||||
response: {
|
|
||||||
code: 20000,
|
|
||||||
data: {
|
|
||||||
key: Mock.mock('@integer(300, 5000)')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// update role
|
|
||||||
{
|
|
||||||
url: '/role/[A-Za-z0-9]',
|
|
||||||
type: 'put',
|
|
||||||
response: {
|
|
||||||
code: 20000,
|
|
||||||
data: {
|
|
||||||
status: 'success'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// delete role
|
|
||||||
{
|
|
||||||
url: '/role/[A-Za-z0-9]',
|
|
||||||
type: 'delete',
|
|
||||||
response: {
|
|
||||||
code: 20000,
|
|
||||||
data: {
|
|
||||||
status: 'success'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,525 +0,0 @@
|
|||||||
// Just a mock data
|
|
||||||
|
|
||||||
export const constantRoutes = [
|
|
||||||
{
|
|
||||||
path: '/redirect',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
hidden: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/redirect/:path*',
|
|
||||||
component: 'views/redirect/index'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/login',
|
|
||||||
component: 'views/login/index',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/auth-redirect',
|
|
||||||
component: 'views/login/auth-redirect',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/404',
|
|
||||||
component: 'views/error-page/404',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/401',
|
|
||||||
component: 'views/error-page/401',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'dashboard',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'dashboard',
|
|
||||||
component: 'views/dashboard/index',
|
|
||||||
name: 'Dashboard',
|
|
||||||
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/documentation',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/documentation/index',
|
|
||||||
name: 'Documentation',
|
|
||||||
meta: { title: 'Documentation', icon: 'documentation', affix: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/guide',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/guide/index',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/guide/index',
|
|
||||||
name: 'Guide',
|
|
||||||
meta: { title: 'Guide', icon: 'guide', noCache: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export const asyncRoutes = [
|
|
||||||
{
|
|
||||||
path: '/permission',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/permission/index',
|
|
||||||
alwaysShow: true,
|
|
||||||
meta: {
|
|
||||||
title: 'Permission',
|
|
||||||
icon: 'lock',
|
|
||||||
roles: ['admin', 'editor']
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'page',
|
|
||||||
component: 'views/permission/page',
|
|
||||||
name: 'PagePermission',
|
|
||||||
meta: {
|
|
||||||
title: 'Page Permission11111',
|
|
||||||
roles: ['admin']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'directive',
|
|
||||||
component: 'views/permission/directive',
|
|
||||||
name: 'DirectivePermission',
|
|
||||||
meta: {
|
|
||||||
title: 'Directive Permission'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'role',
|
|
||||||
component: 'views/permission/role',
|
|
||||||
name: 'RolePermission',
|
|
||||||
meta: {
|
|
||||||
title: 'Role Permission',
|
|
||||||
roles: ['admin']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/icon',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/icons/index',
|
|
||||||
name: 'Icons',
|
|
||||||
meta: { title: 'Icons', icon: 'icon', noCache: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/components',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
name: 'ComponentDemo',
|
|
||||||
meta: {
|
|
||||||
title: 'Components',
|
|
||||||
icon: 'component'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'tinymce',
|
|
||||||
component: 'views/components-demo/tinymce',
|
|
||||||
name: 'TinymceDemo',
|
|
||||||
meta: { title: 'Tinymce' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'markdown',
|
|
||||||
component: 'views/components-demo/markdown',
|
|
||||||
name: 'MarkdownDemo',
|
|
||||||
meta: { title: 'Markdown' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'json-editor',
|
|
||||||
component: 'views/components-demo/json-editor',
|
|
||||||
name: 'JsonEditorDemo',
|
|
||||||
meta: { title: 'Json Editor' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'split-pane',
|
|
||||||
component: 'views/components-demo/split-pane',
|
|
||||||
name: 'SplitpaneDemo',
|
|
||||||
meta: { title: 'SplitPane' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'avatar-upload',
|
|
||||||
component: 'views/components-demo/avatar-upload',
|
|
||||||
name: 'AvatarUploadDemo',
|
|
||||||
meta: { title: 'Avatar Upload' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'dropzone',
|
|
||||||
component: 'views/components-demo/dropzone',
|
|
||||||
name: 'DropzoneDemo',
|
|
||||||
meta: { title: 'Dropzone' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'sticky',
|
|
||||||
component: 'views/components-demo/sticky',
|
|
||||||
name: 'StickyDemo',
|
|
||||||
meta: { title: 'Sticky' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'count-to',
|
|
||||||
component: 'views/components-demo/count-to',
|
|
||||||
name: 'CountToDemo',
|
|
||||||
meta: { title: 'Count To' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'mixin',
|
|
||||||
component: 'views/components-demo/mixin',
|
|
||||||
name: 'ComponentMixinDemo',
|
|
||||||
meta: { title: 'componentMixin' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'back-to-top',
|
|
||||||
component: 'views/components-demo/back-to-top',
|
|
||||||
name: 'BackToTopDemo',
|
|
||||||
meta: { title: 'Back To Top' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'drag-dialog',
|
|
||||||
component: 'views/components-demo/drag-dialog',
|
|
||||||
name: 'DragDialogDemo',
|
|
||||||
meta: { title: 'Drag Dialog' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'drag-select',
|
|
||||||
component: 'views/components-demo/drag-select',
|
|
||||||
name: 'DragSelectDemo',
|
|
||||||
meta: { title: 'Drag Select' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'dnd-list',
|
|
||||||
component: 'views/components-demo/dnd-list',
|
|
||||||
name: 'DndListDemo',
|
|
||||||
meta: { title: 'Dnd List' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'drag-kanban',
|
|
||||||
component: 'views/components-demo/drag-kanban',
|
|
||||||
name: 'DragKanbanDemo',
|
|
||||||
meta: { title: 'Drag Kanban' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/charts',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
name: 'Charts',
|
|
||||||
meta: {
|
|
||||||
title: 'Charts',
|
|
||||||
icon: 'chart'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'keyboard',
|
|
||||||
component: 'views/charts/keyboard',
|
|
||||||
name: 'KeyboardChart',
|
|
||||||
meta: { title: 'Keyboard Chart', noCache: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'line',
|
|
||||||
component: 'views/charts/line',
|
|
||||||
name: 'LineChart',
|
|
||||||
meta: { title: 'Line Chart', noCache: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'mixchart',
|
|
||||||
component: 'views/charts/mixChart',
|
|
||||||
name: 'MixChart',
|
|
||||||
meta: { title: 'Mix Chart', noCache: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/nested',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/nested/menu1/menu1-1',
|
|
||||||
name: 'Nested',
|
|
||||||
meta: {
|
|
||||||
title: 'Nested',
|
|
||||||
icon: 'nested'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'menu1',
|
|
||||||
component: 'views/nested/menu1/index',
|
|
||||||
name: 'Menu1',
|
|
||||||
meta: { title: 'Menu1' },
|
|
||||||
redirect: '/nested/menu1/menu1-1',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'menu1-1',
|
|
||||||
component: 'views/nested/menu1/menu1-1',
|
|
||||||
name: 'Menu1-1',
|
|
||||||
meta: { title: 'Menu1-1' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'menu1-2',
|
|
||||||
component: 'views/nested/menu1/menu1-2',
|
|
||||||
name: 'Menu1-2',
|
|
||||||
redirect: '/nested/menu1/menu1-2/menu1-2-1',
|
|
||||||
meta: { title: 'Menu1-2' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'menu1-2-1',
|
|
||||||
component: 'views/nested/menu1/menu1-2/menu1-2-1',
|
|
||||||
name: 'Menu1-2-1',
|
|
||||||
meta: { title: 'Menu1-2-1' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'menu1-2-2',
|
|
||||||
component: 'views/nested/menu1/menu1-2/menu1-2-2',
|
|
||||||
name: 'Menu1-2-2',
|
|
||||||
meta: { title: 'Menu1-2-2' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'menu1-3',
|
|
||||||
component: 'views/nested/menu1/menu1-3',
|
|
||||||
name: 'Menu1-3',
|
|
||||||
meta: { title: 'Menu1-3' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'menu2',
|
|
||||||
name: 'Menu2',
|
|
||||||
component: 'views/nested/menu2/index',
|
|
||||||
meta: { title: 'Menu2' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/example',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/example/list',
|
|
||||||
name: 'Example',
|
|
||||||
meta: {
|
|
||||||
title: 'Example',
|
|
||||||
icon: 'example'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'create',
|
|
||||||
component: 'views/example/create',
|
|
||||||
name: 'CreateArticle',
|
|
||||||
meta: { title: 'Create Article', icon: 'edit' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'edit/:id(\\d+)',
|
|
||||||
component: 'views/example/edit',
|
|
||||||
name: 'EditArticle',
|
|
||||||
meta: { title: 'Edit Article', noCache: true },
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'list',
|
|
||||||
component: 'views/example/list',
|
|
||||||
name: 'ArticleList',
|
|
||||||
meta: { title: 'Article List', icon: 'list' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/tab',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/tab/index',
|
|
||||||
name: 'Tab',
|
|
||||||
meta: { title: 'Tab', icon: 'tab' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/error',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
name: 'ErrorPages',
|
|
||||||
meta: {
|
|
||||||
title: 'Error Pages',
|
|
||||||
icon: '404'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '401',
|
|
||||||
component: 'views/error-page/401',
|
|
||||||
name: 'Page401',
|
|
||||||
meta: { title: 'Page 401', noCache: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '404',
|
|
||||||
component: 'views/error-page/404',
|
|
||||||
name: 'Page404',
|
|
||||||
meta: { title: 'Page 404', noCache: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/error-log',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'log',
|
|
||||||
component: 'views/error-log/index',
|
|
||||||
name: 'ErrorLog',
|
|
||||||
meta: { title: 'Error Log', icon: 'bug' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/excel',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/excel/export-excel',
|
|
||||||
name: 'Excel',
|
|
||||||
meta: {
|
|
||||||
title: 'Excel',
|
|
||||||
icon: 'excel'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'export-excel',
|
|
||||||
component: 'views/excel/export-excel',
|
|
||||||
name: 'ExportExcel',
|
|
||||||
meta: { title: 'Export Excel' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'export-selected-excel',
|
|
||||||
component: 'views/excel/select-excel',
|
|
||||||
name: 'SelectExcel',
|
|
||||||
meta: { title: 'Select Excel' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'export-merge-header',
|
|
||||||
component: 'views/excel/merge-header',
|
|
||||||
name: 'MergeHeader',
|
|
||||||
meta: { title: 'Merge Header' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'upload-excel',
|
|
||||||
component: 'views/excel/upload-excel',
|
|
||||||
name: 'UploadExcel',
|
|
||||||
meta: { title: 'Upload Excel' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/zip',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/zip/download',
|
|
||||||
alwaysShow: true,
|
|
||||||
meta: { title: 'Zip', icon: 'zip' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'download',
|
|
||||||
component: 'views/zip/index',
|
|
||||||
name: 'ExportZip',
|
|
||||||
meta: { title: 'Export Zip' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/pdf',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: '/pdf/index',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/pdf/index',
|
|
||||||
name: 'PDF',
|
|
||||||
meta: { title: 'PDF', icon: 'pdf' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/pdf/download',
|
|
||||||
component: 'views/pdf/download',
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/theme',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/theme/index',
|
|
||||||
name: 'Theme',
|
|
||||||
meta: { title: 'Theme', icon: 'theme' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/clipboard',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/clipboard/index',
|
|
||||||
name: 'ClipboardDemo',
|
|
||||||
meta: { title: 'Clipboard Demo', icon: 'clipboard' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: '/i18n',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: 'views/i18n-demo/index',
|
|
||||||
name: 'I18n',
|
|
||||||
meta: { title: 'I18n', icon: 'international' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
path: 'external-link',
|
|
||||||
component: 'layout/Layout',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'https://github.com/PanJiaChen/vue-element-admin',
|
|
||||||
meta: { title: 'External Link', icon: 'link' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{ path: '*', redirect: '/404', hidden: true }
|
|
||||||
]
|
|
@ -1,84 +0,0 @@
|
|||||||
|
|
||||||
const tokens = {
|
|
||||||
admin: {
|
|
||||||
token: 'admin-token'
|
|
||||||
},
|
|
||||||
editor: {
|
|
||||||
token: 'editor-token'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const users = {
|
|
||||||
'admin-token': {
|
|
||||||
roles: ['admin'],
|
|
||||||
introduction: 'I am a super administrator',
|
|
||||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
|
||||||
name: 'Super Admin'
|
|
||||||
},
|
|
||||||
'editor-token': {
|
|
||||||
roles: ['editor'],
|
|
||||||
introduction: 'I am an editor',
|
|
||||||
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
|
|
||||||
name: 'Normal Editor'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default [
|
|
||||||
// user login
|
|
||||||
{
|
|
||||||
url: '/user/login',
|
|
||||||
type: 'post',
|
|
||||||
response: config => {
|
|
||||||
const { username } = config.body
|
|
||||||
const token = tokens[username]
|
|
||||||
|
|
||||||
// mock error
|
|
||||||
if (!token) {
|
|
||||||
return {
|
|
||||||
code: "60204",
|
|
||||||
message: 'Account and password are incorrect.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
code: "20000",
|
|
||||||
data: token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// get user info
|
|
||||||
{
|
|
||||||
url: '/user/info\.*',
|
|
||||||
type: 'get',
|
|
||||||
response: config => {
|
|
||||||
const { token } = config.query
|
|
||||||
const info = users[token]
|
|
||||||
|
|
||||||
// mock error
|
|
||||||
if (!info) {
|
|
||||||
return {
|
|
||||||
code: "50008",
|
|
||||||
message: 'Login failed, unable to get user details.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
code: "20000",
|
|
||||||
data: info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// user logout
|
|
||||||
{
|
|
||||||
url: '/user/logout',
|
|
||||||
type: 'post',
|
|
||||||
response: _ => {
|
|
||||||
return {
|
|
||||||
code: "20000",
|
|
||||||
data: 'success'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,114 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "vue-element-admin",
|
|
||||||
"version": "4.2.1",
|
|
||||||
"description": "hippo4j console ui",
|
|
||||||
"author": "jingwk",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vue-cli-service serve",
|
|
||||||
"build:prod": "vue-cli-service build",
|
|
||||||
"build:stage": "vue-cli-service build --mode staging",
|
|
||||||
"preview": "node build/index.js --preview",
|
|
||||||
"lint": "eslint --ext .js,.vue src",
|
|
||||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
|
||||||
"test:ci": "npm run lint && npm run test:unit",
|
|
||||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
|
||||||
"new": "plop"
|
|
||||||
},
|
|
||||||
"husky": {
|
|
||||||
"hooks": {
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"src/**/*.{js,vue}": [
|
|
||||||
"eslint --fix",
|
|
||||||
"git add"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"vue",
|
|
||||||
"admin",
|
|
||||||
"dashboard",
|
|
||||||
"element-ui",
|
|
||||||
"boilerplate",
|
|
||||||
"admin-template",
|
|
||||||
"management-system"
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": ">=0.18.1",
|
|
||||||
"clipboard": "2.0.4",
|
|
||||||
"codemirror": "5.45.0",
|
|
||||||
"driver.js": "0.9.5",
|
|
||||||
"dropzone": "5.5.1",
|
|
||||||
"echarts": "^4.2.1",
|
|
||||||
"element-ui": "^2.13.0",
|
|
||||||
"file-saver": "2.0.1",
|
|
||||||
"fuse.js": "3.4.4",
|
|
||||||
"js-cookie": "2.2.0",
|
|
||||||
"jsonlint": "1.6.3",
|
|
||||||
"jszip": "3.2.1",
|
|
||||||
"moment": "^2.24.0",
|
|
||||||
"normalize.css": "7.0.0",
|
|
||||||
"nprogress": "0.2.0",
|
|
||||||
"path-to-regexp": "2.4.0",
|
|
||||||
"screenfull": "4.2.0",
|
|
||||||
"showdown": "1.9.0",
|
|
||||||
"sortablejs": "1.8.4",
|
|
||||||
"tui-editor": "1.3.3",
|
|
||||||
"vue": "2.6.10",
|
|
||||||
"vue-count-to": "1.0.13",
|
|
||||||
"vue-router": "3.0.2",
|
|
||||||
"vue-splitpane": "1.0.4",
|
|
||||||
"vue2-jsoneditor": "^1.0.6",
|
|
||||||
"vuedraggable": "2.20.0",
|
|
||||||
"vuex": "3.1.0",
|
|
||||||
"xlsx": "0.14.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/core": "7.0.0",
|
|
||||||
"@babel/register": "7.0.0",
|
|
||||||
"@vue/cli-plugin-babel": "3.5.3",
|
|
||||||
"@vue/cli-plugin-eslint": "3.5.1",
|
|
||||||
"@vue/cli-plugin-unit-jest": "3.5.3",
|
|
||||||
"@vue/cli-service": "3.5.3",
|
|
||||||
"@vue/test-utils": "1.0.0-beta.29",
|
|
||||||
"autoprefixer": "^9.5.1",
|
|
||||||
"babel-core": "7.0.0-bridge.0",
|
|
||||||
"babel-eslint": "10.0.1",
|
|
||||||
"babel-jest": "23.6.0",
|
|
||||||
"chalk": "2.4.2",
|
|
||||||
"chokidar": "2.1.5",
|
|
||||||
"connect": "3.6.6",
|
|
||||||
"eslint": "5.15.3",
|
|
||||||
"eslint-plugin-vue": "5.2.2",
|
|
||||||
"html-webpack-plugin": "3.2.0",
|
|
||||||
"lint-staged": "8.1.5",
|
|
||||||
"mockjs": "1.0.1-beta3",
|
|
||||||
"node-sass": "^4.9.0",
|
|
||||||
"plop": "2.3.0",
|
|
||||||
"runjs": "^4.3.2",
|
|
||||||
"sass-loader": "^7.1.0",
|
|
||||||
"script-ext-html-webpack-plugin": "2.1.3",
|
|
||||||
"script-loader": "0.7.2",
|
|
||||||
"serve-static": "^1.13.2",
|
|
||||||
"svg-sprite-loader": "4.1.3",
|
|
||||||
"svgo": "1.2.0",
|
|
||||||
"vue-template-compiler": "2.6.10"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.9",
|
|
||||||
"npm": ">= 3.0.0"
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
const viewGenerator = require('./plop-templates/view/prompt')
|
|
||||||
const componentGenerator = require('./plop-templates/component/prompt')
|
|
||||||
|
|
||||||
module.exports = function(plop) {
|
|
||||||
plop.setGenerator('view', viewGenerator)
|
|
||||||
plop.setGenerator('component', componentGenerator)
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
autoprefixer: {}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 6.2 KiB |
@ -1,15 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
||||||
<meta name="renderer" content="webkit">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
|
||||||
<title><%= webpackConfig.name %></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,11 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="app">
|
|
||||||
<router-view />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'App'
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,10 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// dashborad
|
|
||||||
|
|
||||||
export function chartInfo () {
|
|
||||||
return request({
|
|
||||||
url: '/api/dashboard',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function list(listArray) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/list/instance/' + listArray[0] + '/' + listArray[1],
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tenantList(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updated(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/configs?identify=' + data.identify,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function created(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/save_or_update',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleted(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/delete',
|
|
||||||
method: 'delete',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// project
|
|
||||||
|
|
||||||
export function list (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tenantList (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updated (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/update',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function created (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/save',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleted (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/delete/' + data[0] + '/' + data[1],
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getJobProjectList (params) {
|
|
||||||
return request({
|
|
||||||
url: 'api/jobProject/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// project
|
|
||||||
|
|
||||||
export function list (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/tenant/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updated (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/tenant/update',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function created (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/tenant/save',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleted (data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/tenant/delete/' + data,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getJobProjectList (params) {
|
|
||||||
return request({
|
|
||||||
url: 'api/jobProject/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function list(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tenantList(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/item/query/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updated(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/save_or_update',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function created(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/save_or_update',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleted(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/thread/pool/delete',
|
|
||||||
method: 'delete',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function getList(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/auth/users/page',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateUser(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/auth/users/update',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createUser(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/auth/users/add',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteUser(name) {
|
|
||||||
return request({
|
|
||||||
url: '/api/user/remove/' + name,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function getTables(params) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/getTables',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取schema
|
|
||||||
export function getTableSchema(params) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/getDBSchema',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取字段
|
|
||||||
export function getColumns(params) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/getColumns',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据sql获取字段
|
|
||||||
export function getColumnsByQuerySql(params) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/getColumnsByQuerySql',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据datasourceID、tablename创建表【目标端】
|
|
||||||
export function createTable(params) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/createTable',
|
|
||||||
method: 'post',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 判断字段是否存在,存在,即更新值,否则添加字段
|
|
||||||
export function updateColumnsValue(query) {
|
|
||||||
return request({
|
|
||||||
url: '/api/metadata/updateColumnsValue',
|
|
||||||
method: 'post',
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function searchUser(name) {
|
|
||||||
return request({
|
|
||||||
url: '/search/user',
|
|
||||||
method: 'get',
|
|
||||||
params: { name }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transactionList(query) {
|
|
||||||
return request({
|
|
||||||
url: '/transaction/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function getRoutes() {
|
|
||||||
return request({
|
|
||||||
url: '/routes',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRoles() {
|
|
||||||
return request({
|
|
||||||
url: '/roles',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addRole(data) {
|
|
||||||
return request({
|
|
||||||
url: '/role',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateRole(id, data) {
|
|
||||||
return request({
|
|
||||||
url: `/role/${id}`,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteRole(id) {
|
|
||||||
return request({
|
|
||||||
url: `/role/${id}`,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
export function login(data) {
|
|
||||||
return request({
|
|
||||||
url: '/api/auth/login',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInfo() {
|
|
||||||
return request({
|
|
||||||
url: '/api/user/info',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logout() {
|
|
||||||
return request({
|
|
||||||
url: '/api/user/logout',
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
Before Width: | Height: | Size: 160 KiB |
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1,111 +0,0 @@
|
|||||||
<template>
|
|
||||||
<transition :name="transitionName">
|
|
||||||
<div 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>
|
|
||||||
</transition>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'BackToTop',
|
|
||||||
props: {
|
|
||||||
visibilityHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 400
|
|
||||||
},
|
|
||||||
backPosition: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
customStyle: {
|
|
||||||
type: Object,
|
|
||||||
default: function() {
|
|
||||||
return {
|
|
||||||
right: '50px',
|
|
||||||
bottom: '50px',
|
|
||||||
width: '40px',
|
|
||||||
height: '40px',
|
|
||||||
'border-radius': '4px',
|
|
||||||
'line-height': '45px',
|
|
||||||
background: '#e7eaf1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
transitionName: {
|
|
||||||
type: String,
|
|
||||||
default: 'fade'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
interval: null,
|
|
||||||
isMoving: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
window.addEventListener('scroll', this.handleScroll)
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
window.removeEventListener('scroll', this.handleScroll)
|
|
||||||
if (this.interval) {
|
|
||||||
clearInterval(this.interval)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleScroll() {
|
|
||||||
this.visible = window.pageYOffset > this.visibilityHeight
|
|
||||||
},
|
|
||||||
backToTop() {
|
|
||||||
if (this.isMoving) return
|
|
||||||
const start = window.pageYOffset
|
|
||||||
let i = 0
|
|
||||||
this.isMoving = true
|
|
||||||
this.interval = setInterval(() => {
|
|
||||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
|
||||||
if (next <= this.backPosition) {
|
|
||||||
window.scrollTo(0, this.backPosition)
|
|
||||||
clearInterval(this.interval)
|
|
||||||
this.isMoving = false
|
|
||||||
} else {
|
|
||||||
window.scrollTo(0, next)
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}, 16.7)
|
|
||||||
},
|
|
||||||
easeInOutQuad(t, b, c, d) {
|
|
||||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b
|
|
||||||
return -c / 2 * (--t * (t - 2) - 1) + b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.back-to-ceiling {
|
|
||||||
position: fixed;
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-ceiling:hover {
|
|
||||||
background: #d5dbe7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-enter-active,
|
|
||||||
.fade-leave-active {
|
|
||||||
transition: opacity .5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-enter,
|
|
||||||
.fade-leave-to {
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-to-ceiling .Icon {
|
|
||||||
fill: #9aaabf;
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,82 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
|
||||||
<transition-group name="breadcrumb">
|
|
||||||
<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>
|
|
||||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</transition-group>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import pathToRegexp from 'path-to-regexp'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
levelList: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
$route(route) {
|
|
||||||
// if you go to the redirect page, do not update the breadcrumbs
|
|
||||||
if (route.path.startsWith('/redirect/')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.getBreadcrumb()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getBreadcrumb()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getBreadcrumb() {
|
|
||||||
// only show routes with meta.title
|
|
||||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
|
||||||
const first = matched[0]
|
|
||||||
|
|
||||||
if (!this.isDashboard(first)) {
|
|
||||||
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
|
||||||
},
|
|
||||||
isDashboard(route) {
|
|
||||||
const name = route && route.name
|
|
||||||
if (!name) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
|
||||||
},
|
|
||||||
pathCompile(path) {
|
|
||||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
|
||||||
const { params } = this.$route
|
|
||||||
var toPath = pathToRegexp.compile(path)
|
|
||||||
return toPath(params)
|
|
||||||
},
|
|
||||||
handleLink(item) {
|
|
||||||
const { redirect, path } = item
|
|
||||||
if (redirect) {
|
|
||||||
this.$router.push(redirect)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$router.push(this.pathCompile(path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.app-breadcrumb.el-breadcrumb {
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 50px;
|
|
||||||
margin-left: 8px;
|
|
||||||
|
|
||||||
.no-redirect {
|
|
||||||
color: #97a8be;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,155 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts'
|
|
||||||
import resize from './mixins/resize'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mixins: [resize],
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose()
|
|
||||||
this.chart = null
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
|
||||||
|
|
||||||
const xAxisData = []
|
|
||||||
const data = []
|
|
||||||
const data2 = []
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
xAxisData.push(i)
|
|
||||||
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
|
|
||||||
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
|
|
||||||
}
|
|
||||||
this.chart.setOption({
|
|
||||||
backgroundColor: '#08263a',
|
|
||||||
grid: {
|
|
||||||
left: '5%',
|
|
||||||
right: '5%'
|
|
||||||
},
|
|
||||||
xAxis: [{
|
|
||||||
show: false,
|
|
||||||
data: xAxisData
|
|
||||||
}, {
|
|
||||||
show: false,
|
|
||||||
data: xAxisData
|
|
||||||
}],
|
|
||||||
visualMap: {
|
|
||||||
show: false,
|
|
||||||
min: 0,
|
|
||||||
max: 50,
|
|
||||||
dimension: 0,
|
|
||||||
inRange: {
|
|
||||||
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
axisLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#4a657a'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#08263f'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
name: 'back',
|
|
||||||
type: 'bar',
|
|
||||||
data: data2,
|
|
||||||
z: 1,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
opacity: 0.4,
|
|
||||||
barBorderRadius: 5,
|
|
||||||
shadowBlur: 3,
|
|
||||||
shadowColor: '#111'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'Simulate Shadow',
|
|
||||||
type: 'line',
|
|
||||||
data,
|
|
||||||
z: 2,
|
|
||||||
showSymbol: false,
|
|
||||||
animationDelay: 0,
|
|
||||||
animationEasing: 'linear',
|
|
||||||
animationDuration: 1200,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'transparent'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#08263a',
|
|
||||||
shadowBlur: 50,
|
|
||||||
shadowColor: '#000'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'front',
|
|
||||||
type: 'bar',
|
|
||||||
data,
|
|
||||||
xAxisIndex: 1,
|
|
||||||
z: 3,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
barBorderRadius: 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
animationEasing: 'elasticOut',
|
|
||||||
animationEasingUpdate: 'elasticOut',
|
|
||||||
animationDelay(idx) {
|
|
||||||
return idx * 20
|
|
||||||
},
|
|
||||||
animationDelayUpdate(idx) {
|
|
||||||
return idx * 20
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,227 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts'
|
|
||||||
import resize from './mixins/resize'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mixins: [resize],
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose()
|
|
||||||
this.chart = null
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
|
||||||
|
|
||||||
this.chart.setOption({
|
|
||||||
backgroundColor: '#394056',
|
|
||||||
title: {
|
|
||||||
top: 20,
|
|
||||||
text: 'Requests',
|
|
||||||
textStyle: {
|
|
||||||
fontWeight: 'normal',
|
|
||||||
fontSize: 16,
|
|
||||||
color: '#F1F1F3'
|
|
||||||
},
|
|
||||||
left: '1%'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
top: 20,
|
|
||||||
icon: 'rect',
|
|
||||||
itemWidth: 14,
|
|
||||||
itemHeight: 5,
|
|
||||||
itemGap: 13,
|
|
||||||
data: ['CMCC', 'CTCC', 'CUCC'],
|
|
||||||
right: '4%',
|
|
||||||
textStyle: {
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#F1F1F3'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: 100,
|
|
||||||
left: '2%',
|
|
||||||
right: '2%',
|
|
||||||
bottom: '2%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: [{
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
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']
|
|
||||||
}],
|
|
||||||
yAxis: [{
|
|
||||||
type: 'value',
|
|
||||||
name: '(%)',
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
margin: 10,
|
|
||||||
textStyle: {
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#57617B'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
series: [{
|
|
||||||
name: 'CMCC',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(137, 189, 27, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(137, 189, 27, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(137,189,27)',
|
|
||||||
borderColor: 'rgba(137,189,2,0.27)',
|
|
||||||
borderWidth: 12
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
|
||||||
}, {
|
|
||||||
name: 'CTCC',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(0, 136, 212, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(0, 136, 212, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(0,136,212)',
|
|
||||||
borderColor: 'rgba(0,136,212,0.2)',
|
|
||||||
borderWidth: 12
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
|
||||||
}, {
|
|
||||||
name: 'CUCC',
|
|
||||||
type: 'line',
|
|
||||||
smooth: true,
|
|
||||||
symbol: 'circle',
|
|
||||||
symbolSize: 5,
|
|
||||||
showSymbol: false,
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
normal: {
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
|
||||||
offset: 0,
|
|
||||||
color: 'rgba(219, 50, 51, 0.3)'
|
|
||||||
}, {
|
|
||||||
offset: 0.8,
|
|
||||||
color: 'rgba(219, 50, 51, 0)'
|
|
||||||
}], false),
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
||||||
shadowBlur: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgb(219,50,51)',
|
|
||||||
borderColor: 'rgba(219,50,51,0.2)',
|
|
||||||
borderWidth: 12
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,271 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import echarts from 'echarts'
|
|
||||||
import resize from './mixins/resize'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
mixins: [resize],
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
default: 'chart'
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '200px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chart: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initChart()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (!this.chart) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.chart.dispose()
|
|
||||||
this.chart = null
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(document.getElementById(this.id))
|
|
||||||
const xData = (function() {
|
|
||||||
const data = []
|
|
||||||
for (let i = 1; i < 13; i++) {
|
|
||||||
data.push(i + 'month')
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}())
|
|
||||||
this.chart.setOption({
|
|
||||||
backgroundColor: '#344b58',
|
|
||||||
title: {
|
|
||||||
text: 'statistics',
|
|
||||||
x: '20',
|
|
||||||
top: '20',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: '22'
|
|
||||||
},
|
|
||||||
subtextStyle: {
|
|
||||||
color: '#90979c',
|
|
||||||
fontSize: '16'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: '5%',
|
|
||||||
right: '5%',
|
|
||||||
borderWidth: 0,
|
|
||||||
top: 150,
|
|
||||||
bottom: 95,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
x: '5%',
|
|
||||||
top: '10%',
|
|
||||||
textStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
},
|
|
||||||
data: ['female', 'male', 'average']
|
|
||||||
},
|
|
||||||
calculable: true,
|
|
||||||
xAxis: [{
|
|
||||||
type: 'category',
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
splitArea: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0
|
|
||||||
|
|
||||||
},
|
|
||||||
data: xData
|
|
||||||
}],
|
|
||||||
yAxis: [{
|
|
||||||
type: 'value',
|
|
||||||
splitLine: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLine: {
|
|
||||||
lineStyle: {
|
|
||||||
color: '#90979c'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisTick: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0
|
|
||||||
},
|
|
||||||
splitArea: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
dataZoom: [{
|
|
||||||
show: true,
|
|
||||||
height: 30,
|
|
||||||
xAxisIndex: [
|
|
||||||
0
|
|
||||||
],
|
|
||||||
bottom: 30,
|
|
||||||
start: 10,
|
|
||||||
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',
|
|
||||||
handleSize: '110%',
|
|
||||||
handleStyle: {
|
|
||||||
color: '#d3dee5'
|
|
||||||
|
|
||||||
},
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff' },
|
|
||||||
borderColor: '#90979c'
|
|
||||||
|
|
||||||
}, {
|
|
||||||
type: 'inside',
|
|
||||||
show: true,
|
|
||||||
height: 15,
|
|
||||||
start: 1,
|
|
||||||
end: 35
|
|
||||||
}],
|
|
||||||
series: [{
|
|
||||||
name: 'female',
|
|
||||||
type: 'bar',
|
|
||||||
stack: 'total',
|
|
||||||
barMaxWidth: 35,
|
|
||||||
barGap: '10%',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(255,144,128,1)',
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
},
|
|
||||||
position: 'insideTop',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
709,
|
|
||||||
1917,
|
|
||||||
2455,
|
|
||||||
2610,
|
|
||||||
1719,
|
|
||||||
1433,
|
|
||||||
1544,
|
|
||||||
3285,
|
|
||||||
5208,
|
|
||||||
3372,
|
|
||||||
2484,
|
|
||||||
4078
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'male',
|
|
||||||
type: 'bar',
|
|
||||||
stack: 'total',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(0,191,183,1)',
|
|
||||||
barBorderRadius: 0,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
327,
|
|
||||||
1776,
|
|
||||||
507,
|
|
||||||
1200,
|
|
||||||
800,
|
|
||||||
482,
|
|
||||||
204,
|
|
||||||
1390,
|
|
||||||
1001,
|
|
||||||
951,
|
|
||||||
381,
|
|
||||||
220
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
name: 'average',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'total',
|
|
||||||
symbolSize: 10,
|
|
||||||
symbol: 'circle',
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: 'rgba(252,230,48,1)',
|
|
||||||
barBorderRadius: 0,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
formatter(p) {
|
|
||||||
return p.value > 0 ? p.value : ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
1036,
|
|
||||||
3693,
|
|
||||||
2962,
|
|
||||||
3810,
|
|
||||||
2519,
|
|
||||||
1915,
|
|
||||||
1748,
|
|
||||||
4675,
|
|
||||||
6209,
|
|
||||||
4323,
|
|
||||||
2865,
|
|
||||||
4298
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,34 +0,0 @@
|
|||||||
import { debounce } from '@/utils'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
$_sidebarElm: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.__resizeHandler = debounce(() => {
|
|
||||||
if (this.chart) {
|
|
||||||
this.chart.resize()
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
window.addEventListener('resize', this.__resizeHandler)
|
|
||||||
|
|
||||||
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
|
||||||
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
window.removeEventListener('resize', this.__resizeHandler)
|
|
||||||
|
|
||||||
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// use $_ for mixins properties
|
|
||||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
|
||||||
$_sidebarResizeHandler(e) {
|
|
||||||
if (e.propertyName === 'width') {
|
|
||||||
this.__resizeHandler()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
<template lang="html">
|
|
||||||
<div :val="value_">
|
|
||||||
<div>
|
|
||||||
<el-radio v-model="type" label="1" size="mini" border>每年</el-radio>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-radio v-model="type" label="5" size="mini" border>不指定</el-radio>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<el-radio v-model="type" label="2" size="mini" border>周期</el-radio>
|
|
||||||
<span style="margin-left: 10px; margin-right: 5px;">从</span>
|
|
||||||
<el-input-number v-model="cycle.start" :min="2000" size="mini" style="width: 100px;" @change="type = '2'" />
|
|
||||||
<span style="margin-left: 5px; margin-right: 5px;">至</span>
|
|
||||||
<el-input-number v-model="cycle.end" :min="2000" size="mini" style="width: 100px;" @change="type = '2'" />
|
|
||||||
年
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: String,
|
|
||||||
default: '*'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
const year = new Date().getFullYear()
|
|
||||||
return {
|
|
||||||
type: '1', // 类型
|
|
||||||
cycle: { // 周期
|
|
||||||
start: year,
|
|
||||||
end: year
|
|
||||||
},
|
|
||||||
loop: { // 循环
|
|
||||||
start: 0,
|
|
||||||
end: 0
|
|
||||||
},
|
|
||||||
week: { // 指定周
|
|
||||||
start: 0,
|
|
||||||
end: 0
|
|
||||||
},
|
|
||||||
work: 0,
|
|
||||||
last: 0,
|
|
||||||
appoint: [] // 指定
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
value_() {
|
|
||||||
const result = []
|
|
||||||
switch (this.type) {
|
|
||||||
case '1': // 每秒
|
|
||||||
result.push('*')
|
|
||||||
break
|
|
||||||
case '2': // 年期
|
|
||||||
result.push(`${this.cycle.start}-${this.cycle.end}`)
|
|
||||||
break
|
|
||||||
case '3': // 循环
|
|
||||||
result.push(`${this.loop.start}/${this.loop.end}`)
|
|
||||||
break
|
|
||||||
case '4': // 指定
|
|
||||||
result.push(this.appoint.join(','))
|
|
||||||
break
|
|
||||||
case '6': // 最后
|
|
||||||
result.push(`${this.last === 0 ? '' : this.last}L`)
|
|
||||||
break
|
|
||||||
default: // 不指定
|
|
||||||
result.push('?')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
this.$emit('input', result.join(''))
|
|
||||||
return result.join('')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'value'(a, b) {
|
|
||||||
this.updateVal()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.updateVal()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateVal() {
|
|
||||||
if (!this.value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.value === '?') {
|
|
||||||
this.type = '5'
|
|
||||||
} else if (this.value.indexOf('-') !== -1) { // 2周期
|
|
||||||
if (this.value.split('-').length === 2) {
|
|
||||||
this.type = '2'
|
|
||||||
this.cycle.start = this.value.split('-')[0]
|
|
||||||
this.cycle.end = this.value.split('-')[1]
|
|
||||||
}
|
|
||||||
} else if (this.value.indexOf('/') !== -1) { // 3循环
|
|
||||||
if (this.value.split('/').length === 2) {
|
|
||||||
this.type = '3'
|
|
||||||
this.loop.start = this.value.split('/')[0]
|
|
||||||
this.loop.end = this.value.split('/')[1]
|
|
||||||
}
|
|
||||||
} else if (this.value.indexOf('*') !== -1) { // 1每
|
|
||||||
this.type = '1'
|
|
||||||
} else if (this.value.indexOf('L') !== -1) { // 6最后
|
|
||||||
this.type = '6'
|
|
||||||
this.last = this.value.replace('L', '')
|
|
||||||
} else if (this.value.indexOf('#') !== -1) { // 7指定周
|
|
||||||
if (this.value.split('#').length === 2) {
|
|
||||||
this.type = '7'
|
|
||||||
this.week.start = this.value.split('#')[0]
|
|
||||||
this.week.end = this.value.split('#')[1]
|
|
||||||
}
|
|
||||||
} else if (this.value.indexOf('W') !== -1) { // 8工作日
|
|
||||||
this.type = '8'
|
|
||||||
this.work = this.value.replace('W', '')
|
|
||||||
} else { // *
|
|
||||||
this.type = '4'
|
|
||||||
this.appoint = this.value.split(',')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="css">
|
|
||||||
.el-checkbox+.el-checkbox {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,138 +0,0 @@
|
|||||||
<template lang="html">
|
|
||||||
<div class="cron" :val="value_">
|
|
||||||
<el-tabs v-model="activeName">
|
|
||||||
<el-tab-pane label="秒" name="s">
|
|
||||||
<second-and-minute v-model="sVal" lable="秒" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="分" name="m">
|
|
||||||
<second-and-minute v-model="mVal" lable="分" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="时" name="h">
|
|
||||||
<hour v-model="hVal" lable="时" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="日" name="d">
|
|
||||||
<day v-model="dVal" lable="日" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="月" name="month">
|
|
||||||
<month v-model="monthVal" lable="月" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="周" name="week">
|
|
||||||
<week v-model="weekVal" lable="周" />
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="年" name="year">
|
|
||||||
<year v-model="yearVal" lable="年" />
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<!-- table -->
|
|
||||||
<el-table :data="tableData" size="mini" border style="width: 100%;">
|
|
||||||
<el-table-column prop="sVal" label="秒" width="70" />
|
|
||||||
<el-table-column prop="mVal" label="分" width="70" />
|
|
||||||
<el-table-column prop="hVal" label="时" width="70" />
|
|
||||||
<el-table-column prop="dVal" label="日" width="70" />
|
|
||||||
<el-table-column prop="monthVal" label="月" width="70" />
|
|
||||||
<el-table-column prop="weekVal" label="周" width="70" />
|
|
||||||
<el-table-column prop="yearVal" label="年" />
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import SecondAndMinute from './component/secondAndMinute'
|
|
||||||
import hour from './component/hour'
|
|
||||||
import day from './component/day'
|
|
||||||
import month from './component/month'
|
|
||||||
import week from './component/week'
|
|
||||||
import year from './component/year'
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
SecondAndMinute,
|
|
||||||
hour,
|
|
||||||
day,
|
|
||||||
month,
|
|
||||||
week,
|
|
||||||
year
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: String
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
//
|
|
||||||
activeName: 's',
|
|
||||||
sVal: '',
|
|
||||||
mVal: '',
|
|
||||||
hVal: '',
|
|
||||||
dVal: '',
|
|
||||||
monthVal: '',
|
|
||||||
weekVal: '',
|
|
||||||
yearVal: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
tableData() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
sVal: this.sVal,
|
|
||||||
mVal: this.mVal,
|
|
||||||
hVal: this.hVal,
|
|
||||||
dVal: this.dVal,
|
|
||||||
monthVal: this.monthVal,
|
|
||||||
weekVal: this.weekVal,
|
|
||||||
yearVal: this.yearVal
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
value_() {
|
|
||||||
if (!this.dVal && !this.weekVal) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
if (this.dVal === '?' && this.weekVal === '?') {
|
|
||||||
this.$message.error('日期与星期不可以同时为“不指定”')
|
|
||||||
}
|
|
||||||
if (this.dVal !== '?' && this.weekVal !== '?') {
|
|
||||||
this.$message.error('日期与星期必须有一个为“不指定”')
|
|
||||||
}
|
|
||||||
const v = `${this.sVal} ${this.mVal} ${this.hVal} ${this.dVal} ${this.monthVal} ${this.weekVal} ${this.yearVal}`
|
|
||||||
if (v !== this.value) {
|
|
||||||
this.$emit('input', v)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(a, b) {
|
|
||||||
this.updateVal()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.updateVal()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateVal() {
|
|
||||||
if (!this.value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const arrays = this.value.split(' ')
|
|
||||||
this.sVal = arrays[0]
|
|
||||||
this.mVal = arrays[1]
|
|
||||||
this.hVal = arrays[2]
|
|
||||||
this.dVal = arrays[3]
|
|
||||||
this.monthVal = arrays[4]
|
|
||||||
this.weekVal = arrays[5]
|
|
||||||
this.yearVal = arrays[6]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="css">
|
|
||||||
.cron {
|
|
||||||
text-align: left;
|
|
||||||
padding: 10px;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #dcdfe6;
|
|
||||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,166 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="dndList">
|
|
||||||
<div :style="{width:width1}" class="dndList-list">
|
|
||||||
<h3>{{ list1Title }}</h3>
|
|
||||||
<draggable :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">
|
|
||||||
{{ element.id }}[{{ element.author }}] {{ element.title }}
|
|
||||||
</div>
|
|
||||||
<div style="position:absolute;right:0px;">
|
|
||||||
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
|
|
||||||
<i style="color:#ff4949" class="el-icon-delete" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
<div :style="{width:width2}" class="dndList-list">
|
|
||||||
<h3>{{ list2Title }}</h3>
|
|
||||||
<draggable :list="list2" group="article" class="dragArea">
|
|
||||||
<div v-for="element in list2" :key="element.id" class="list-complete-item">
|
|
||||||
<div class="list-complete-item-handle2" @click="pushEle(element)">
|
|
||||||
{{ element.id }} [{{ element.author }}] {{ element.title }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import draggable from 'vuedraggable'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DndList',
|
|
||||||
components: { draggable },
|
|
||||||
props: {
|
|
||||||
list1: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list2: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list1Title: {
|
|
||||||
type: String,
|
|
||||||
default: 'list1'
|
|
||||||
},
|
|
||||||
list2Title: {
|
|
||||||
type: String,
|
|
||||||
default: 'list2'
|
|
||||||
},
|
|
||||||
width1: {
|
|
||||||
type: String,
|
|
||||||
default: '48%'
|
|
||||||
},
|
|
||||||
width2: {
|
|
||||||
type: String,
|
|
||||||
default: '48%'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
isNotInList1(v) {
|
|
||||||
return this.list1.every(k => v.id !== k.id)
|
|
||||||
},
|
|
||||||
isNotInList2(v) {
|
|
||||||
return this.list2.every(k => v.id !== k.id)
|
|
||||||
},
|
|
||||||
deleteEle(ele) {
|
|
||||||
for (const item of this.list1) {
|
|
||||||
if (item.id === ele.id) {
|
|
||||||
const index = this.list1.indexOf(item)
|
|
||||||
this.list1.splice(index, 1)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.isNotInList2(ele)) {
|
|
||||||
this.list2.unshift(ele)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pushEle(ele) {
|
|
||||||
for (const item of this.list2) {
|
|
||||||
if (item.id === ele.id) {
|
|
||||||
const index = this.list2.indexOf(item)
|
|
||||||
this.list2.splice(index, 1)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.isNotInList1(ele)) {
|
|
||||||
this.list1.push(ele)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setData(dataTransfer) {
|
|
||||||
// to avoid Firefox bug
|
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
|
||||||
dataTransfer.setData('Text', '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.dndList {
|
|
||||||
background: #fff;
|
|
||||||
padding-bottom: 40px;
|
|
||||||
&:after {
|
|
||||||
content: "";
|
|
||||||
display: table;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.dndList-list {
|
|
||||||
float: left;
|
|
||||||
padding-bottom: 30px;
|
|
||||||
&:first-of-type {
|
|
||||||
margin-right: 2%;
|
|
||||||
}
|
|
||||||
.dragArea {
|
|
||||||
margin-top: 15px;
|
|
||||||
min-height: 50px;
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-item {
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
border: 1px solid #bfcbd9;
|
|
||||||
transition: all 1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-item-handle {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
margin-right: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-item-handle2 {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-item.sortable-chosen {
|
|
||||||
background: #4AB7BD;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-item.sortable-ghost {
|
|
||||||
background: #30B08F;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-complete-enter,
|
|
||||||
.list-complete-leave-active {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,61 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
|
|
||||||
<slot />
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Sortable from 'sortablejs'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DragSelect',
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: Array,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
selectVal: {
|
|
||||||
get() {
|
|
||||||
return [...this.value]
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$emit('input', [...val])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.setSort()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setSort() {
|
|
||||||
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
|
|
||||||
this.sortable = Sortable.create(el, {
|
|
||||||
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
|
|
||||||
setData: function(dataTransfer) {
|
|
||||||
dataTransfer.setData('Text', '')
|
|
||||||
// to avoid Firefox bug
|
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
|
||||||
},
|
|
||||||
onEnd: evt => {
|
|
||||||
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
|
|
||||||
this.value.splice(evt.newIndex, 0, targetRow)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.drag-select >>> .sortable-ghost {
|
|
||||||
opacity: .8;
|
|
||||||
color: #fff!important;
|
|
||||||
background: #42b983!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drag-select >>> .el-tag {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,297 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :id="id" :ref="id" :action="url" class="dropzone">
|
|
||||||
<input type="file" name="file">
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Dropzone from 'dropzone'
|
|
||||||
import 'dropzone/dist/dropzone.css'
|
|
||||||
// import { getToken } from 'api/qiniu';
|
|
||||||
|
|
||||||
Dropzone.autoDiscover = false
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
url: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
clickable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
defaultMsg: {
|
|
||||||
type: String,
|
|
||||||
default: '上传图片'
|
|
||||||
},
|
|
||||||
acceptedFiles: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
thumbnailHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 200
|
|
||||||
},
|
|
||||||
thumbnailWidth: {
|
|
||||||
type: Number,
|
|
||||||
default: 200
|
|
||||||
},
|
|
||||||
showRemoveLink: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
maxFilesize: {
|
|
||||||
type: Number,
|
|
||||||
default: 2
|
|
||||||
},
|
|
||||||
maxFiles: {
|
|
||||||
type: Number,
|
|
||||||
default: 3
|
|
||||||
},
|
|
||||||
autoProcessQueue: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
useCustomDropzoneOptions: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
defaultImg: {
|
|
||||||
default: '',
|
|
||||||
type: [String, Array]
|
|
||||||
},
|
|
||||||
couldPaste: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dropzone: '',
|
|
||||||
initOnce: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
defaultImg(val) {
|
|
||||||
if (val.length === 0) {
|
|
||||||
this.initOnce = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!this.initOnce) return
|
|
||||||
this.initImages(val)
|
|
||||||
this.initOnce = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const element = document.getElementById(this.id)
|
|
||||||
const vm = this
|
|
||||||
this.dropzone = new Dropzone(element, {
|
|
||||||
clickable: this.clickable,
|
|
||||||
thumbnailWidth: this.thumbnailWidth,
|
|
||||||
thumbnailHeight: this.thumbnailHeight,
|
|
||||||
maxFiles: this.maxFiles,
|
|
||||||
maxFilesize: this.maxFilesize,
|
|
||||||
dictRemoveFile: 'Remove',
|
|
||||||
addRemoveLinks: this.showRemoveLink,
|
|
||||||
acceptedFiles: this.acceptedFiles,
|
|
||||||
autoProcessQueue: this.autoProcessQueue,
|
|
||||||
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + 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() {
|
|
||||||
const val = vm.defaultImg
|
|
||||||
if (!val) return
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
if (val.length === 0) return
|
|
||||||
val.map((v, i) => {
|
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
|
||||||
this.options.addedfile.call(this, mockFile)
|
|
||||||
this.options.thumbnail.call(this, mockFile, v)
|
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
|
||||||
vm.initOnce = false
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const mockFile = { name: 'name', size: 12345, url: val }
|
|
||||||
this.options.addedfile.call(this, mockFile)
|
|
||||||
this.options.thumbnail.call(this, mockFile, val)
|
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
|
||||||
vm.initOnce = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
accept: (file, done) => {
|
|
||||||
/* 七牛*/
|
|
||||||
// const token = this.$store.getters.token;
|
|
||||||
// getToken(token).then(response => {
|
|
||||||
// file.token = response.data.qiniu_token;
|
|
||||||
// file.key = response.data.qiniu_key;
|
|
||||||
// file.url = response.data.qiniu_url;
|
|
||||||
// done();
|
|
||||||
// })
|
|
||||||
done()
|
|
||||||
},
|
|
||||||
sending: (file, xhr, formData) => {
|
|
||||||
// formData.append('token', file.token);
|
|
||||||
// formData.append('key', file.key);
|
|
||||||
vm.initOnce = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (this.couldPaste) {
|
|
||||||
document.addEventListener('paste', this.pasteImg)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dropzone.on('success', file => {
|
|
||||||
vm.$emit('dropzone-success', file, vm.dropzone.element)
|
|
||||||
})
|
|
||||||
this.dropzone.on('addedfile', file => {
|
|
||||||
vm.$emit('dropzone-fileAdded', file)
|
|
||||||
})
|
|
||||||
this.dropzone.on('removedfile', file => {
|
|
||||||
vm.$emit('dropzone-removedFile', file)
|
|
||||||
})
|
|
||||||
this.dropzone.on('error', (file, error, xhr) => {
|
|
||||||
vm.$emit('dropzone-error', file, error, xhr)
|
|
||||||
})
|
|
||||||
this.dropzone.on('successmultiple', (file, error, xhr) => {
|
|
||||||
vm.$emit('dropzone-successmultiple', file, error, xhr)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
document.removeEventListener('paste', this.pasteImg)
|
|
||||||
this.dropzone.destroy()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
removeAllFiles() {
|
|
||||||
this.dropzone.removeAllFiles(true)
|
|
||||||
},
|
|
||||||
processQueue() {
|
|
||||||
this.dropzone.processQueue()
|
|
||||||
},
|
|
||||||
pasteImg(event) {
|
|
||||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items
|
|
||||||
if (items[0].kind === 'file') {
|
|
||||||
this.dropzone.addFile(items[0].getAsFile())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initImages(val) {
|
|
||||||
if (!val) return
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
val.map((v, i) => {
|
|
||||||
const mockFile = { name: 'name' + i, size: 12345, url: v }
|
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
|
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const mockFile = { name: 'name', size: 12345, url: val }
|
|
||||||
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
|
|
||||||
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
|
|
||||||
mockFile.previewElement.classList.add('dz-success')
|
|
||||||
mockFile.previewElement.classList.add('dz-complete')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.dropzone {
|
|
||||||
border: 2px solid #E5E5E5;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
color: #777;
|
|
||||||
transition: background-color .2s linear;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone:hover {
|
|
||||||
background-color: #F6F6F6;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #CCC;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-image img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone input[name='file'] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-image {
|
|
||||||
border-radius: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-image img {
|
|
||||||
transform: none;
|
|
||||||
filter: none;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details {
|
|
||||||
bottom: 0px;
|
|
||||||
top: 0px;
|
|
||||||
color: white;
|
|
||||||
background-color: rgba(33, 150, 243, 0.8);
|
|
||||||
transition: opacity .2s linear;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-details .dz-filename:hover span {
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-remove {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 30;
|
|
||||||
color: white;
|
|
||||||
margin-left: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
top: inherit;
|
|
||||||
bottom: 15px;
|
|
||||||
border: 2px white solid;
|
|
||||||
text-decoration: none;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: 1.1px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview:hover .dz-remove {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
|
|
||||||
margin-left: -40px;
|
|
||||||
margin-top: -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropzone .dz-preview .dz-success-mark i, .dropzone .dz-preview .dz-error-mark i {
|
|
||||||
color: white;
|
|
||||||
font-size: 5rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,78 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="errorLogs.length>0">
|
|
||||||
<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">
|
|
||||||
<svg-icon icon-class="bug" />
|
|
||||||
</el-button>
|
|
||||||
</el-badge>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
|
|
||||||
<div slot="title">
|
|
||||||
<span style="padding-right: 10px;">Error Log</span>
|
|
||||||
<el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</el-button>
|
|
||||||
</div>
|
|
||||||
<el-table :data="errorLogs" border>
|
|
||||||
<el-table-column label="Message">
|
|
||||||
<template slot-scope="{row}">
|
|
||||||
<div>
|
|
||||||
<span class="message-title">Msg:</span>
|
|
||||||
<el-tag type="danger">
|
|
||||||
{{ row.err.message }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div>
|
|
||||||
<span class="message-title" style="padding-right: 10px;">Info: </span>
|
|
||||||
<el-tag type="warning">
|
|
||||||
{{ row.vm.$vnode.tag }} error in {{ row.info }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div>
|
|
||||||
<span class="message-title" style="padding-right: 16px;">Url: </span>
|
|
||||||
<el-tag type="success">
|
|
||||||
{{ row.url }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="Stack">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ scope.row.err.stack }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'ErrorLog',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogTableVisible: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
errorLogs() {
|
|
||||||
return this.$store.getters.errorLogs
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
clearAll() {
|
|
||||||
this.dialogTableVisible = false
|
|
||||||
this.$store.dispatch('errorLog/clearErrorLog')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.message-title {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: bold;
|
|
||||||
padding-right: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,54 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
|
|
||||||
<svg
|
|
||||||
width="80"
|
|
||||||
height="80"
|
|
||||||
viewBox="0 0 250 250"
|
|
||||||
style="fill:#40c9c6; color:#fff;"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
|
|
||||||
<path
|
|
||||||
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
|
|
||||||
fill="currentColor"
|
|
||||||
style="transform-origin: 130px 106px;"
|
|
||||||
class="octo-arm"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
|
|
||||||
fill="currentColor"
|
|
||||||
class="octo-body"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.github-corner:hover .octo-arm {
|
|
||||||
animation: octocat-wave 560ms ease-in-out
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes octocat-wave {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
transform: rotate(0)
|
|
||||||
}
|
|
||||||
20%,
|
|
||||||
60% {
|
|
||||||
transform: rotate(-25deg)
|
|
||||||
}
|
|
||||||
40%,
|
|
||||||
80% {
|
|
||||||
transform: rotate(10deg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:500px) {
|
|
||||||
.github-corner:hover .octo-arm {
|
|
||||||
animation: none
|
|
||||||
}
|
|
||||||
.github-corner .octo-arm {
|
|
||||||
animation: octocat-wave 560ms ease-in-out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,44 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div style="padding: 0 15px;" @click="toggleClick">
|
|
||||||
<svg
|
|
||||||
:class="{'is-active':isActive}"
|
|
||||||
class="hamburger"
|
|
||||||
viewBox="0 0 1024 1024"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="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" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'Hamburger',
|
|
||||||
props: {
|
|
||||||
isActive: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleClick() {
|
|
||||||
this.$emit('toggleClick')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.hamburger {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger.is-active {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,180 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :class="{'show':show}" class="header-search">
|
|
||||||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
|
||||||
<el-select
|
|
||||||
ref="headerSearchSelect"
|
|
||||||
v-model="search"
|
|
||||||
:remote-method="querySearch"
|
|
||||||
filterable
|
|
||||||
default-first-option
|
|
||||||
remote
|
|
||||||
placeholder="Search"
|
|
||||||
class="header-search-select"
|
|
||||||
@change="change"
|
|
||||||
>
|
|
||||||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// fuse is a lightweight fuzzy-search module
|
|
||||||
// make search results more in line with expectations
|
|
||||||
import Fuse from 'fuse.js'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'HeaderSearch',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
search: '',
|
|
||||||
options: [],
|
|
||||||
searchPool: [],
|
|
||||||
show: false,
|
|
||||||
fuse: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
routes() {
|
|
||||||
return this.$store.getters.permission_routes
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
routes() {
|
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
|
||||||
},
|
|
||||||
searchPool(list) {
|
|
||||||
this.initFuse(list)
|
|
||||||
},
|
|
||||||
show(value) {
|
|
||||||
if (value) {
|
|
||||||
document.body.addEventListener('click', this.close)
|
|
||||||
} else {
|
|
||||||
document.body.removeEventListener('click', this.close)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.searchPool = this.generateRoutes(this.routes)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
click() {
|
|
||||||
this.show = !this.show
|
|
||||||
if (this.show) {
|
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
|
|
||||||
this.options = []
|
|
||||||
this.show = false
|
|
||||||
},
|
|
||||||
change(val) {
|
|
||||||
this.$router.push(val.path)
|
|
||||||
this.search = ''
|
|
||||||
this.options = []
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.show = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
initFuse(list) {
|
|
||||||
this.fuse = new Fuse(list, {
|
|
||||||
shouldSort: true,
|
|
||||||
threshold: 0.4,
|
|
||||||
location: 0,
|
|
||||||
distance: 100,
|
|
||||||
maxPatternLength: 32,
|
|
||||||
minMatchCharLength: 1,
|
|
||||||
keys: [{
|
|
||||||
name: 'title',
|
|
||||||
weight: 0.7
|
|
||||||
}, {
|
|
||||||
name: 'path',
|
|
||||||
weight: 0.3
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// Filter out the routes that can be displayed in the sidebar
|
|
||||||
// And generate the internationalized title
|
|
||||||
generateRoutes(routes, basePath = '/', prefixTitle = []) {
|
|
||||||
let res = []
|
|
||||||
|
|
||||||
for (const router of routes) {
|
|
||||||
// skip hidden router
|
|
||||||
if (router.hidden) { continue }
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
path: path.resolve(basePath, router.path),
|
|
||||||
title: [...prefixTitle]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (router.meta && router.meta.title) {
|
|
||||||
data.title = [...data.title, router.meta.title]
|
|
||||||
|
|
||||||
if (router.redirect !== 'noRedirect') {
|
|
||||||
// only push the routes with title
|
|
||||||
// special case: need to exclude parent router without redirect
|
|
||||||
res.push(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// recursive child routes
|
|
||||||
if (router.children) {
|
|
||||||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
|
|
||||||
if (tempRoutes.length >= 1) {
|
|
||||||
res = [...res, ...tempRoutes]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
},
|
|
||||||
querySearch(query) {
|
|
||||||
if (query !== '') {
|
|
||||||
this.options = this.fuse.search(query)
|
|
||||||
} else {
|
|
||||||
this.options = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.header-search {
|
|
||||||
font-size: 0 !important;
|
|
||||||
|
|
||||||
.search-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 18px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-search-select {
|
|
||||||
font-size: 18px;
|
|
||||||
transition: width 0.2s;
|
|
||||||
width: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
background: transparent;
|
|
||||||
border-radius: 0;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
/deep/ .el-input__inner {
|
|
||||||
border-radius: 0;
|
|
||||||
border: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
box-shadow: none !important;
|
|
||||||
border-bottom: 1px solid #d9d9d9;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.show {
|
|
||||||
.header-search-select {
|
|
||||||
width: 210px;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
File diff suppressed because it is too large
Load Diff
@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
* 点击波纹效果
|
|
||||||
*
|
|
||||||
* @param {[event]} e [description]
|
|
||||||
* @param {[Object]} arg_opts [description]
|
|
||||||
* @return {[bollean]} [description]
|
|
||||||
*/
|
|
||||||
export default function(e, arg_opts) {
|
|
||||||
var opts = Object.assign({
|
|
||||||
ele: e.target, // 波纹作用元素
|
|
||||||
type: 'hit', // hit点击位置扩散center中心点扩展
|
|
||||||
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
|
||||||
}, arg_opts)
|
|
||||||
var target = opts.ele
|
|
||||||
if (target) {
|
|
||||||
var rect = target.getBoundingClientRect()
|
|
||||||
var ripple = target.querySelector('.e-ripple')
|
|
||||||
if (!ripple) {
|
|
||||||
ripple = document.createElement('span')
|
|
||||||
ripple.className = 'e-ripple'
|
|
||||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
|
|
||||||
target.appendChild(ripple)
|
|
||||||
} else {
|
|
||||||
ripple.className = 'e-ripple'
|
|
||||||
}
|
|
||||||
switch (opts.type) {
|
|
||||||
case 'center':
|
|
||||||
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
|
|
||||||
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
ripple.style.top = (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.className = 'e-ripple z-active'
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
export default {
|
|
||||||
'jpg': 'image/jpeg',
|
|
||||||
'png': 'image/png',
|
|
||||||
'gif': 'image/gif',
|
|
||||||
'svg': 'image/svg+xml',
|
|
||||||
'psd': 'image/photoshop'
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="json-editor">
|
|
||||||
<textarea ref="textarea" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
import 'codemirror/addon/lint/lint.css'
|
|
||||||
import 'codemirror/lib/codemirror.css'
|
|
||||||
import 'codemirror/theme/rubyblue.css'
|
|
||||||
require('script-loader!jsonlint')
|
|
||||||
import 'codemirror/mode/javascript/javascript'
|
|
||||||
import 'codemirror/addon/lint/lint'
|
|
||||||
import 'codemirror/addon/lint/json-lint'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'JsonEditor',
|
|
||||||
/* eslint-disable vue/require-prop-types */
|
|
||||||
props: ['value'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
jsonEditor: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(value) {
|
|
||||||
const editorValue = this.jsonEditor.getValue()
|
|
||||||
if (value !== editorValue) {
|
|
||||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: 'application/json',
|
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
|
||||||
theme: 'rubyblue',
|
|
||||||
lint: true
|
|
||||||
})
|
|
||||||
|
|
||||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
|
|
||||||
this.jsonEditor.on('change', cm => {
|
|
||||||
this.$emit('changed', cm.getValue())
|
|
||||||
this.$emit('input', cm.getValue())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getValue() {
|
|
||||||
return this.jsonEditor.getValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.json-editor{
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.json-editor >>> .CodeMirror {
|
|
||||||
height: auto;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.json-editor >>> .CodeMirror-scroll{
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.json-editor >>> .cm-s-rubyblue span.cm-string {
|
|
||||||
color: #F08047;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,99 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="board-column">
|
|
||||||
<div class="board-column-header">
|
|
||||||
{{ headerText }}
|
|
||||||
</div>
|
|
||||||
<draggable
|
|
||||||
:list="list"
|
|
||||||
v-bind="$attrs"
|
|
||||||
class="board-column-content"
|
|
||||||
:set-data="setData"
|
|
||||||
>
|
|
||||||
<div v-for="element in list" :key="element.id" class="board-item">
|
|
||||||
{{ element.name }} {{ element.id }}
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import draggable from 'vuedraggable'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DragKanbanDemo',
|
|
||||||
components: {
|
|
||||||
draggable
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
headerText: {
|
|
||||||
type: String,
|
|
||||||
default: 'Header'
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
list: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setData(dataTransfer) {
|
|
||||||
// to avoid Firefox bug
|
|
||||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
|
||||||
dataTransfer.setData('Text', '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.board-column {
|
|
||||||
min-width: 300px;
|
|
||||||
min-height: 100px;
|
|
||||||
height: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #f0f0f0;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
.board-column-header {
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0 20px;
|
|
||||||
text-align: center;
|
|
||||||
background: #333;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 3px 3px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.board-column-content {
|
|
||||||
height: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 10px solid transparent;
|
|
||||||
min-height: 60px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.board-item {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 100%;
|
|
||||||
height: 64px;
|
|
||||||
margin: 5px 0;
|
|
||||||
background-color: #fff;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 54px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,360 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :class="computedClasses" class="material-input__component">
|
|
||||||
<div :class="{iconClass:icon}">
|
|
||||||
<i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
|
|
||||||
<input
|
|
||||||
v-if="type === 'email'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:required="required"
|
|
||||||
type="email"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-if="type === 'url'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:required="required"
|
|
||||||
type="url"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-if="type === 'number'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:step="step"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:max="max"
|
|
||||||
:min="min"
|
|
||||||
:minlength="minlength"
|
|
||||||
:maxlength="maxlength"
|
|
||||||
:required="required"
|
|
||||||
type="number"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-if="type === 'password'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:max="max"
|
|
||||||
:min="min"
|
|
||||||
:required="required"
|
|
||||||
type="password"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-if="type === 'tel'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:required="required"
|
|
||||||
type="tel"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
v-if="type === 'text'"
|
|
||||||
v-model="currentValue"
|
|
||||||
:name="name"
|
|
||||||
:placeholder="fillPlaceHolder"
|
|
||||||
:readonly="readonly"
|
|
||||||
:disabled="disabled"
|
|
||||||
:autocomplete="autoComplete"
|
|
||||||
:minlength="minlength"
|
|
||||||
:maxlength="maxlength"
|
|
||||||
:required="required"
|
|
||||||
type="text"
|
|
||||||
class="material-input"
|
|
||||||
@focus="handleMdFocus"
|
|
||||||
@blur="handleMdBlur"
|
|
||||||
@input="handleModelInput"
|
|
||||||
>
|
|
||||||
<span class="material-input-bar" />
|
|
||||||
<label class="material-label">
|
|
||||||
<slot />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MdInput',
|
|
||||||
props: {
|
|
||||||
/* eslint-disable */
|
|
||||||
icon: String,
|
|
||||||
name: String,
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
default: 'text'
|
|
||||||
},
|
|
||||||
value: [String, Number],
|
|
||||||
placeholder: String,
|
|
||||||
readonly: Boolean,
|
|
||||||
disabled: Boolean,
|
|
||||||
min: String,
|
|
||||||
max: String,
|
|
||||||
step: String,
|
|
||||||
minlength: Number,
|
|
||||||
maxlength: Number,
|
|
||||||
required: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
autoComplete: {
|
|
||||||
type: String,
|
|
||||||
default: 'off'
|
|
||||||
},
|
|
||||||
validateEvent: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
currentValue: this.value,
|
|
||||||
focus: false,
|
|
||||||
fillPlaceHolder: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
computedClasses() {
|
|
||||||
return {
|
|
||||||
'material--active': this.focus,
|
|
||||||
'material--disabled': this.disabled,
|
|
||||||
'material--raised': Boolean(this.focus || this.currentValue) // has value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(newValue) {
|
|
||||||
this.currentValue = newValue
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleModelInput(event) {
|
|
||||||
const value = event.target.value
|
|
||||||
this.$emit('input', value)
|
|
||||||
if (this.$parent.$options.componentName === 'ElFormItem') {
|
|
||||||
if (this.validateEvent) {
|
|
||||||
this.$parent.$emit('el.form.change', [value])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$emit('change', value)
|
|
||||||
},
|
|
||||||
handleMdFocus(event) {
|
|
||||||
this.focus = true
|
|
||||||
this.$emit('focus', event)
|
|
||||||
if (this.placeholder && this.placeholder !== '') {
|
|
||||||
this.fillPlaceHolder = this.placeholder
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleMdBlur(event) {
|
|
||||||
this.focus = false
|
|
||||||
this.$emit('blur', event)
|
|
||||||
this.fillPlaceHolder = null
|
|
||||||
if (this.$parent.$options.componentName === 'ElFormItem') {
|
|
||||||
if (this.validateEvent) {
|
|
||||||
this.$parent.$emit('el.form.blur', [this.currentValue])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
// Fonts:
|
|
||||||
$font-size-base: 16px;
|
|
||||||
$font-size-small: 18px;
|
|
||||||
$font-size-smallest: 12px;
|
|
||||||
$font-weight-normal: normal;
|
|
||||||
$font-weight-bold: bold;
|
|
||||||
$apixel: 1px;
|
|
||||||
// Utils
|
|
||||||
$spacer: 12px;
|
|
||||||
$transition: 0.2s ease all;
|
|
||||||
$index: 0px;
|
|
||||||
$index-has-icon: 30px;
|
|
||||||
// Theme:
|
|
||||||
$color-white: white;
|
|
||||||
$color-grey: #9E9E9E;
|
|
||||||
$color-grey-light: #E0E0E0;
|
|
||||||
$color-blue: #2196F3;
|
|
||||||
$color-red: #F44336;
|
|
||||||
$color-black: black;
|
|
||||||
// Base clases:
|
|
||||||
%base-bar-pseudo {
|
|
||||||
content: '';
|
|
||||||
height: 1px;
|
|
||||||
width: 0;
|
|
||||||
bottom: 0;
|
|
||||||
position: absolute;
|
|
||||||
transition: $transition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mixins:
|
|
||||||
@mixin slided-top() {
|
|
||||||
top: - ($font-size-base + $spacer);
|
|
||||||
left: 0;
|
|
||||||
font-size: $font-size-base;
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Component:
|
|
||||||
.material-input__component {
|
|
||||||
margin-top: 36px;
|
|
||||||
position: relative;
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.iconClass {
|
|
||||||
.material-input__icon {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
line-height: $font-size-base;
|
|
||||||
color: $color-blue;
|
|
||||||
top: $spacer;
|
|
||||||
width: $index-has-icon;
|
|
||||||
height: $font-size-base;
|
|
||||||
font-size: $font-size-base;
|
|
||||||
font-weight: $font-weight-normal;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.material-label {
|
|
||||||
left: $index-has-icon;
|
|
||||||
}
|
|
||||||
.material-input {
|
|
||||||
text-indent: $index-has-icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.material-input {
|
|
||||||
font-size: $font-size-base;
|
|
||||||
padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: none;
|
|
||||||
line-height: 1;
|
|
||||||
border-radius: 0;
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid transparent; // fixes the height issue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.material-label {
|
|
||||||
font-weight: $font-weight-normal;
|
|
||||||
position: absolute;
|
|
||||||
pointer-events: none;
|
|
||||||
left: $index;
|
|
||||||
top: 0;
|
|
||||||
transition: $transition;
|
|
||||||
font-size: $font-size-small;
|
|
||||||
}
|
|
||||||
.material-input-bar {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
&:before {
|
|
||||||
@extend %base-bar-pseudo;
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
@extend %base-bar-pseudo;
|
|
||||||
right: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Disabled state:
|
|
||||||
&.material--disabled {
|
|
||||||
.material-input {
|
|
||||||
border-bottom-style: dashed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Raised state:
|
|
||||||
&.material--raised {
|
|
||||||
.material-label {
|
|
||||||
@include slided-top();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Active state:
|
|
||||||
&.material--active {
|
|
||||||
.material-input-bar {
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.material-input__component {
|
|
||||||
background: $color-white;
|
|
||||||
.material-input {
|
|
||||||
background: none;
|
|
||||||
color: $color-black;
|
|
||||||
text-indent: $index;
|
|
||||||
border-bottom: 1px solid $color-grey-light;
|
|
||||||
}
|
|
||||||
.material-label {
|
|
||||||
color: $color-grey;
|
|
||||||
}
|
|
||||||
.material-input-bar {
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
background: $color-blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Active state:
|
|
||||||
&.material--active {
|
|
||||||
.material-label {
|
|
||||||
color: $color-blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Errors:
|
|
||||||
&.material--has-errors {
|
|
||||||
&.material--active .material-label {
|
|
||||||
color: $color-red;
|
|
||||||
}
|
|
||||||
.material-input-bar {
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,31 +0,0 @@
|
|||||||
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
|
|
||||||
export default {
|
|
||||||
minHeight: '200px',
|
|
||||||
previewStyle: 'vertical',
|
|
||||||
useCommandShortcut: true,
|
|
||||||
useDefaultHTMLSanitizer: true,
|
|
||||||
usageStatistics: false,
|
|
||||||
hideModeSwitch: false,
|
|
||||||
toolbarItems: [
|
|
||||||
'heading',
|
|
||||||
'bold',
|
|
||||||
'italic',
|
|
||||||
'strike',
|
|
||||||
'divider',
|
|
||||||
'hr',
|
|
||||||
'quote',
|
|
||||||
'divider',
|
|
||||||
'ul',
|
|
||||||
'ol',
|
|
||||||
'task',
|
|
||||||
'indent',
|
|
||||||
'outdent',
|
|
||||||
'divider',
|
|
||||||
'table',
|
|
||||||
'image',
|
|
||||||
'link',
|
|
||||||
'divider',
|
|
||||||
'code',
|
|
||||||
'codeblock'
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :id="id" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// deps for editor
|
|
||||||
import 'codemirror/lib/codemirror.css' // codemirror
|
|
||||||
import 'tui-editor/dist/tui-editor.css' // editor ui
|
|
||||||
import 'tui-editor/dist/tui-editor-contents.css' // editor content
|
|
||||||
|
|
||||||
import Editor from 'tui-editor'
|
|
||||||
import defaultOptions from './default-options'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MarddownEditor',
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default() {
|
|
||||||
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return defaultOptions
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mode: {
|
|
||||||
type: String,
|
|
||||||
default: 'markdown'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: '300px'
|
|
||||||
},
|
|
||||||
language: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
editor: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
editorOptions() {
|
|
||||||
const options = Object.assign({}, defaultOptions, this.options)
|
|
||||||
options.initialEditType = this.mode
|
|
||||||
options.height = this.height
|
|
||||||
options.language = this.language
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(newValue, preValue) {
|
|
||||||
if (newValue !== preValue && newValue !== this.editor.getValue()) {
|
|
||||||
this.editor.setValue(newValue)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
language(val) {
|
|
||||||
this.destroyEditor()
|
|
||||||
this.initEditor()
|
|
||||||
},
|
|
||||||
height(newValue) {
|
|
||||||
this.editor.height(newValue)
|
|
||||||
},
|
|
||||||
mode(newValue) {
|
|
||||||
this.editor.changeMode(newValue)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initEditor()
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.destroyEditor()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initEditor() {
|
|
||||||
this.editor = new Editor({
|
|
||||||
el: document.getElementById(this.id),
|
|
||||||
...this.editorOptions
|
|
||||||
})
|
|
||||||
if (this.value) {
|
|
||||||
this.editor.setValue(this.value)
|
|
||||||
}
|
|
||||||
this.editor.on('change', () => {
|
|
||||||
this.$emit('input', this.editor.getValue())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyEditor() {
|
|
||||||
if (!this.editor) return
|
|
||||||
this.editor.off('change')
|
|
||||||
this.editor.remove()
|
|
||||||
},
|
|
||||||
setValue(value) {
|
|
||||||
this.editor.setValue(value)
|
|
||||||
},
|
|
||||||
getValue() {
|
|
||||||
return this.editor.getValue()
|
|
||||||
},
|
|
||||||
setHtml(value) {
|
|
||||||
this.editor.setHtml(value)
|
|
||||||
},
|
|
||||||
getHtml() {
|
|
||||||
return this.editor.getHtml()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,101 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
|
||||||
<el-pagination
|
|
||||||
:background="background"
|
|
||||||
:current-page.sync="currentPage"
|
|
||||||
:page-size.sync="pageSize"
|
|
||||||
:layout="layout"
|
|
||||||
:page-sizes="pageSizes"
|
|
||||||
:total="total"
|
|
||||||
v-bind="$attrs"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { scrollTo } from '@/utils/scroll-to'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Pagination',
|
|
||||||
props: {
|
|
||||||
total: {
|
|
||||||
required: true,
|
|
||||||
type: Number
|
|
||||||
},
|
|
||||||
page: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
limit: {
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
pageSizes: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return [10, 20, 30, 50]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
type: String,
|
|
||||||
default: 'total, sizes, prev, pager, next, jumper'
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
autoScroll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
hidden: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
currentPage: {
|
|
||||||
get() {
|
|
||||||
return this.page
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$emit('update:page', val)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pageSize: {
|
|
||||||
get() {
|
|
||||||
return this.limit
|
|
||||||
},
|
|
||||||
set(val) {
|
|
||||||
this.$emit('update:limit', val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleSizeChange(val) {
|
|
||||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
|
||||||
if (this.autoScroll) {
|
|
||||||
scrollTo(0, 800)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleCurrentChange(val) {
|
|
||||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
|
||||||
if (this.autoScroll) {
|
|
||||||
scrollTo(0, 800)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.pagination-container {
|
|
||||||
background: #fff;
|
|
||||||
padding: 32px 16px;
|
|
||||||
}
|
|
||||||
.pagination-container.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,142 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
|
|
||||||
<div class="pan-info">
|
|
||||||
<div class="pan-info-roles-container">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- eslint-disable-next-line -->
|
|
||||||
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'PanThumb',
|
|
||||||
props: {
|
|
||||||
image: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
zIndex: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: String,
|
|
||||||
default: '150px'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '150px'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.pan-item {
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
cursor: default;
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info-roles-container {
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-thumb {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-position: center center;
|
|
||||||
background-size: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: absolute;
|
|
||||||
transform-origin: 95% 40%;
|
|
||||||
transition: all 0.3s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .pan-thumb:after {
|
|
||||||
content: '';
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 50%;
|
|
||||||
top: 40%;
|
|
||||||
left: 95%;
|
|
||||||
margin: -4px 0 0 -4px;
|
|
||||||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
|
|
||||||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
|
|
||||||
} */
|
|
||||||
|
|
||||||
.pan-info {
|
|
||||||
position: absolute;
|
|
||||||
width: inherit;
|
|
||||||
height: inherit;
|
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info h3 {
|
|
||||||
color: #fff;
|
|
||||||
text-transform: uppercase;
|
|
||||||
position: relative;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
font-size: 18px;
|
|
||||||
margin: 0 60px;
|
|
||||||
padding: 22px 0 0 0;
|
|
||||||
height: 85px;
|
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
|
||||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p {
|
|
||||||
color: #fff;
|
|
||||||
padding: 10px 5px;
|
|
||||||
font-style: italic;
|
|
||||||
margin: 0 30px;
|
|
||||||
font-size: 12px;
|
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p a {
|
|
||||||
display: block;
|
|
||||||
color: #333;
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #fff;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 9px;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
padding-top: 24px;
|
|
||||||
margin: 7px auto 0;
|
|
||||||
font-family: 'Open Sans', Arial, sans-serif;
|
|
||||||
opacity: 0;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-info p a:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-item:hover .pan-thumb {
|
|
||||||
transform: rotate(-110deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-item:hover .pan-info p a {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0px) rotate(0deg);
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,70 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="powershell-editor">
|
|
||||||
<textarea ref="textarea" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
import 'codemirror/addon/lint/lint.css'
|
|
||||||
import 'codemirror/lib/codemirror.css'
|
|
||||||
import 'codemirror/theme/rubyblue.css'
|
|
||||||
import 'codemirror/mode/javascript/javascript'
|
|
||||||
import 'codemirror/addon/lint/lint'
|
|
||||||
require('codemirror/mode/powershell/powershell.js')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PowershellEditor',
|
|
||||||
props: ['value'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
powershellEditor: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(value) {
|
|
||||||
const editorValue = this.powershellEditor.getValue()
|
|
||||||
if (value !== editorValue) {
|
|
||||||
this.powershellEditor.setValue(this.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.powershellEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: 'powershell',
|
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
|
||||||
theme: 'rubyblue',
|
|
||||||
lint: true
|
|
||||||
})
|
|
||||||
|
|
||||||
this.powershellEditor.setValue(this.value ? this.value : '')
|
|
||||||
this.powershellEditor.on('change', cm => {
|
|
||||||
this.$emit('changed', cm.getValue())
|
|
||||||
this.$emit('input', cm.getValue())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getValue() {
|
|
||||||
return this.powershellEditor.getValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.powershell-editor{
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.powershell-editor >>> .CodeMirror {
|
|
||||||
height: auto;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.powershell-editor >>> .CodeMirror-scroll{
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.powershell-editor >>> .cm-s-rubyblue span.cm-string {
|
|
||||||
color: #F08047;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,70 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="python-editor">
|
|
||||||
<textarea ref="textarea" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
import 'codemirror/addon/lint/lint.css'
|
|
||||||
import 'codemirror/lib/codemirror.css'
|
|
||||||
import 'codemirror/theme/rubyblue.css'
|
|
||||||
import 'codemirror/mode/javascript/javascript'
|
|
||||||
import 'codemirror/addon/lint/lint'
|
|
||||||
require('codemirror/mode/python/python.js')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PythonEditor',
|
|
||||||
props: ['value'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pythonEditor: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(value) {
|
|
||||||
const editorValue = this.pythonEditor.getValue()
|
|
||||||
if (value !== editorValue) {
|
|
||||||
this.pythonEditor.setValue(this.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.pythonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: 'text/x-python',
|
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
|
||||||
theme: 'rubyblue',
|
|
||||||
lint: true
|
|
||||||
})
|
|
||||||
|
|
||||||
this.pythonEditor.setValue(this.value ? this.value : '')
|
|
||||||
this.pythonEditor.on('change', cm => {
|
|
||||||
this.$emit('changed', cm.getValue())
|
|
||||||
this.$emit('input', cm.getValue())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getValue() {
|
|
||||||
return this.pythonEditor.getValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.python-editor{
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.python-editor >>> .CodeMirror {
|
|
||||||
height: auto;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.python-editor >>> .CodeMirror-scroll{
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.python-editor >>> .cm-s-rubyblue span.cm-string {
|
|
||||||
color: #F08047;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,145 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
|
||||||
<div class="rightPanel-background" />
|
|
||||||
<div class="rightPanel" style="display: none">
|
|
||||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
|
||||||
<i :class="show?'el-icon-close':'el-icon-setting'" />
|
|
||||||
</div>
|
|
||||||
<div class="rightPanel-items">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { addClass, removeClass } from '@/utils'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'RightPanel',
|
|
||||||
props: {
|
|
||||||
clickNotClose: {
|
|
||||||
default: false,
|
|
||||||
type: Boolean
|
|
||||||
},
|
|
||||||
buttonTop: {
|
|
||||||
default: 250,
|
|
||||||
type: Number
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
theme() {
|
|
||||||
return this.$store.state.settings.theme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
show(value) {
|
|
||||||
if (value && !this.clickNotClose) {
|
|
||||||
this.addEventClick()
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
addClass(document.body, 'showRightPanel')
|
|
||||||
} else {
|
|
||||||
removeClass(document.body, 'showRightPanel')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.insertToBody()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
const elx = this.$refs.rightPanel
|
|
||||||
elx.remove()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
addEventClick() {
|
|
||||||
window.addEventListener('click', this.closeSidebar)
|
|
||||||
},
|
|
||||||
closeSidebar(evt) {
|
|
||||||
const parent = evt.target.closest('.rightPanel')
|
|
||||||
if (!parent) {
|
|
||||||
this.show = false
|
|
||||||
window.removeEventListener('click', this.closeSidebar)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
insertToBody() {
|
|
||||||
const elx = this.$refs.rightPanel
|
|
||||||
const body = document.querySelector('body')
|
|
||||||
body.insertBefore(elx, body.firstChild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.showRightPanel {
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
width: calc(100% - 15px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.rightPanel-background {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
|
||||||
background: rgba(0, 0, 0, .2);
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPanel {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 260px;
|
|
||||||
height: 100vh;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
|
||||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
|
||||||
transform: translate(100%);
|
|
||||||
background: #fff;
|
|
||||||
z-index: 40000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show {
|
|
||||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
|
||||||
|
|
||||||
.rightPanel-background {
|
|
||||||
z-index: 20000;
|
|
||||||
opacity: 1;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightPanel {
|
|
||||||
transform: translate(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.handle-button {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
position: absolute;
|
|
||||||
left: -48px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 24px;
|
|
||||||
border-radius: 6px 0 0 6px !important;
|
|
||||||
z-index: 0;
|
|
||||||
pointer-events: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #fff;
|
|
||||||
line-height: 48px;
|
|
||||||
i {
|
|
||||||
font-size: 24px;
|
|
||||||
line-height: 48px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,60 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import screenfull from 'screenfull'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Screenfull',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isFullscreen: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.init()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.destroy()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
click() {
|
|
||||||
if (!screenfull.enabled) {
|
|
||||||
this.$message({
|
|
||||||
message: 'you browser can not work',
|
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
screenfull.toggle()
|
|
||||||
},
|
|
||||||
change() {
|
|
||||||
this.isFullscreen = screenfull.isFullscreen
|
|
||||||
},
|
|
||||||
init() {
|
|
||||||
if (screenfull.enabled) {
|
|
||||||
screenfull.on('change', this.change)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
if (screenfull.enabled) {
|
|
||||||
screenfull.off('change', this.change)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.screenfull-svg {
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
fill: #5a5e66;;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
vertical-align: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,100 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :class="{active:isActive}" class="share-dropdown-menu">
|
|
||||||
<div class="share-dropdown-menu-wrapper">
|
|
||||||
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</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>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
items: {
|
|
||||||
type: Array,
|
|
||||||
default: function() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: 'vue'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isActive: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
clickTitle() {
|
|
||||||
this.isActive = !this.isActive
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" >
|
|
||||||
$n: 9; //和items.length 相同
|
|
||||||
$t: .1s;
|
|
||||||
.share-dropdown-menu {
|
|
||||||
width: 250px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
&-title {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
height: 60px;
|
|
||||||
line-height: 60px;
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
z-index: 2;
|
|
||||||
transform: translate3d(0,0,0);
|
|
||||||
}
|
|
||||||
&-wrapper {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
&-item {
|
|
||||||
text-align: center;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
background: #e0e0e0;
|
|
||||||
line-height: 60px;
|
|
||||||
height: 60px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
opacity: 1;
|
|
||||||
transition: transform 0.28s ease;
|
|
||||||
&:hover {
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
@for $i from 1 through $n {
|
|
||||||
&:nth-of-type(#{$i}) {
|
|
||||||
z-index: -1;
|
|
||||||
transition-delay: $i*$t;
|
|
||||||
transform: translate3d(0, -60px, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.active {
|
|
||||||
.share-dropdown-menu-wrapper {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.share-dropdown-menu-item {
|
|
||||||
@for $i from 1 through $n {
|
|
||||||
&:nth-of-type(#{$i}) {
|
|
||||||
transition-delay: ($n - $i)*$t;
|
|
||||||
transform: translate3d(0, ($i - 1)*60px, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,70 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="shell-editor">
|
|
||||||
<textarea ref="textarea" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import CodeMirror from 'codemirror'
|
|
||||||
import 'codemirror/addon/lint/lint.css'
|
|
||||||
import 'codemirror/lib/codemirror.css'
|
|
||||||
import 'codemirror/theme/rubyblue.css'
|
|
||||||
import 'codemirror/mode/javascript/javascript'
|
|
||||||
import 'codemirror/addon/lint/lint'
|
|
||||||
require('codemirror/mode/shell/shell.js')
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ShellEditor',
|
|
||||||
props: ['value'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
shellEditor: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value(value) {
|
|
||||||
const editorValue = this.shellEditor.getValue()
|
|
||||||
if (value !== editorValue) {
|
|
||||||
this.shellEditor.setValue(this.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.shellEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: 'text/x-sh',
|
|
||||||
gutters: ['CodeMirror-lint-markers'],
|
|
||||||
theme: 'rubyblue',
|
|
||||||
lint: true
|
|
||||||
})
|
|
||||||
|
|
||||||
this.shellEditor.setValue(this.value ? this.value : '')
|
|
||||||
this.shellEditor.on('change', cm => {
|
|
||||||
this.$emit('changed', cm.getValue())
|
|
||||||
this.$emit('input', cm.getValue())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getValue() {
|
|
||||||
return this.shellEditor.getValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.shell-editor{
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.shell-editor >>> .CodeMirror {
|
|
||||||
height: auto;
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.shell-editor >>> .CodeMirror-scroll{
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.shell-editor >>> .cm-s-rubyblue span.cm-string {
|
|
||||||
color: #F08047;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,57 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dropdown trigger="click" @command="handleSetSize">
|
|
||||||
<div>
|
|
||||||
<svg-icon class-name="size-icon" icon-class="size" />
|
|
||||||
</div>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
|
|
||||||
{{
|
|
||||||
item.label }}
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
sizeOptions: [
|
|
||||||
{ label: 'Default', value: 'default' },
|
|
||||||
{ label: 'Medium', value: 'medium' },
|
|
||||||
{ label: 'Small', value: 'small' },
|
|
||||||
{ label: 'Mini', value: 'mini' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
size() {
|
|
||||||
return this.$store.getters.size
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleSetSize(size) {
|
|
||||||
this.$ELEMENT.size = size
|
|
||||||
this.$store.dispatch('app/setSize', size)
|
|
||||||
this.refreshView()
|
|
||||||
this.$message({
|
|
||||||
message: 'Switch Size Success',
|
|
||||||
type: 'success'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
refreshView() {
|
|
||||||
// In order to make the cached page re-rendered
|
|
||||||
this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
|
|
||||||
|
|
||||||
const { fullPath } = this.$route
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$router.replace({
|
|
||||||
path: '/redirect' + fullPath
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,91 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{height:height+'px',zIndex:zIndex}">
|
|
||||||
<div
|
|
||||||
:class="className"
|
|
||||||
:style="{top:(isSticky ? stickyTop +'px' : ''),zIndex:zIndex,position:position,width:width,height:height+'px'}"
|
|
||||||
>
|
|
||||||
<slot>
|
|
||||||
<div>sticky</div>
|
|
||||||
</slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'Sticky',
|
|
||||||
props: {
|
|
||||||
stickyTop: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
zIndex: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
active: false,
|
|
||||||
position: '',
|
|
||||||
width: undefined,
|
|
||||||
height: undefined,
|
|
||||||
isSticky: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.height = this.$el.getBoundingClientRect().height
|
|
||||||
window.addEventListener('scroll', this.handleScroll)
|
|
||||||
window.addEventListener('resize', this.handleResize)
|
|
||||||
},
|
|
||||||
activated() {
|
|
||||||
this.handleScroll()
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
window.removeEventListener('scroll', this.handleScroll)
|
|
||||||
window.removeEventListener('resize', this.handleResize)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
sticky() {
|
|
||||||
if (this.active) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.position = 'fixed'
|
|
||||||
this.active = true
|
|
||||||
this.width = this.width + 'px'
|
|
||||||
this.isSticky = true
|
|
||||||
},
|
|
||||||
handleReset() {
|
|
||||||
if (!this.active) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.reset()
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
this.position = ''
|
|
||||||
this.width = 'auto'
|
|
||||||
this.active = false
|
|
||||||
this.isSticky = false
|
|
||||||
},
|
|
||||||
handleScroll() {
|
|
||||||
const width = this.$el.getBoundingClientRect().width
|
|
||||||
this.width = width || 'auto'
|
|
||||||
const offsetTop = this.$el.getBoundingClientRect().top
|
|
||||||
if (offsetTop < this.stickyTop) {
|
|
||||||
this.sticky()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.handleReset()
|
|
||||||
},
|
|
||||||
handleResize() {
|
|
||||||
if (this.isSticky) {
|
|
||||||
this.width = this.$el.getBoundingClientRect().width + 'px'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -1,62 +0,0 @@
|
|||||||
<template>
|
|
||||||
<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">
|
|
||||||
<use :xlink:href="iconName" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
|
||||||
import { isExternal } from '@/utils/validate'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SvgIcon',
|
|
||||||
props: {
|
|
||||||
iconClass: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isExternal() {
|
|
||||||
return isExternal(this.iconClass)
|
|
||||||
},
|
|
||||||
iconName() {
|
|
||||||
return `#icon-${this.iconClass}`
|
|
||||||
},
|
|
||||||
svgClass() {
|
|
||||||
if (this.className) {
|
|
||||||
return 'svg-icon ' + this.className
|
|
||||||
} else {
|
|
||||||
return 'svg-icon'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
styleExternalIcon() {
|
|
||||||
return {
|
|
||||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
|
||||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.svg-icon {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
vertical-align: -0.15em;
|
|
||||||
fill: currentColor;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svg-external-icon {
|
|
||||||
background-color: currentColor;
|
|
||||||
mask-size: cover!important;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,113 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a :class="className" class="link--mallki" href="#">
|
|
||||||
{{ text }}
|
|
||||||
<span :data-letters="text" />
|
|
||||||
<span :data-letters="text" />
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
type: String,
|
|
||||||
default: 'vue-element-admin'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Mallki */
|
|
||||||
|
|
||||||
.link--mallki {
|
|
||||||
font-weight: 800;
|
|
||||||
color: #4dd9d5;
|
|
||||||
font-family: 'Dosis', sans-serif;
|
|
||||||
-webkit-transition: color 0.5s 0.25s;
|
|
||||||
transition: color 0.5s 0.25s;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
outline: none;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki:hover {
|
|
||||||
-webkit-transition: none;
|
|
||||||
transition: none;
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki::before {
|
|
||||||
content: '';
|
|
||||||
width: 100%;
|
|
||||||
height: 6px;
|
|
||||||
margin: -3px 0 0 0;
|
|
||||||
background: #3888fa;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 50%;
|
|
||||||
-webkit-transform: translate3d(-100%, 0, 0);
|
|
||||||
transform: translate3d(-100%, 0, 0);
|
|
||||||
-webkit-transition: -webkit-transform 0.4s;
|
|
||||||
transition: transform 0.4s;
|
|
||||||
-webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
|
|
||||||
transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki:hover::before {
|
|
||||||
-webkit-transform: translate3d(100%, 0, 0);
|
|
||||||
transform: translate3d(100%, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki span {
|
|
||||||
position: absolute;
|
|
||||||
height: 50%;
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki span::before {
|
|
||||||
content: attr(data-letters);
|
|
||||||
color: red;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
color: #3888fa;
|
|
||||||
-webkit-transition: -webkit-transform 0.5s;
|
|
||||||
transition: transform 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki span:nth-child(2) {
|
|
||||||
top: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki span:first-child::before {
|
|
||||||
top: 0;
|
|
||||||
-webkit-transform: translate3d(0, 100%, 0);
|
|
||||||
transform: translate3d(0, 100%, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki span:nth-child(2)::before {
|
|
||||||
bottom: 0;
|
|
||||||
-webkit-transform: translate3d(0, -100%, 0);
|
|
||||||
transform: translate3d(0, -100%, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link--mallki:hover span::before {
|
|
||||||
-webkit-transition-delay: 0.3s;
|
|
||||||
transition-delay: 0.3s;
|
|
||||||
-webkit-transform: translate3d(0, 0, 0);
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
-webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
|
||||||
transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,175 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-color-picker
|
|
||||||
v-model="theme"
|
|
||||||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
|
|
||||||
class="theme-picker"
|
|
||||||
popper-class="theme-picker-dropdown"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
|
||||||
const ORIGINAL_THEME = '#409EFF' // default color
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chalk: '', // content of theme-chalk css
|
|
||||||
theme: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
defaultTheme() {
|
|
||||||
return this.$store.state.settings.theme
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
defaultTheme: {
|
|
||||||
handler: function(val, oldVal) {
|
|
||||||
this.theme = val
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
},
|
|
||||||
async theme(val) {
|
|
||||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
|
||||||
if (typeof val !== 'string') return
|
|
||||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
|
||||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
|
||||||
console.log(themeCluster, originalCluster)
|
|
||||||
|
|
||||||
const $message = this.$message({
|
|
||||||
message: ' Compiling the theme',
|
|
||||||
customClass: 'theme-message',
|
|
||||||
type: 'success',
|
|
||||||
duration: 0,
|
|
||||||
iconClass: 'el-icon-loading'
|
|
||||||
})
|
|
||||||
|
|
||||||
const getHandler = (variable, id) => {
|
|
||||||
return () => {
|
|
||||||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
|
|
||||||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
|
|
||||||
|
|
||||||
let styleTag = document.getElementById(id)
|
|
||||||
if (!styleTag) {
|
|
||||||
styleTag = document.createElement('style')
|
|
||||||
styleTag.setAttribute('id', id)
|
|
||||||
document.head.appendChild(styleTag)
|
|
||||||
}
|
|
||||||
styleTag.innerText = newStyle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.chalk) {
|
|
||||||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
|
|
||||||
await this.getCSSString(url, 'chalk')
|
|
||||||
}
|
|
||||||
|
|
||||||
const chalkHandler = getHandler('chalk', 'chalk-style')
|
|
||||||
|
|
||||||
chalkHandler()
|
|
||||||
|
|
||||||
const styles = [].slice.call(document.querySelectorAll('style'))
|
|
||||||
.filter(style => {
|
|
||||||
const text = style.innerText
|
|
||||||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
|
|
||||||
})
|
|
||||||
styles.forEach(style => {
|
|
||||||
const { innerText } = style
|
|
||||||
if (typeof innerText !== 'string') return
|
|
||||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$emit('change', val)
|
|
||||||
|
|
||||||
$message.close()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
updateStyle(style, oldCluster, newCluster) {
|
|
||||||
let newStyle = style
|
|
||||||
oldCluster.forEach((color, index) => {
|
|
||||||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
|
|
||||||
})
|
|
||||||
return newStyle
|
|
||||||
},
|
|
||||||
|
|
||||||
getCSSString(url, variable) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const xhr = new XMLHttpRequest()
|
|
||||||
xhr.onreadystatechange = () => {
|
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
|
||||||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xhr.open('GET', url)
|
|
||||||
xhr.send()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
getThemeCluster(theme) {
|
|
||||||
const tintColor = (color, tint) => {
|
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
|
||||||
|
|
||||||
if (tint === 0) { // when primary color is in its rgb space
|
|
||||||
return [red, green, blue].join(',')
|
|
||||||
} else {
|
|
||||||
red += Math.round(tint * (255 - red))
|
|
||||||
green += Math.round(tint * (255 - green))
|
|
||||||
blue += Math.round(tint * (255 - blue))
|
|
||||||
|
|
||||||
red = red.toString(16)
|
|
||||||
green = green.toString(16)
|
|
||||||
blue = blue.toString(16)
|
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shadeColor = (color, shade) => {
|
|
||||||
let red = parseInt(color.slice(0, 2), 16)
|
|
||||||
let green = parseInt(color.slice(2, 4), 16)
|
|
||||||
let blue = parseInt(color.slice(4, 6), 16)
|
|
||||||
|
|
||||||
red = Math.round((1 - shade) * red)
|
|
||||||
green = Math.round((1 - shade) * green)
|
|
||||||
blue = Math.round((1 - shade) * blue)
|
|
||||||
|
|
||||||
red = red.toString(16)
|
|
||||||
green = green.toString(16)
|
|
||||||
blue = blue.toString(16)
|
|
||||||
|
|
||||||
return `#${red}${green}${blue}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const clusters = [theme]
|
|
||||||
for (let i = 0; i <= 9; i++) {
|
|
||||||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
|
|
||||||
}
|
|
||||||
clusters.push(shadeColor(theme, 0.1))
|
|
||||||
return clusters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.theme-message,
|
|
||||||
.theme-picker-dropdown {
|
|
||||||
z-index: 99999 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-picker .el-color-picker__trigger {
|
|
||||||
height: 26px !important;
|
|
||||||
width: 26px !important;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-picker-dropdown .el-color-dropdown__link-btn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,111 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="upload-container">
|
|
||||||
<el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
|
|
||||||
upload
|
|
||||||
</el-button>
|
|
||||||
<el-dialog :visible.sync="dialogVisible">
|
|
||||||
<el-upload
|
|
||||||
:multiple="true"
|
|
||||||
:file-list="fileList"
|
|
||||||
:show-file-list="true"
|
|
||||||
:on-remove="handleRemove"
|
|
||||||
:on-success="handleSuccess"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
class="editor-slide-upload"
|
|
||||||
action="https://httpbin.org/post"
|
|
||||||
list-type="picture-card"
|
|
||||||
>
|
|
||||||
<el-button size="small" type="primary">
|
|
||||||
Click upload
|
|
||||||
</el-button>
|
|
||||||
</el-upload>
|
|
||||||
<el-button @click="dialogVisible = false">
|
|
||||||
Cancel
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" @click="handleSubmit">
|
|
||||||
Confirm
|
|
||||||
</el-button>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// import { getToken } from 'api/qiniu'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'EditorSlideUpload',
|
|
||||||
props: {
|
|
||||||
color: {
|
|
||||||
type: String,
|
|
||||||
default: '#1890ff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible: false,
|
|
||||||
listObj: {},
|
|
||||||
fileList: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
checkAllSuccess() {
|
|
||||||
return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
|
|
||||||
},
|
|
||||||
handleSubmit() {
|
|
||||||
const arr = Object.keys(this.listObj).map(v => this.listObj[v])
|
|
||||||
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!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$emit('successCBK', arr)
|
|
||||||
this.listObj = {}
|
|
||||||
this.fileList = []
|
|
||||||
this.dialogVisible = false
|
|
||||||
},
|
|
||||||
handleSuccess(response, file) {
|
|
||||||
const uid = file.uid
|
|
||||||
const objKeyArr = Object.keys(this.listObj)
|
|
||||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
|
||||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
|
||||||
this.listObj[objKeyArr[i]].url = response.files.file
|
|
||||||
this.listObj[objKeyArr[i]].hasSuccess = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleRemove(file) {
|
|
||||||
const uid = file.uid
|
|
||||||
const objKeyArr = Object.keys(this.listObj)
|
|
||||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
|
||||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
|
||||||
delete this.listObj[objKeyArr[i]]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeUpload(file) {
|
|
||||||
const _self = this
|
|
||||||
const _URL = window.URL || window.webkitURL
|
|
||||||
const fileName = file.uid
|
|
||||||
this.listObj[fileName] = {}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const img = new Image()
|
|
||||||
img.src = _URL.createObjectURL(file)
|
|
||||||
img.onload = function() {
|
|
||||||
_self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
|
|
||||||
}
|
|
||||||
resolve(true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.editor-slide-upload {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
/deep/ .el-upload--picture-card {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,59 +0,0 @@
|
|||||||
let callbacks = []
|
|
||||||
|
|
||||||
function loadedTinymce() {
|
|
||||||
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
|
|
||||||
// check is successfully downloaded script
|
|
||||||
return window.tinymce
|
|
||||||
}
|
|
||||||
|
|
||||||
const dynamicLoadScript = (src, callback) => {
|
|
||||||
const existingScript = document.getElementById(src)
|
|
||||||
const cb = callback || function() {}
|
|
||||||
|
|
||||||
if (!existingScript) {
|
|
||||||
const script = document.createElement('script')
|
|
||||||
script.src = src // src url for the third-party library being loaded.
|
|
||||||
script.id = src
|
|
||||||
document.body.appendChild(script)
|
|
||||||
callbacks.push(cb)
|
|
||||||
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
|
|
||||||
onEnd(script)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingScript && cb) {
|
|
||||||
if (loadedTinymce()) {
|
|
||||||
cb(null, existingScript)
|
|
||||||
} else {
|
|
||||||
callbacks.push(cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stdOnEnd(script) {
|
|
||||||
script.onload = function() {
|
|
||||||
// this.onload = null here is necessary
|
|
||||||
// because even IE9 works not like others
|
|
||||||
this.onerror = this.onload = null
|
|
||||||
for (const cb of callbacks) {
|
|
||||||
cb(null, script)
|
|
||||||
}
|
|
||||||
callbacks = null
|
|
||||||
}
|
|
||||||
script.onerror = function() {
|
|
||||||
this.onerror = this.onload = null
|
|
||||||
cb(new Error('Failed to load ' + src), script)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ieOnEnd(script) {
|
|
||||||
script.onreadystatechange = function() {
|
|
||||||
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
|
|
||||||
this.onreadystatechange = null
|
|
||||||
for (const cb of callbacks) {
|
|
||||||
cb(null, script) // there is no way to catch loading errors in IE8
|
|
||||||
}
|
|
||||||
callbacks = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default dynamicLoadScript
|
|
@ -1,7 +0,0 @@
|
|||||||
// Any plugins you want to use has to be imported
|
|
||||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
|
||||||
// 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']
|
|
||||||
|
|
||||||
export default plugins
|
|
@ -1,6 +0,0 @@
|
|||||||
// Here is a list of the toolbar
|
|
||||||
// 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']
|
|
||||||
|
|
||||||
export default toolbar
|
|
@ -1,130 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="singleImageUpload2 upload-container">
|
|
||||||
<el-upload
|
|
||||||
:data="dataObj"
|
|
||||||
:multiple="false"
|
|
||||||
:show-file-list="false"
|
|
||||||
:on-success="handleImageSuccess"
|
|
||||||
class="image-uploader"
|
|
||||||
drag
|
|
||||||
action="https://httpbin.org/post"
|
|
||||||
>
|
|
||||||
<i class="el-icon-upload" />
|
|
||||||
<div class="el-upload__text">
|
|
||||||
Drag或<em>点击上传</em>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
|
||||||
<div v-show="imageUrl.length>0" class="image-preview">
|
|
||||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
|
||||||
<img :src="imageUrl">
|
|
||||||
<div class="image-preview-action">
|
|
||||||
<i class="el-icon-delete" @click="rmImage" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getToken } from '@/api/qiniu'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SingleImageUpload2',
|
|
||||||
props: {
|
|
||||||
value: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tempUrl: '',
|
|
||||||
dataObj: { token: '', key: '' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
imageUrl() {
|
|
||||||
return this.value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
rmImage() {
|
|
||||||
this.emitInput('')
|
|
||||||
},
|
|
||||||
emitInput(val) {
|
|
||||||
this.$emit('input', val)
|
|
||||||
},
|
|
||||||
handleImageSuccess() {
|
|
||||||
this.emitInput(this.tempUrl)
|
|
||||||
},
|
|
||||||
beforeUpload() {
|
|
||||||
const _self = this
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
getToken().then(response => {
|
|
||||||
const key = response.data.qiniu_key
|
|
||||||
const token = response.data.qiniu_token
|
|
||||||
_self._data.dataObj.token = token
|
|
||||||
_self._data.dataObj.key = key
|
|
||||||
this.tempUrl = response.data.qiniu_url
|
|
||||||
resolve(true)
|
|
||||||
}).catch(() => {
|
|
||||||
reject(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.upload-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
.image-uploader {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.image-preview {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
border: 1px dashed #d9d9d9;
|
|
||||||
.image-preview-wrapper {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.image-preview-action {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
cursor: default;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
opacity: 0;
|
|
||||||
font-size: 20px;
|
|
||||||
background-color: rgba(0, 0, 0, .5);
|
|
||||||
transition: opacity .3s;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 200px;
|
|
||||||
.el-icon-delete {
|
|
||||||
font-size: 36px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.image-preview-action {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,138 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<input 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
|
|
||||||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">
|
|
||||||
Browse
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import XLSX from 'xlsx'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
beforeUpload: Function, // eslint-disable-line
|
|
||||||
onSuccess: Function// eslint-disable-line
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
excelData: {
|
|
||||||
header: null,
|
|
||||||
results: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
generateData({ header, results }) {
|
|
||||||
this.excelData.header = header
|
|
||||||
this.excelData.results = results
|
|
||||||
this.onSuccess && this.onSuccess(this.excelData)
|
|
||||||
},
|
|
||||||
handleDrop(e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
e.preventDefault()
|
|
||||||
if (this.loading) return
|
|
||||||
const files = e.dataTransfer.files
|
|
||||||
if (files.length !== 1) {
|
|
||||||
this.$message.error('Only support uploading one file!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const rawFile = files[0] // only use files[0]
|
|
||||||
|
|
||||||
if (!this.isExcel(rawFile)) {
|
|
||||||
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
this.upload(rawFile)
|
|
||||||
e.stopPropagation()
|
|
||||||
e.preventDefault()
|
|
||||||
},
|
|
||||||
handleDragover(e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
e.preventDefault()
|
|
||||||
e.dataTransfer.dropEffect = 'copy'
|
|
||||||
},
|
|
||||||
handleUpload() {
|
|
||||||
this.$refs['excel-upload-input'].click()
|
|
||||||
},
|
|
||||||
handleClick(e) {
|
|
||||||
const files = e.target.files
|
|
||||||
const rawFile = files[0] // only use files[0]
|
|
||||||
if (!rawFile) return
|
|
||||||
this.upload(rawFile)
|
|
||||||
},
|
|
||||||
upload(rawFile) {
|
|
||||||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel
|
|
||||||
|
|
||||||
if (!this.beforeUpload) {
|
|
||||||
this.readerData(rawFile)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const before = this.beforeUpload(rawFile)
|
|
||||||
if (before) {
|
|
||||||
this.readerData(rawFile)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readerData(rawFile) {
|
|
||||||
this.loading = true
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = e => {
|
|
||||||
const data = e.target.result
|
|
||||||
const workbook = XLSX.read(data, { type: 'array' })
|
|
||||||
const firstSheetName = workbook.SheetNames[0]
|
|
||||||
const worksheet = workbook.Sheets[firstSheetName]
|
|
||||||
const header = this.getHeaderRow(worksheet)
|
|
||||||
const results = XLSX.utils.sheet_to_json(worksheet)
|
|
||||||
this.generateData({ header, results })
|
|
||||||
this.loading = false
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
reader.readAsArrayBuffer(rawFile)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getHeaderRow(sheet) {
|
|
||||||
const headers = []
|
|
||||||
const range = XLSX.utils.decode_range(sheet['!ref'])
|
|
||||||
let C
|
|
||||||
const R = range.s.r
|
|
||||||
/* start in the first row */
|
|
||||||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
|
|
||||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
|
|
||||||
/* find the cell in the first row */
|
|
||||||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
|
|
||||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
|
|
||||||
headers.push(hdr)
|
|
||||||
}
|
|
||||||
return headers
|
|
||||||
},
|
|
||||||
isExcel(file) {
|
|
||||||
return /\.(xlsx|xls|csv)$/.test(file.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.excel-upload-input{
|
|
||||||
display: none;
|
|
||||||
z-index: -9999;
|
|
||||||
}
|
|
||||||
.drop{
|
|
||||||
border: 2px dashed #bbb;
|
|
||||||
width: 600px;
|
|
||||||
height: 160px;
|
|
||||||
line-height: 160px;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-size: 24px;
|
|
||||||
border-radius: 5px;
|
|
||||||
text-align: center;
|
|
||||||
color: #bbb;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,49 +0,0 @@
|
|||||||
// Inspired by https://github.com/Inndy/vue-clipboard2
|
|
||||||
const Clipboard = require('clipboard')
|
|
||||||
if (!Clipboard) {
|
|
||||||
throw new Error('you should npm install `clipboard` --save at first ')
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el, binding) {
|
|
||||||
if (binding.arg === 'success') {
|
|
||||||
el._v_clipboard_success = binding.value
|
|
||||||
} else if (binding.arg === 'error') {
|
|
||||||
el._v_clipboard_error = binding.value
|
|
||||||
} else {
|
|
||||||
const clipboard = new Clipboard(el, {
|
|
||||||
text() { return binding.value },
|
|
||||||
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
|
||||||
})
|
|
||||||
clipboard.on('success', e => {
|
|
||||||
const callback = el._v_clipboard_success
|
|
||||||
callback && callback(e) // eslint-disable-line
|
|
||||||
})
|
|
||||||
clipboard.on('error', e => {
|
|
||||||
const callback = el._v_clipboard_error
|
|
||||||
callback && callback(e) // eslint-disable-line
|
|
||||||
})
|
|
||||||
el._v_clipboard = clipboard
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update(el, binding) {
|
|
||||||
if (binding.arg === 'success') {
|
|
||||||
el._v_clipboard_success = binding.value
|
|
||||||
} else if (binding.arg === 'error') {
|
|
||||||
el._v_clipboard_error = binding.value
|
|
||||||
} else {
|
|
||||||
el._v_clipboard.text = function() { return binding.value }
|
|
||||||
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
unbind(el, binding) {
|
|
||||||
if (binding.arg === 'success') {
|
|
||||||
delete el._v_clipboard_success
|
|
||||||
} else if (binding.arg === 'error') {
|
|
||||||
delete el._v_clipboard_error
|
|
||||||
} else {
|
|
||||||
el._v_clipboard.destroy()
|
|
||||||
delete el._v_clipboard
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import Clipboard from './clipboard'
|
|
||||||
|
|
||||||
const install = function(Vue) {
|
|
||||||
Vue.directive('Clipboard', Clipboard)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window.clipboard = Clipboard
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
Clipboard.install = install
|
|
||||||
export default Clipboard
|
|
@ -1,77 +0,0 @@
|
|||||||
export default {
|
|
||||||
bind(el, binding, vnode) {
|
|
||||||
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
|
||||||
const dragDom = el.querySelector('.el-dialog')
|
|
||||||
dialogHeaderEl.style.cssText += ';cursor:move;'
|
|
||||||
dragDom.style.cssText += ';top:0px;'
|
|
||||||
|
|
||||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
|
||||||
const getStyle = (function() {
|
|
||||||
if (window.document.currentStyle) {
|
|
||||||
return (dom, attr) => dom.currentStyle[attr]
|
|
||||||
} else {
|
|
||||||
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
dialogHeaderEl.onmousedown = (e) => {
|
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离
|
|
||||||
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
|
||||||
const disY = e.clientY - dialogHeaderEl.offsetTop
|
|
||||||
|
|
||||||
const dragDomWidth = dragDom.offsetWidth
|
|
||||||
const dragDomHeight = dragDom.offsetHeight
|
|
||||||
|
|
||||||
const screenWidth = document.body.clientWidth
|
|
||||||
const screenHeight = document.body.clientHeight
|
|
||||||
|
|
||||||
const minDragDomLeft = dragDom.offsetLeft
|
|
||||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
|
|
||||||
|
|
||||||
const minDragDomTop = dragDom.offsetTop
|
|
||||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
|
|
||||||
|
|
||||||
// 获取到的值带px 正则匹配替换
|
|
||||||
let styL = getStyle(dragDom, 'left')
|
|
||||||
let styT = getStyle(dragDom, 'top')
|
|
||||||
|
|
||||||
if (styL.includes('%')) {
|
|
||||||
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
|
||||||
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
|
||||||
} else {
|
|
||||||
styL = +styL.replace(/\px/g, '')
|
|
||||||
styT = +styT.replace(/\px/g, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
document.onmousemove = function(e) {
|
|
||||||
// 通过事件委托,计算移动的距离
|
|
||||||
let left = e.clientX - disX
|
|
||||||
let top = e.clientY - disY
|
|
||||||
|
|
||||||
// 边界处理
|
|
||||||
if (-(left) > minDragDomLeft) {
|
|
||||||
left = -minDragDomLeft
|
|
||||||
} else if (left > maxDragDomLeft) {
|
|
||||||
left = maxDragDomLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-(top) > minDragDomTop) {
|
|
||||||
top = -minDragDomTop
|
|
||||||
} else if (top > maxDragDomTop) {
|
|
||||||
top = maxDragDomTop
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动当前元素
|
|
||||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
|
||||||
|
|
||||||
// emit onDrag event
|
|
||||||
vnode.child.$emit('dragDialog')
|
|
||||||
}
|
|
||||||
|
|
||||||
document.onmouseup = function(e) {
|
|
||||||
document.onmousemove = null
|
|
||||||
document.onmouseup = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import drag from './drag'
|
|
||||||
|
|
||||||
const install = function(Vue) {
|
|
||||||
Vue.directive('el-drag-dialog', drag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window['el-drag-dialog'] = drag
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
drag.install = install
|
|
||||||
export default drag
|
|
@ -1,41 +0,0 @@
|
|||||||
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* How to use
|
|
||||||
* <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
|
|
||||||
* el-table height is must be set
|
|
||||||
* bottomOffset: 30(default) // The height of the table from the bottom of the page.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const doResize = (el, binding, vnode) => {
|
|
||||||
const { componentInstance: $table } = vnode
|
|
||||||
|
|
||||||
const { value } = binding
|
|
||||||
|
|
||||||
if (!$table.height) {
|
|
||||||
throw new Error(`el-$table must set the height. Such as height='100px'`)
|
|
||||||
}
|
|
||||||
const bottomOffset = (value && value.bottomOffset) || 30
|
|
||||||
|
|
||||||
if (!$table) return
|
|
||||||
|
|
||||||
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
|
|
||||||
$table.layout.setHeight(height)
|
|
||||||
$table.doLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el, binding, vnode) {
|
|
||||||
el.resizeListener = () => {
|
|
||||||
doResize(el, binding, vnode)
|
|
||||||
}
|
|
||||||
// parameter 1 is must be "Element" type
|
|
||||||
addResizeListener(window.document.body, el.resizeListener)
|
|
||||||
},
|
|
||||||
inserted(el, binding, vnode) {
|
|
||||||
doResize(el, binding, vnode)
|
|
||||||
},
|
|
||||||
unbind(el) {
|
|
||||||
removeResizeListener(window.document.body, el.resizeListener)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import adaptive from './adaptive'
|
|
||||||
|
|
||||||
const install = function(Vue) {
|
|
||||||
Vue.directive('el-height-adaptive-table', adaptive)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window['el-height-adaptive-table'] = adaptive
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
adaptive.install = install
|
|
||||||
export default adaptive
|
|
@ -1,13 +0,0 @@
|
|||||||
import permission from './permission'
|
|
||||||
|
|
||||||
const install = function(Vue) {
|
|
||||||
Vue.directive('permission', permission)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window['permission'] = permission
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
permission.install = install
|
|
||||||
export default permission
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue