commit
eb09c5d5e4
|
|
@ -3781,9 +3781,9 @@
|
|||
}
|
||||
},
|
||||
"cropperjs": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.3.5.tgz",
|
||||
"integrity": "sha512-tL3iQJ0rqGDp5Tdb83NVaudV7wKFu2IcLQVF48uty3zfz0vhLS9ifZHbR16L1DRVKtPvAZn1NvTRNuxliTdi5Q=="
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.2.2.tgz",
|
||||
"integrity": "sha512-E+QGUV9zqtV5t7Q/zQD/9vMc2eTJn5hm4MpmHAf12U9LXT815Hy2DSmj0B4a3Gacm7/OJ1MUDTomKGXJBP0osw=="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "5.1.0",
|
||||
|
|
@ -8190,9 +8190,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"iview": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/iview/-/iview-2.14.1.tgz",
|
||||
"integrity": "sha512-0ykE0nN+uFSpIBqJAwUPotfamajxkYIk5U/Z/SzzQdzl1++byDF/+HDL0w/ShEvHV4h1zJJP6D9jyyK+Qu08Xg==",
|
||||
"version": "2.14.3",
|
||||
"resolved": "https://registry.npmjs.org/iview/-/iview-2.14.3.tgz",
|
||||
"integrity": "sha512-jK5CBNuNBKUZWooCVlipBIUkNnGeZHRtypeuMo9VhQmJ9cCXmuI6BalrtxBFkBCnuUXRdFD34/kSevF9Cc2kpg==",
|
||||
"requires": {
|
||||
"async-validator": "1.8.2",
|
||||
"deepmerge": "2.1.1",
|
||||
|
|
@ -8201,18 +8201,13 @@
|
|||
"lodash.throttle": "4.1.1",
|
||||
"popper.js": "1.14.3",
|
||||
"tinycolor2": "1.4.1",
|
||||
"v-click-outside-x": "3.0.0"
|
||||
"v-click-outside-x": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"deepmerge": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.1.tgz",
|
||||
"integrity": "sha512-urQxA1smbLZ2cBbXbaYObM1dJ82aJ2H57A1C/Kklfh/ZN1bgH4G/n5KWhdNfOK11W98gqZfyYj7W4frJJRwA2w=="
|
||||
},
|
||||
"v-click-outside-x": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/v-click-outside-x/-/v-click-outside-x-3.0.0.tgz",
|
||||
"integrity": "sha512-VKm35tQ1tlZFXZc527v05sRXbyoQ8KKT1aeefZrcRCW+mPU4KuTiPy4pe1AH8Pibjzx80iU3pNJ4gNUFSXekUQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -14279,11 +14274,6 @@
|
|||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
|
||||
"integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
|
||||
},
|
||||
"tinymce": {
|
||||
"version": "4.7.13",
|
||||
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-4.7.13.tgz",
|
||||
"integrity": "sha512-6QbNYGV4VExH+p7+o/5km6jOnVSD5mO7aw0s+eKByKnpyG8gZfajxXPhwBM57r7SIravrCI6LFj8DARNe31qPw=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.31",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
|
||||
|
|
@ -14838,6 +14828,11 @@
|
|||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
|
||||
"dev": true
|
||||
},
|
||||
"v-click-outside-x": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v-click-outside-x/-/v-click-outside-x-3.0.1.tgz",
|
||||
"integrity": "sha512-Dqy4XEoAPHP/qRzkB5EF+4/luo2G4feAKDrTpjdlsTB9PVHd6D7ryxVkmNsnhDdjOsJDBDcKRsZq8lD8YqbCjQ=="
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
|
||||
|
|
|
|||
|
|
@ -15,15 +15,14 @@
|
|||
"clipboard": "^2.0.0",
|
||||
"codemirror": "^5.38.0",
|
||||
"countup": "^1.8.2",
|
||||
"cropperjs": "^1.3.5",
|
||||
"cropperjs": "^1.2.2",
|
||||
"echarts": "^4.0.4",
|
||||
"html2canvas": "^1.0.0-alpha.12",
|
||||
"iview": "^2.14.1",
|
||||
"iview": "^2.14.3",
|
||||
"iview-area": "^1.5.17",
|
||||
"js-cookie": "^2.2.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"sortablejs": "^1.7.0",
|
||||
"tinymce": "^4.7.11",
|
||||
"vue": "^2.5.10",
|
||||
"vue-i18n": "^7.8.0",
|
||||
"vue-router": "^3.0.1",
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div class="cropper-wrapper">
|
||||
<img id="aaa" ref="cropperImg" alt="">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cropper from 'cropperjs/dist/cropper.esm.js'
|
||||
import 'cropperjs/dist/cropper.min.css'
|
||||
export default {
|
||||
name: 'ImgCropper',
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
dragMode: {
|
||||
type: String,
|
||||
default: 'move'
|
||||
},
|
||||
previewId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
cropper: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
src (src) {
|
||||
console.log(src)
|
||||
console.log(this.cropper)
|
||||
this.cropper.replace(src)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.log(this.$refs.cropperImg)
|
||||
const aaa = document.getElementById('aaa')
|
||||
this.cropper = new Cropper(aaa, {
|
||||
dragMode: 'move',
|
||||
preview: this.previewId,
|
||||
restore: false,
|
||||
center: false,
|
||||
highlight: false,
|
||||
cropBoxMovable: false,
|
||||
toggleDragModeOnDblclick: false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
</style>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import ImgCropper from './img-cropper'
|
||||
export default ImgCropper
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
.cropper-wrapper{
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #c3c3c3;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img{
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,5 +8,5 @@ export default {
|
|||
* 如果不使用,则需要在路由中给需要在菜单中展示的路由设置meta: {title: 'xxx'}
|
||||
* 用来在菜单中显示文字
|
||||
*/
|
||||
useI18n: false
|
||||
useI18n: true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,18 @@ export const forEach = (arr, fn) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const getCommonString = (arr1, arr2) => {
|
||||
/**
|
||||
* @param {Array} arr1
|
||||
* @param {Array} arr2
|
||||
* @description 得到两个数组的交集, 两个数组的元素为数值或字符串
|
||||
*/
|
||||
export const getIntersection = (arr1, arr2) => {
|
||||
let len = Math.min(arr1.length, arr2.length)
|
||||
let i = -1
|
||||
let res = []
|
||||
while (++i < len) {
|
||||
const item = arr2[i]
|
||||
if (arr1.indexOf() > -1) res.push(item)
|
||||
if (arr1.indexOf(item) > -1) res.push(item)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -22,9 +27,9 @@ export const getCommonString = (arr1, arr2) => {
|
|||
/**
|
||||
* @param {Array} arr1
|
||||
* @param {Array} arr2
|
||||
* @description 得到两个数组的交集, 两个数组的元素为数值或字符串
|
||||
* @description 得到两个数组的并集, 两个数组的元素为数值或字符串
|
||||
*/
|
||||
export const getIntersection = (arr1, arr2) => {
|
||||
export const getUnion = (arr1, arr2) => {
|
||||
return Array.from(new Set([...arr1, ...arr2]))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,17 +120,6 @@ export const getNewTagList = (list, newRoute) => {
|
|||
return newList
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Boolean} status 状态 1 => locked 0 => unlocked
|
||||
* @description 这里只是为了演示,实际应该将锁定状态的设置和获取用接口来实现
|
||||
*/
|
||||
export const setLockStatus = (status) => {
|
||||
localStorage.isLocked = status
|
||||
}
|
||||
export const getLockStatus = () => {
|
||||
return parseInt(localStorage.isLocked)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} access 用户权限数组,如 ['super_admin', 'admin']
|
||||
* @param {*} route 路由列表
|
||||
|
|
@ -261,3 +250,30 @@ export const getTableDataFromArray = (array) => {
|
|||
tableData
|
||||
}
|
||||
}
|
||||
|
||||
export const findNodeUpper = (ele, tag) => {
|
||||
if (ele.parentNode) {
|
||||
if (ele.parentNode.tagName === tag.toUpperCase()) {
|
||||
return ele.parentNode
|
||||
} else {
|
||||
return findNodeUpper(ele.parentNode, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const findNodeDownward = (ele, tag) => {
|
||||
const tagName = tag.toUpperCase()
|
||||
if (ele.childNodes.length) {
|
||||
let i = -1
|
||||
let len = ele.childNodes.length
|
||||
while (++i < len) {
|
||||
let child = ele.childNodes[i]
|
||||
if (child.tagName === tagName) return child
|
||||
else return findNodeDownward(child, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const showByAccess = (access, canViewAccess) => {
|
||||
return hasOneOf(canViewAccess, access)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@ import zhTwLocale from 'iview/src/locale/lang/zh-TW'
|
|||
Vue.use(VueI18n)
|
||||
|
||||
// 自动根据浏览器系统语言设置语言
|
||||
// const navLang = navigator.language
|
||||
// const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false
|
||||
// let lang = window.localStorage.lang || localLang || 'zh-CN'
|
||||
let lang = 'zh-CN'
|
||||
const navLang = navigator.language
|
||||
const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false
|
||||
let lang = window.localStorage.lang || localLang || 'zh-CN'
|
||||
|
||||
Vue.config.lang = lang
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
export default {
|
||||
components: 'components',
|
||||
count_to: 'count-to',
|
||||
components: 'Components',
|
||||
count_to_page: 'Count-to',
|
||||
tables_page: 'Table',
|
||||
split_pane_page: 'Split-pane',
|
||||
markdown_page: 'Markdown-editor',
|
||||
editor_page: 'Rich-Text-Editor',
|
||||
icons_page: 'Custom-icon',
|
||||
img_cropper_page: 'Image-editor',
|
||||
update: 'Update',
|
||||
update_table_page: 'Update .CSV',
|
||||
update_paste_page: 'Paste Table Data',
|
||||
multilevel: 'multilevel',
|
||||
directive_page: 'Directive',
|
||||
level_1: 'level-1',
|
||||
level_2: 'level-2',
|
||||
level_2_1: 'level-2-1'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
export default {
|
||||
components: '组件',
|
||||
count_to: '数字渐变',
|
||||
count_to_page: '数字渐变',
|
||||
tables_page: '多功能表格',
|
||||
split_pane_page: '分割窗口',
|
||||
markdown_page: 'Markdown编辑器',
|
||||
editor_page: '富文本编辑器',
|
||||
icons_page: '自定义图标',
|
||||
img_cropper_page: '图片编辑器',
|
||||
update: '上传数据',
|
||||
update_table_page: '上传CSV文件',
|
||||
update_paste_page: '粘贴表格数据',
|
||||
multilevel: '多级菜单',
|
||||
directive_page: '指令',
|
||||
level_1: 'level-1',
|
||||
level_2: 'level-2',
|
||||
level_2_1: 'level-2-1'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
export default {
|
||||
components: '组件',
|
||||
count_to: '数字渐变',
|
||||
count_to_page: '数字渐变',
|
||||
tables_page: '多功能表格',
|
||||
split_pane_page: '分割窗口',
|
||||
markdown_page: 'Markdown編輯器',
|
||||
editor_page: '富文本編輯器',
|
||||
icons_page: '自定義圖標',
|
||||
img_cropper_page: '圖片編輯器',
|
||||
update: '上傳數據',
|
||||
update_table_page: '上傳CSV文件',
|
||||
update_paste_page: '粘貼表格數據',
|
||||
multilevel: '多级菜单',
|
||||
directive_page: '指令',
|
||||
level_1: 'level-1',
|
||||
level_2: 'level-2',
|
||||
level_2_1: 'level-2-1'
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ importDirective(Vue)
|
|||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
i18n,
|
||||
store,
|
||||
render: h => h(App)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,49 +3,36 @@ import Router from 'vue-router'
|
|||
import routes from './routers'
|
||||
import store from '@/store'
|
||||
import iView from 'iview'
|
||||
import { getToken, getLockStatus, canTurnTo } from '@/libs/util'
|
||||
import { getToken, canTurnTo } from '@/libs/util'
|
||||
|
||||
Vue.use(Router)
|
||||
const router = new Router({
|
||||
routes
|
||||
})
|
||||
const LOCK_PAGE_NAME = 'lock_page'
|
||||
const LOGIN_PAGE_NAME = 'login'
|
||||
const IS_LOCKED = getLockStatus()
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
iView.LoadingBar.start()
|
||||
if (IS_LOCKED && to.name !== LOCK_PAGE_NAME) {
|
||||
// 当前是锁定状态并且用户要跳转到的页面不是解锁页面
|
||||
const token = getToken()
|
||||
if (!token && to.name !== LOGIN_PAGE_NAME) {
|
||||
// 未登录且要跳转的页面不是登录页
|
||||
next({
|
||||
replace: true, // 重定向到解锁页面
|
||||
name: LOCK_PAGE_NAME
|
||||
name: LOGIN_PAGE_NAME // 跳转到登录页
|
||||
})
|
||||
} else if (!token && to.name === LOGIN_PAGE_NAME) {
|
||||
// 未登陆且要跳转的页面是登录页
|
||||
next() // 跳转
|
||||
} else if (token && to.name === LOGIN_PAGE_NAME) {
|
||||
// 已登录且要跳转的页面是登录页
|
||||
next({
|
||||
name: 'home' // 跳转到home页
|
||||
})
|
||||
} else if (IS_LOCKED && to.name === LOCK_PAGE_NAME) {
|
||||
// 当前未锁定且用户要跳转到的页面是解锁页面
|
||||
next(false) // 不做跳转
|
||||
} else {
|
||||
const token = getToken()
|
||||
if (!token && to.name !== LOGIN_PAGE_NAME) {
|
||||
// 未登录且要跳转的页面不是登录页
|
||||
next({
|
||||
name: LOGIN_PAGE_NAME // 跳转到登录页
|
||||
})
|
||||
} else if (!token && to.name === LOGIN_PAGE_NAME) {
|
||||
// 未登陆且要跳转的页面是登录页
|
||||
next() // 跳转
|
||||
} else if (token && to.name === LOGIN_PAGE_NAME) {
|
||||
// 已登录且要跳转的页面是登录页
|
||||
next({
|
||||
name: 'home' // 跳转到home页
|
||||
})
|
||||
} else {
|
||||
store.dispatch('getUserInfo').then(user => {
|
||||
// 拉取用户信息,通过用户权限和跳转的页面的name来判断是否有权限访问;access必须是一个数组,如:['super_admin'] ['super_admin', 'admin']
|
||||
if (canTurnTo(to.name, user.access, routes)) next() // 有权限,可访问
|
||||
else next({ replace: true, name: 'error_401' }) // 无权限,重定向到401页面
|
||||
})
|
||||
}
|
||||
store.dispatch('getUserInfo').then(user => {
|
||||
// 拉取用户信息,通过用户权限和跳转的页面的name来判断是否有权限访问;access必须是一个数组,如:['super_admin'] ['super_admin', 'admin']
|
||||
if (canTurnTo(to.name, user.access, routes)) next() // 有权限,可访问
|
||||
else next({ replace: true, name: 'error_401' }) // 无权限,重定向到401页面
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,15 @@ export default [
|
|||
},
|
||||
component: () => import('@/view/components/editor/editor.vue')
|
||||
},
|
||||
{
|
||||
path: 'img_cropper_page',
|
||||
name: 'img_cropper_page',
|
||||
meta: {
|
||||
icon: 'crop',
|
||||
title: '图片编辑器'
|
||||
},
|
||||
component: () => import('@/view/components/img-cropper/img-cropper.vue')
|
||||
},
|
||||
{
|
||||
path: 'icons_page',
|
||||
name: 'icons_page',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ export default {
|
|||
state: {
|
||||
breadCrumbList: [],
|
||||
tagNavList: [],
|
||||
homeRoute: getHomeRoute(routers)
|
||||
homeRoute: getHomeRoute(routers),
|
||||
local: ''
|
||||
},
|
||||
getters: {
|
||||
menuList: (state, getters, rootState) => getMenuByRouter(routers, rootState.user.access)
|
||||
|
|
@ -25,6 +26,9 @@ export default {
|
|||
else state.tagNavList.unshift(item)
|
||||
setTagNavListInLocalstorage([...state.tagNavList])
|
||||
}
|
||||
},
|
||||
setLocal (state, lang) {
|
||||
state.local = lang
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<Row :gutter="20">
|
||||
<i-col span="12">
|
||||
<div class="img-cropper-page">
|
||||
<img-cropper :src="imgSrc" preview-id="preview_con"/>
|
||||
</div>
|
||||
</i-col>
|
||||
<i-col span="12">
|
||||
<div class="preview-con" id="preview_con"></div>
|
||||
</i-col>
|
||||
</Row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ImgCropper from '_c/img-cropper'
|
||||
import img from '@/assets/images/talkingdata.png'
|
||||
export default {
|
||||
name: 'img_cropper_page',
|
||||
components: {
|
||||
ImgCropper
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
imgSrc: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.imgSrc = img
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.img-cropper-page{
|
||||
height: 400px;
|
||||
}
|
||||
.preview-con{
|
||||
height: 400px;
|
||||
border: 1px solid #c3c3c3;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,11 +4,12 @@
|
|||
<i-col>
|
||||
<Card>
|
||||
<Row>
|
||||
<i-col span="4">
|
||||
<i-col span="5">
|
||||
<Button type="primary" @click="showModal">显示可拖动弹窗</Button>
|
||||
<br/>
|
||||
<Button v-draggable="buttonOptions" class="draggable-btn">这个按钮也是可以拖动的</Button>
|
||||
</i-col>
|
||||
<i-col span="20">
|
||||
<i-col span="19">
|
||||
<div class="intro-con">
|
||||
<Modal v-draggable="options" v-model="visible">标题</Modal>
|
||||
<pre class="code-con">
|
||||
|
|
@ -22,10 +23,10 @@
|
|||
</Row>
|
||||
</Card>
|
||||
</i-col>
|
||||
<Modal v-draggable="options" v-model="modalVisible">
|
||||
拖动这里即可拖动整个弹窗
|
||||
</Modal>
|
||||
</Row>
|
||||
<Modal v-draggable="options" v-model="modalVisible">
|
||||
拖动这里即可拖动整个弹窗
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -43,7 +44,8 @@ export default {
|
|||
buttonOptions: {
|
||||
trigger: '.draggable-btn',
|
||||
body: '.draggable-btn'
|
||||
}
|
||||
},
|
||||
statu: 1
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -56,7 +58,7 @@ export default {
|
|||
|
||||
<style>
|
||||
.intro-con{
|
||||
height: 140px;
|
||||
min-height: 140px;
|
||||
}
|
||||
.draggable-btn{
|
||||
margin-top: 20px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div v-if="showFullScreenBtn" class="full-screen-btn-con">
|
||||
<Tooltip :content="value ? '退出全屏' : '全屏'" placement="bottom">
|
||||
<Icon @click.native="handleChange" :type="value ? 'arrow-shrink' : 'arrow-expand'" :size="23"></Icon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Fullscreen',
|
||||
computed: {
|
||||
showFullScreenBtn () {
|
||||
return window.navigator.userAgent.indexOf('MSIE') < 0
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleFullscreen () {
|
||||
let main = document.body
|
||||
if (this.value) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen()
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen()
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen()
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen()
|
||||
}
|
||||
} else {
|
||||
if (main.requestFullscreen) {
|
||||
main.requestFullscreen()
|
||||
} else if (main.mozRequestFullScreen) {
|
||||
main.mozRequestFullScreen()
|
||||
} else if (main.webkitRequestFullScreen) {
|
||||
main.webkitRequestFullScreen()
|
||||
} else if (main.msRequestFullscreen) {
|
||||
main.msRequestFullscreen()
|
||||
}
|
||||
}
|
||||
},
|
||||
handleChange () {
|
||||
this.handleFullscreen()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
let isFullscreen = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen
|
||||
isFullscreen = !!isFullscreen
|
||||
document.addEventListener('fullscreenchange', () => {
|
||||
this.$emit('input', !this.value)
|
||||
this.$emit('on-change', !this.value)
|
||||
})
|
||||
document.addEventListener('mozfullscreenchange', () => {
|
||||
this.$emit('input', !this.value)
|
||||
this.$emit('on-change', !this.value)
|
||||
})
|
||||
document.addEventListener('webkitfullscreenchange', () => {
|
||||
this.$emit('input', !this.value)
|
||||
this.$emit('on-change', !this.value)
|
||||
})
|
||||
document.addEventListener('msfullscreenchange', () => {
|
||||
this.$emit('input', !this.value)
|
||||
this.$emit('on-change', !this.value)
|
||||
})
|
||||
this.$emit('input', isFullscreen)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.full-screen-btn-con .ivu-tooltip-rel{
|
||||
height: 64px;
|
||||
line-height: 73px;
|
||||
i{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import Fullscreen from './fullscreen.vue'
|
||||
export default Fullscreen
|
||||
|
|
@ -6,5 +6,9 @@
|
|||
float: right;
|
||||
height: auto;
|
||||
padding-right: 20px;
|
||||
line-height: 64px;
|
||||
& > *{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
import Language from './language.vue'
|
||||
export default Language
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<template>
|
||||
<div>
|
||||
<Dropdown trigger="click" @on-click="selectLang">
|
||||
<a href="javascript:void(0)">
|
||||
{{ title }}
|
||||
<Icon type="arrow-down-b"></Icon>
|
||||
</a>
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem v-for="(value, key) in localList" :name="key" :key="`lang-${key}`">{{ value }}</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Language',
|
||||
props: {
|
||||
lang: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
langList: {
|
||||
'zh-CN': '语言',
|
||||
'zh-TW': '語言',
|
||||
'en-US': 'Lang'
|
||||
},
|
||||
localList: {
|
||||
'zh-CN': '中文简体',
|
||||
'zh-TW': '中文繁体',
|
||||
'en-US': 'English'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
lang (lang) {
|
||||
this.$i18n.locale = lang
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title () {
|
||||
return this.langList[this.lang]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectLang (name) {
|
||||
this.$emit('on-lang-change', name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -26,8 +26,9 @@
|
|||
<script>
|
||||
import SideMenuItem from './side-menu-item.vue'
|
||||
import CollapsedMenu from './collapsed-menu.vue'
|
||||
import { getIntersection } from '@/libs/tools'
|
||||
import { getUnion } from '@/libs/tools'
|
||||
import mixin from './mixin'
|
||||
|
||||
export default {
|
||||
name: 'SideMenu',
|
||||
mixins: [ mixin ],
|
||||
|
|
@ -88,7 +89,7 @@ export default {
|
|||
watch: {
|
||||
activeName (name) {
|
||||
if (this.accordion) this.openedNames = this.getOpenedNamesByActiveName(name)
|
||||
else this.openedNames = getIntersection(this.openedNames, this.getOpenedNamesByActiveName(name))
|
||||
else this.openedNames = getUnion(this.openedNames, this.getOpenedNamesByActiveName(name))
|
||||
},
|
||||
openNames (newNames) {
|
||||
this.openedNames = newNames
|
||||
|
|
@ -100,7 +101,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted () {
|
||||
this.openedNames = getIntersection(this.openedNames, this.getOpenedNamesByActiveName(name))
|
||||
this.openedNames = getUnion(this.openedNames, this.getOpenedNamesByActiveName(name))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
.user{
|
||||
&-avator-dropdown{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
// height: 64px;
|
||||
vertical-align: middle;
|
||||
line-height: 10px;
|
||||
// line-height: 64px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
<Header class="header-con">
|
||||
<header-bar :collapsed="collapsed" @on-coll-change="handleCollapsedChange">
|
||||
<user :user-avator="userAvator"/>
|
||||
<language @on-lang-change="setLocal" style="margin-right: 10px;" :lang="local"/>
|
||||
<fullscreen v-model="isFullscreen" style="margin-right: 10px;"/>
|
||||
</header-bar>
|
||||
</Header>
|
||||
<Content>
|
||||
|
|
@ -35,6 +37,8 @@ import SideMenu from './components/side-menu'
|
|||
import HeaderBar from './components/header-bar'
|
||||
import TagsNav from './components/tags-nav'
|
||||
import User from './components/user'
|
||||
import Fullscreen from './components/fullscreen'
|
||||
import Language from './components/language'
|
||||
import { mapMutations, mapActions } from 'vuex'
|
||||
import { getNewTagList, getNextName } from '@/libs/util'
|
||||
import minLogo from '@/assets/images/logo-min.jpg'
|
||||
|
|
@ -45,14 +49,17 @@ export default {
|
|||
components: {
|
||||
SideMenu,
|
||||
HeaderBar,
|
||||
Language,
|
||||
TagsNav,
|
||||
Fullscreen,
|
||||
User
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
collapsed: false,
|
||||
minLogo,
|
||||
maxLogo
|
||||
maxLogo,
|
||||
isFullscreen: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -70,13 +77,17 @@ export default {
|
|||
},
|
||||
menuList () {
|
||||
return this.$store.getters.menuList
|
||||
},
|
||||
local () {
|
||||
return this.$store.state.app.local
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'setBreadCrumb',
|
||||
'setTagNavList',
|
||||
'addTag'
|
||||
'addTag',
|
||||
'setLocal'
|
||||
]),
|
||||
...mapActions([
|
||||
'handleLogin'
|
||||
|
|
@ -112,6 +123,8 @@ export default {
|
|||
this.setTagNavList()
|
||||
this.addTag(this.$store.state.app.homeRoute)
|
||||
this.setBreadCrumb(this.$route.matched)
|
||||
// 设置初始语言
|
||||
this.setLocal(this.$i18n.locale)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ module.exports = (on, config) => Object.assign({}, config, {
|
|||
integrationFolder: 'tests/e2e/specs',
|
||||
screenshotsFolder: 'tests/e2e/screenshots',
|
||||
videosFolder: 'tests/e2e/videos',
|
||||
supportFile: 'tests/e2e/support/index.js',
|
||||
});
|
||||
supportFile: 'tests/e2e/support/index.js'
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
describe('My First Test', () => {
|
||||
it('Visits the app root url', () => {
|
||||
cy.visit('/');
|
||||
cy.contains('h1', 'Welcome to Your Vue.js App');
|
||||
});
|
||||
});
|
||||
cy.visit('/')
|
||||
cy.contains('h1', 'Welcome to Your Vue.js App')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { expect } from 'chai';
|
||||
import { shallow } from '@vue/test-utils';
|
||||
import HelloWorld from '@/components/HelloWorld.vue';
|
||||
import { expect } from 'chai'
|
||||
import { shallow } from '@vue/test-utils'
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
describe('HelloWorld.vue', () => {
|
||||
it('renders props.msg when passed', () => {
|
||||
const msg = 'new message';
|
||||
const msg = 'new message'
|
||||
const wrapper = shallow(HelloWorld, {
|
||||
propsData: { msg },
|
||||
});
|
||||
expect(wrapper.text()).to.include(msg);
|
||||
});
|
||||
});
|
||||
propsData: { msg }
|
||||
})
|
||||
expect(wrapper.text()).to.include(msg)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,10 +9,13 @@ const env = process.env.NODE_ENV || 'development'
|
|||
fs.writeFileSync(path.join(__dirname, './config/env.js'), `export default '${env}'
|
||||
`)
|
||||
|
||||
// 这里需要修改为你线上项目存放的路径
|
||||
// 比如你打包的文件放到服务器的my-app文件夹,域名为a.com,则应改为
|
||||
// http(s)://a.com/my-app/
|
||||
const BASE_URL = 'https://iview.github.io/iview-admin/'
|
||||
// 项目部署基础
|
||||
// 默认情况下,我们假设你的应用将被部署在域的根目录下,
|
||||
// 例如:https://www.my-app.com/
|
||||
// 如果您的应用程序部署在子路径中,则需要在这指定子路径
|
||||
// 例如:https://www.foobar.com/my-app/
|
||||
// 需要将它改为'/my-app/'
|
||||
const BASE_URL = '/'
|
||||
|
||||
module.exports = {
|
||||
// Project deployment base
|
||||
|
|
|
|||
Loading…
Reference in New Issue