Merge pull request #747 from iview/2.0

2.0
This commit is contained in:
Lison 2018-07-02 20:55:30 +08:00 committed by GitHub
commit eb09c5d5e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 426 additions and 110 deletions

29
package-lock.json generated
View File

@ -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",

View File

@ -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

View File

@ -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>

View File

@ -0,0 +1,2 @@
import ImgCropper from './img-cropper'
export default ImgCropper

View File

@ -0,0 +1,9 @@
.cropper-wrapper{
box-sizing: border-box;
border: 1px solid #c3c3c3;
width: 100%;
height: 100%;
img{
max-height: 100%;
}
}

View File

@ -8,5 +8,5 @@ export default {
* 如果不使用则需要在路由中给需要在菜单中展示的路由设置meta: {title: 'xxx'}
* 用来在菜单中显示文字
*/
useI18n: false
useI18n: true
}

View File

@ -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]))
}

View File

@ -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)
}

View File

@ -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

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -30,6 +30,7 @@ importDirective(Vue)
new Vue({
el: '#app',
router,
i18n,
store,
render: h => h(App)
})

View File

@ -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页面
})
}
})

View File

@ -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',

View File

@ -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
}
}
}

View File

@ -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>

View File

@ -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">
&lt;Modal v-draggable="options" v-model="visible"&gt;标题&lt;/Modal&gt;
<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;

View File

@ -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>

View File

@ -0,0 +1,2 @@
import Fullscreen from './fullscreen.vue'
export default Fullscreen

View File

@ -6,5 +6,9 @@
float: right;
height: auto;
padding-right: 20px;
line-height: 64px;
& > *{
float: right;
}
}
}

View File

@ -0,0 +1,2 @@
import Language from './language.vue'
export default Language

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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'
})

View File

@ -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')
})
})

View File

@ -14,7 +14,7 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -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)
})
})

View File

@ -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