Merge branch 'master' into deploy
This commit is contained in:
commit
caffe6f470
|
@ -1,11 +1,23 @@
|
|||
import Mock from 'mockjs'
|
||||
import mocks from './mocks'
|
||||
import { param2Obj } from '../src/utils'
|
||||
|
||||
const MOCK_API_BASE = '/mock'
|
||||
import user from './user'
|
||||
import role from './role'
|
||||
import article from './article'
|
||||
import search from './remoteSearch'
|
||||
|
||||
const mocks = [
|
||||
...user,
|
||||
...role,
|
||||
...article,
|
||||
...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() {
|
||||
// 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
|
||||
// mock patch
|
||||
// https://github.com/nuysoft/Mock/issues/300
|
||||
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
||||
Mock.XHR.prototype.send = function() {
|
||||
|
@ -42,9 +54,10 @@ export function mockXHR() {
|
|||
}
|
||||
}
|
||||
|
||||
// for mock server
|
||||
const responseFake = (url, type, respond) => {
|
||||
return {
|
||||
url: new RegExp(`${MOCK_API_BASE}${url}`),
|
||||
url: new RegExp(`/mock${url}`),
|
||||
type: type || 'get',
|
||||
response(req, res) {
|
||||
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
const chokidar = require('chokidar')
|
||||
const bodyParser = require('body-parser')
|
||||
const chalk = require('chalk')
|
||||
|
||||
function registerRoutes(app) {
|
||||
const { default: mocks } = require('./index.js')
|
||||
for (const mock of mocks) {
|
||||
app[mock.type](mock.url, mock.response)
|
||||
}
|
||||
return {
|
||||
mockRoutesLength: Object.keys(mocks).length
|
||||
}
|
||||
}
|
||||
|
||||
function unregisterRoutes() {
|
||||
Object.keys(require.cache).forEach(i => {
|
||||
if (i.includes('/mock')) {
|
||||
delete require.cache[require.resolve(i)]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getPath(path) {
|
||||
var match = path.toString()
|
||||
.replace('\\/?', '')
|
||||
.replace('(?=\\/|$)', '$')
|
||||
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
|
||||
return match
|
||||
? match[1].replace(/\\(.)/g, '$1').split('/')
|
||||
: path.toString()
|
||||
}
|
||||
|
||||
function getMockRoutesIndex(app) {
|
||||
for (let index = 0; index <= app._router.stack.length; index++) {
|
||||
const r = app._router.stack[index]
|
||||
if (r.route && r.route.path) {
|
||||
const path = getPath(r.route.path)
|
||||
if (path.includes('mock')) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = app => {
|
||||
// es6 polyfill
|
||||
require('@babel/register')
|
||||
|
||||
// parse app.body
|
||||
// http://expressjs.com/en/4x/api.html#req.body
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}))
|
||||
|
||||
const { mockRoutesLength } = registerRoutes(app)
|
||||
|
||||
// watch files, hot reload mock server
|
||||
chokidar.watch(('./mock'), {
|
||||
ignored: 'mock/mock-server.js',
|
||||
persistent: true,
|
||||
ignoreInitial: true
|
||||
}).on('all', (event, path) => {
|
||||
if (event === 'change' || event === 'add') {
|
||||
// find mock routes stack index
|
||||
const index = getMockRoutesIndex(app)
|
||||
|
||||
// remove mock routes stack
|
||||
app._router.stack.splice(index, mockRoutesLength)
|
||||
|
||||
// clear routes cache
|
||||
unregisterRoutes()
|
||||
|
||||
registerRoutes(app)
|
||||
|
||||
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import user from './user'
|
||||
import role from './role'
|
||||
import article from './article'
|
||||
import search from './remoteSearch'
|
||||
|
||||
export default [
|
||||
...user,
|
||||
...role,
|
||||
...article,
|
||||
...search
|
||||
]
|
||||
|
|
@ -19,7 +19,7 @@ export const constantRoutes = [
|
|||
},
|
||||
{
|
||||
path: '/auth-redirect',
|
||||
component: 'views/login/authredirect',
|
||||
component: 'views/login/authRedirect',
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
"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",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="dndList">
|
||||
<div :style="{width:width1}" class="dndList-list">
|
||||
<h3>{{ list1Title }}</h3>
|
||||
<draggable :list="list1" group="article" class="dragArea">
|
||||
<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 }}
|
||||
|
@ -94,6 +94,11 @@ export default {
|
|||
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', '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</el-button>
|
||||
</el-badge>
|
||||
|
||||
<el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%">
|
||||
<el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%" append-to-body>
|
||||
<el-table :data="errorLogs" border>
|
||||
<el-table-column label="Message">
|
||||
<template slot-scope="{row}">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
: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 }}
|
||||
|
@ -39,6 +40,13 @@ export default {
|
|||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setData(dataTransfer) {
|
||||
// to avoid Firefox bug
|
||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||
dataTransfer.setData('Text', '')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export default {
|
||||
route: {
|
||||
dashboard: 'Dashboard',
|
||||
introduction: 'Introduction',
|
||||
documentation: 'Documentation',
|
||||
guide: 'Guide',
|
||||
permission: 'Permission',
|
||||
|
@ -10,7 +9,6 @@ export default {
|
|||
directivePermission: 'Directive Permission',
|
||||
icons: 'Icons',
|
||||
components: 'Components',
|
||||
componentIndex: 'Introduction',
|
||||
tinymce: 'Tinymce',
|
||||
markdown: 'Markdown',
|
||||
jsonEditor: 'JSON Editor',
|
||||
|
@ -88,10 +86,10 @@ export default {
|
|||
},
|
||||
permission: {
|
||||
addRole: 'New Role',
|
||||
editPermission: 'Edit Permission',
|
||||
editPermission: 'Edit',
|
||||
roles: 'Your roles',
|
||||
switchRoles: 'Switch roles',
|
||||
tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.',
|
||||
tips: 'In some cases, using v-permission will have no effect. For example: Element-UI el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.',
|
||||
delete: 'Delete',
|
||||
confirm: 'Confirm',
|
||||
cancel: 'Cancel'
|
||||
|
@ -102,7 +100,7 @@ export default {
|
|||
},
|
||||
components: {
|
||||
documentation: 'Documentation',
|
||||
tinymceTips: 'Rich text editor is a core part of management system, but at the same time is a place with lots of problems. In the process of selecting rich texts, I also walked a lot of detours. The common rich text editors in the market are basically used, and the finally chose Tinymce. See documentation for more detailed rich text editor comparisons and introductions.',
|
||||
tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.',
|
||||
dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
|
||||
stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
|
||||
backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
|
||||
|
@ -150,7 +148,7 @@ export default {
|
|||
placeholder: 'Please enter the file name (default file)'
|
||||
},
|
||||
pdf: {
|
||||
tips: 'Here we use window.print() to implement the feature of downloading pdf.'
|
||||
tips: 'Here we use window.print() to implement the feature of downloading PDF.'
|
||||
},
|
||||
theme: {
|
||||
change: 'Change Theme',
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export default {
|
||||
route: {
|
||||
dashboard: 'Panel de control',
|
||||
introduction: 'Introducción',
|
||||
documentation: 'Documentación',
|
||||
guide: 'Guía',
|
||||
permission: 'Permisos',
|
||||
|
@ -10,7 +9,6 @@ export default {
|
|||
directivePermission: 'Permisos de la directiva',
|
||||
icons: 'Iconos',
|
||||
components: 'Componentes',
|
||||
componentIndex: 'Introducción',
|
||||
tinymce: 'Tinymce',
|
||||
markdown: 'Markdown',
|
||||
jsonEditor: 'Editor JSON',
|
||||
|
|
|
@ -24,11 +24,24 @@ const messages = {
|
|||
...elementEsLocale
|
||||
}
|
||||
}
|
||||
export function getLanguage() {
|
||||
const chooseLanguage = Cookies.get('language')
|
||||
if (chooseLanguage) return chooseLanguage
|
||||
|
||||
// if has not choose language
|
||||
const language = (navigator.language || navigator.browserLanguage).toLowerCase()
|
||||
const locales = Object.keys(messages)
|
||||
for (const locale of locales) {
|
||||
if (language.indexOf(locale) > -1) {
|
||||
return locale
|
||||
}
|
||||
}
|
||||
return 'en'
|
||||
}
|
||||
const i18n = new VueI18n({
|
||||
// set locale
|
||||
// options: en | zh | es
|
||||
locale: Cookies.get('language') || 'en',
|
||||
locale: getLanguage(),
|
||||
// set locale messages
|
||||
messages
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export default {
|
||||
route: {
|
||||
dashboard: '首页',
|
||||
introduction: '简述',
|
||||
documentation: '文档',
|
||||
guide: '引导页',
|
||||
permission: '权限测试页',
|
||||
|
@ -10,7 +9,6 @@ export default {
|
|||
directivePermission: '指令权限',
|
||||
icons: '图标',
|
||||
components: '组件',
|
||||
componentIndex: '介绍',
|
||||
tinymce: '富文本编辑器',
|
||||
markdown: 'Markdown',
|
||||
jsonEditor: 'JSON 编辑器',
|
||||
|
@ -91,7 +89,7 @@ export default {
|
|||
editPermission: '编辑权限',
|
||||
roles: '你的权限',
|
||||
switchRoles: '切换权限',
|
||||
tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 Tab 组件或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
|
||||
tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
|
||||
delete: '删除',
|
||||
confirm: '确定',
|
||||
cancel: '取消'
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<logo v-if="showLogo" :collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="$route.path"
|
||||
:default-active="activeMenu"
|
||||
:collapse="isCollapse"
|
||||
:background-color="variables.menuBg"
|
||||
:text-color="variables.menuText"
|
||||
|
@ -30,6 +30,15 @@ export default {
|
|||
'permission_routes',
|
||||
'sidebar'
|
||||
]),
|
||||
activeMenu() {
|
||||
const route = this.$route
|
||||
const { meta, path } = route
|
||||
// if set path, the sidebar will highlight the path you set
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu
|
||||
}
|
||||
return path
|
||||
},
|
||||
showLogo() {
|
||||
return this.$store.state.settings.sidebarLogo
|
||||
},
|
||||
|
|
|
@ -243,7 +243,7 @@ export default {
|
|||
.contextmenu {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
z-index: 100;
|
||||
z-index: 3000;
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
padding: 5px 0;
|
||||
|
|
|
@ -12,32 +12,32 @@ import chartsRouter from './modules/charts'
|
|||
import tableRouter from './modules/table'
|
||||
import nestedRouter from './modules/nested'
|
||||
|
||||
/** note: sub-menu only appear when children.length>=1
|
||||
* detail see https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
|
||||
**/
|
||||
|
||||
/**
|
||||
* hidden: true if `hidden:true` will not show in the sidebar(default is false)
|
||||
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
|
||||
* if not set alwaysShow, only more than one route under the children
|
||||
* Note: sub-menu only appear when route children.length >= 1
|
||||
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
|
||||
*
|
||||
* hidden: true if set true, item will not show in the sidebar(default is false)
|
||||
* alwaysShow: true if set true, will always show the root menu
|
||||
* if not set alwaysShow, when item has more than one children route,
|
||||
* it will becomes nested mode, otherwise not show the root menu
|
||||
* redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
|
||||
* name:'router-name' the name is used by <keep-alive> (must set!!!)
|
||||
* meta : {
|
||||
roles: ['admin','editor'] will control the page roles (you can set multiple roles)
|
||||
title: 'title' the name show in sub-menu and breadcrumb (recommend set)
|
||||
roles: ['admin','editor'] control the page roles (you can set multiple roles)
|
||||
title: 'title' the name show in sidebar and breadcrumb (recommend set)
|
||||
icon: 'svg-name' the icon show in the sidebar
|
||||
noCache: true if true, the page will no be cached(default is false)
|
||||
breadcrumb: false if false, the item will hidden in breadcrumb(default is true)
|
||||
affix: true if true, the tag will affix in the tags-view
|
||||
noCache: true if set true, the page will no be cached(default is false)
|
||||
affix: true if set true, the tag will affix in the tags-view
|
||||
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
|
||||
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
|
||||
}
|
||||
**/
|
||||
*/
|
||||
|
||||
/**
|
||||
* constantRoutes
|
||||
* a base page that does not have permission requirements
|
||||
* all roles can be accessed
|
||||
* */
|
||||
*/
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/redirect',
|
||||
|
@ -57,7 +57,7 @@ export const constantRoutes = [
|
|||
},
|
||||
{
|
||||
path: '/auth-redirect',
|
||||
component: () => import('@/views/login/authredirect'),
|
||||
component: () => import('@/views/login/authRedirect'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ export const asyncRoutes = [
|
|||
path: 'edit/:id(\\d+)',
|
||||
component: () => import('@/views/example/edit'),
|
||||
name: 'EditArticle',
|
||||
meta: { title: 'editArticle', noCache: true },
|
||||
meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' },
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import app from './modules/app'
|
||||
import errorLog from './modules/errorLog'
|
||||
import permission from './modules/permission'
|
||||
import tagsView from './modules/tagsView'
|
||||
import settings from './modules/settings'
|
||||
import user from './modules/user'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
// https://webpack.js.org/guides/dependency-management/#requirecontext
|
||||
const modulesFiles = require.context('./modules', false, /\.js$/)
|
||||
|
||||
// you do not need `import app from './modules/app'`
|
||||
// it will auto require all vuex module from modules file
|
||||
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
|
||||
// set './app.js' => 'app'
|
||||
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
|
||||
const value = modulesFiles(modulePath)
|
||||
modules[moduleName] = value.default
|
||||
return modules
|
||||
}, {})
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
app,
|
||||
errorLog,
|
||||
permission,
|
||||
tagsView,
|
||||
settings,
|
||||
user
|
||||
},
|
||||
modules,
|
||||
getters
|
||||
})
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Cookies from 'js-cookie'
|
||||
import { getLanguage } from '@/lang/index'
|
||||
|
||||
const state = {
|
||||
sidebar: {
|
||||
|
@ -6,7 +7,7 @@ const state = {
|
|||
withoutAnimation: false
|
||||
},
|
||||
device: 'desktop',
|
||||
language: Cookies.get('language') || 'en',
|
||||
language: getLanguage(),
|
||||
size: Cookies.get('size') || 'medium'
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
const state = {
|
||||
logs: []
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
const state = {
|
||||
visitedViews: [],
|
||||
cachedViews: []
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
|
||||
.scrollbar-wrapper {
|
||||
overflow-x: hidden !important;
|
||||
|
||||
.el-scrollbar__view {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.el-scrollbar__bar.is-vertical {
|
||||
|
|
|
@ -23,7 +23,7 @@ service.interceptors.request.use(
|
|||
error => {
|
||||
// Do something with request error
|
||||
console.log(error) // for debug
|
||||
Promise.reject(error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -43,7 +43,7 @@ service.interceptors.response.use(
|
|||
const res = response.data
|
||||
if (res.code !== 20000) {
|
||||
Message({
|
||||
message: res.message,
|
||||
message: res.message || 'error',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
|
@ -61,7 +61,7 @@ service.interceptors.response.use(
|
|||
})
|
||||
})
|
||||
}
|
||||
return Promise.reject('error')
|
||||
return Promise.reject(res.message || 'error')
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div style="display:inline-block;">
|
||||
<!-- $t is vue-i18n global function to translate lang -->
|
||||
<label class="radio-label" style="padding-left:0;">Filename: </label>
|
||||
<el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:340px;" prefix-icon="el-icon-document" />
|
||||
<el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:350px;" prefix-icon="el-icon-document" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- $t is vue-i18n global function to translate lang -->
|
||||
<el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:340px;" prefix-icon="el-icon-document" />
|
||||
<el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:350px;" prefix-icon="el-icon-document" />
|
||||
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="document" @click="handleDownload">
|
||||
{{ $t('excel.selectedExport') }}
|
||||
</el-button>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'Authredirect',
|
||||
name: 'AuthRedirect',
|
||||
created() {
|
||||
const hash = window.location.search.slice(1)
|
||||
if (window.localStorage) {
|
|
@ -23,6 +23,7 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
|
||||
<el-form-item prop="password">
|
||||
<span class="svg-container">
|
||||
<svg-icon icon-class="password" />
|
||||
|
@ -35,12 +36,15 @@
|
|||
:placeholder="$t('login.password')"
|
||||
name="password"
|
||||
auto-complete="on"
|
||||
@keyup.native="checkCapslock"
|
||||
@blur="capsTooltip = false"
|
||||
@keyup.enter.native="handleLogin"
|
||||
/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">
|
||||
{{ $t('login.logIn') }}
|
||||
|
@ -77,7 +81,7 @@
|
|||
<script>
|
||||
import { validUsername } from '@/utils/validate'
|
||||
import LangSelect from '@/components/LangSelect'
|
||||
import SocialSign from './socialsignin'
|
||||
import SocialSign from './socialSignin'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
|
@ -107,6 +111,7 @@ export default {
|
|||
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
|
||||
},
|
||||
passwordType: 'password',
|
||||
capsTooltip: false,
|
||||
loading: false,
|
||||
showDialog: false,
|
||||
redirect: undefined
|
||||
|
@ -134,6 +139,18 @@ export default {
|
|||
// window.removeEventListener('storage', this.afterQRScan)
|
||||
},
|
||||
methods: {
|
||||
checkCapslock({ shiftKey, key } = {}) {
|
||||
if (key && key.length === 1) {
|
||||
if (shiftKey && (key >= 'a' && key <= 'z') || !shiftKey && (key >= 'A' && key <= 'Z')) {
|
||||
this.capsTooltip = true
|
||||
} else {
|
||||
this.capsTooltip = false
|
||||
}
|
||||
}
|
||||
if (key === 'CapsLock' && this.capsTooltip === true) {
|
||||
this.capsTooltip = false
|
||||
}
|
||||
},
|
||||
showPwd() {
|
||||
if (this.passwordType === 'password') {
|
||||
this.passwordType = ''
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px;">
|
||||
{{ $t('permission.roles') }}: {{ roles }}
|
||||
{{ $t('permission.roles') }}: {{ roles }}
|
||||
</div>
|
||||
{{ $t('permission.switchRoles') }}:
|
||||
{{ $t('permission.switchRoles') }}:
|
||||
<el-radio-group v-model="switchRoles">
|
||||
<el-radio-button label="editor" />
|
||||
<el-radio-button label="admin" />
|
||||
|
|
|
@ -54,10 +54,10 @@
|
|||
</el-table>
|
||||
<!-- $t is vue-i18n global function to translate lang (lang in @/lang) -->
|
||||
<div class="show-d">
|
||||
{{ $t('table.dragTips1') }} : {{ oldList }}
|
||||
<el-tag style="margin-right:12px;">{{ $t('table.dragTips1') }} :</el-tag> {{ oldList }}
|
||||
</div>
|
||||
<div class="show-d">
|
||||
{{ $t('table.dragTips2') }} : {{ newList }}
|
||||
<el-tag>{{ $t('table.dragTips2') }} :</el-tag> {{ newList }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -113,9 +113,9 @@ export default {
|
|||
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
|
||||
dataTransfer.setData('Text', '')
|
||||
},
|
||||
onEnd: evt => {
|
||||
const targetRow = this.list.splice(evt.oldIndex, 1)[0]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<!-- $t is vue-i18n global function to translate lang -->
|
||||
<el-input v-model="filename" :placeholder="$t('zip.placeholder')" style="width:300px;" prefix-icon="el-icon-document" />
|
||||
<el-button :loading="downloadLoading" style="margin-bottom:20px;" type="primary" icon="document" @click="handleDownload">
|
||||
{{ $t('zip.export') }} zip
|
||||
{{ $t('zip.export') }} Zip
|
||||
</el-button>
|
||||
<el-table v-loading="listLoading" :data="list" element-loading-text="拼命加载中" border fit highlight-current-row>
|
||||
<el-table-column align="center" label="ID" width="95">
|
||||
|
|
|
@ -41,22 +41,7 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
},
|
||||
after(app) {
|
||||
require('@babel/register')
|
||||
const bodyParser = require('body-parser')
|
||||
|
||||
// parse app.body
|
||||
// http://expressjs.com/en/4x/api.html#req.body
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}))
|
||||
|
||||
const { default: mocks } = require('./mock')
|
||||
for (const mock of mocks) {
|
||||
app[mock.type](mock.url, mock.response)
|
||||
}
|
||||
}
|
||||
after: require('./mock/mock-server.js')
|
||||
},
|
||||
configureWebpack: {
|
||||
// provide the app's title in webpack's name field, so that
|
||||
|
|
Loading…
Reference in New Issue