This commit is contained in:
张成
2025-10-08 15:10:33 +08:00
commit 2e1cd65b07
161 changed files with 19936 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
import ABackTop from './index.vue'
export default ABackTop

View File

@@ -0,0 +1,94 @@
<template>
<div :class="classes" :style="styles" @click="back">
<slot>
<div :class="innerClasses">
<i class="ivu-icon ivu-icon-ios-arrow-up"></i>
</div>
</slot>
</div>
</template>
<script>
import { scrollTop, on, off } from '@/utils/tools'
const prefixCls = 'ivu-back-top'
export default {
name: 'ABackTop',
props: {
height: {
type: Number,
default: 400
},
bottom: {
type: Number,
default: 30
},
right: {
type: Number,
default: 30
},
duration: {
type: Number,
default: 1000
},
container: {
type: null,
default: window
}
},
data() {
return {
backTop: false
}
},
mounted() {
// window.addEventListener('scroll', this.handleScroll, false)
// window.addEventListener('resize', this.handleScroll, false)
on(this.containerEle, 'scroll', this.handleScroll)
on(this.containerEle, 'resize', this.handleScroll)
},
beforeDestroy() {
// window.removeEventListener('scroll', this.handleScroll, false)
// window.removeEventListener('resize', this.handleScroll, false)
off(this.containerEle, 'scroll', this.handleScroll)
off(this.containerEle, 'resize', this.handleScroll)
},
computed: {
classes() {
return [
`${prefixCls}`,
{
[`${prefixCls}-show`]: this.backTop
}
]
},
styles() {
return {
bottom: `${this.bottom}px`,
right: `${this.right}px`
}
},
innerClasses() {
return `${prefixCls}-inner`
},
containerEle() {
return this.container === window
? window
: document.querySelector(this.container)
}
},
methods: {
handleScroll() {
this.backTop = this.containerEle.scrollTop >= this.height
},
back() {
let target =
typeof this.container === 'string'
? this.containerEle
: document.documentElement || document.body
const sTop = target.scrollTop
scrollTop(this.containerEle, sTop, 0, this.duration)
this.$emit('on-click')
}
}
}
</script>

View File

@@ -0,0 +1,90 @@
<template>
<div v-if="showFullScreenBtn" class="full-screen-btn-con">
<Tooltip :content="value ? '退出全屏' : '全屏'" placement="bottom">
<Icon @click.native="handleChange" :type="value ? 'md-contract' : 'md-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: 56px;
i {
cursor: pointer;
}
}
</style>

View File

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

View File

@@ -0,0 +1,4 @@
.custom-bread-crumb{
display: inline-block;
vertical-align: top;
}

View File

@@ -0,0 +1,46 @@
<template>
<div class="custom-bread-crumb">
<Breadcrumb :style="{fontSize: `${fontSize}px`}">
<BreadcrumbItem v-for="item in list" :to="item.to" :key="`bread-crumb-${item.name}`">
<common-icon style="margin-right: 4px;" :type="item.icon || ''" />
{{ showTitle(item) }}
</BreadcrumbItem>
</Breadcrumb>
</div>
</template>
<script>
import { showTitle } from '@/utils/tools'
import CommonIcon from '@component/common-icon/common-icon'
import './custom-bread-crumb.less'
export default {
name: 'customBreadCrumb',
components: {
CommonIcon,
},
props: {
list: {
type: Array,
default: () => [],
},
fontSize: {
type: Number,
default: 14,
},
showIcon: {
type: Boolean,
default: false,
},
},
methods: {
showTitle(item) {
return showTitle(item, this)
},
isCustomIcon(iconName) {
return iconName.indexOf('_') === 0
},
getCustomIconName(iconName) {
return iconName.slice(1)
},
},
}
</script>

View File

@@ -0,0 +1,2 @@
import customBreadCrumb from './custom-bread-crumb.vue'
export default customBreadCrumb

View File

@@ -0,0 +1,18 @@
.header-bar {
width: 100%;
height: 100%;
position: relative;
height: 64px;
display: flex;
flex-direction: row;
.custom-content-con {
height: 64px;
padding-right: 120px;
line-height: 64px;
display: inline-block;
vertical-align: top;
flex: 1;
}
}

View File

@@ -0,0 +1,39 @@
<template>
<div class="header-bar">
<sider-trigger :collapsed="collapsed" icon="md-menu" @on-change="handleCollpasedChange"></sider-trigger>
<custom-bread-crumb show-icon style="margin-left: 30px;" :list="breadCrumbList"></custom-bread-crumb>
<div class="custom-content-con">
<slot></slot>
</div>
</div>
</template>
<script>
import siderTrigger from './sider-trigger'
import customBreadCrumb from './custom-bread-crumb'
import './header-bar.less'
export default {
name: 'HeaderBar',
components: {
siderTrigger,
customBreadCrumb,
},
props: {
collapsed: Boolean,
},
computed: {
breadCrumbList() {
let route = this.$route.matched.map((p) => {
let { name, path, meta } = p
return { name, path, meta }
})
route.shift()
return route
},
},
methods: {
handleCollpasedChange(state) {
this.$emit('on-coll-change', state)
},
},
}
</script>

View File

@@ -0,0 +1,2 @@
import HeaderBar from './header-bar'
export default HeaderBar

View File

@@ -0,0 +1,2 @@
import siderTrigger from './sider-trigger.vue'
export default siderTrigger

View File

@@ -0,0 +1,21 @@
.trans{
transition: transform .2s ease;
}
@size: 40px;
.sider-trigger-a{
padding: 6px;
width: @size;
height: @size;
display: inline-block;
text-align: center;
color: #5c6b77;
margin-top: 12px;
i{
.trans;
vertical-align: top;
}
&.collapsed i{
transform: rotateZ(90deg);
.trans;
}
}

View File

@@ -0,0 +1,27 @@
<template>
<a @click="handleChange" type="text" :class="['sider-trigger-a', collapsed ? 'collapsed' : '']"><Icon :type="icon" :size="size" /></a>
</template>
<script>
export default {
name: 'siderTrigger',
props: {
collapsed: Boolean,
icon: {
type: String,
default: 'navicon-round'
},
size: {
type: Number,
default: 26
}
},
methods: {
handleChange() {
this.$emit('on-change', !this.collapsed)
}
}
}
</script>
<style lang="less">
@import './sider-trigger.less';
</style>

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 :size="18" type="md-arrow-dropdown" />
</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

@@ -0,0 +1,58 @@
<template>
<Dropdown ref="dropdown" @on-click="handleClick" :class="hideTitle ? '' : 'collased-menu-dropdown'" :transfer="hideTitle" :placement="placement">
<a class="drop-menu-a" type="text" @mouseover="handleMousemove($event, children)" :style="{textAlign: !hideTitle ? 'left' : ''}">
<common-icon :size="rootIconSize" :color="textColor" :type="parentItem.meta.icon" /><span class="menu-title" v-if="!hideTitle">{{
showTitle(parentItem) }}</span>
<Icon style="float: right;" v-if="!hideTitle" type="ios-arrow-forward" :size="16" />
</a>
<DropdownMenu ref="dropdown" slot="list">
<template v-for="child in children">
<collapsed-menu v-if="showChildren(child)" :icon-size="iconSize" :parent-item="child" :key="`drop-${child.name}`"></collapsed-menu>
<DropdownItem v-else :key="`drop-${child.name}`" :name="child.name">
<common-icon :size="iconSize" :type="child.meta.icon" /><span class="menu-title">{{ showTitle(child) }}</span>
</DropdownItem>
</template>
</DropdownMenu>
</Dropdown>
</template>
<script>
import mixin from './mixin'
import itemMixin from './item-mixin'
import { findNodeUpperByClasses } from '@/utils/tools'
export default {
name: 'CollapsedMenu',
mixins: [mixin, itemMixin],
props: {
hideTitle: {
type: Boolean,
default: false,
},
rootIconSize: {
type: Number,
default: 16,
},
},
data() {
return {
placement: 'right-end',
}
},
methods: {
handleClick(name) {
this.$emit('on-click', name)
},
handleMousemove(event, children) {
const { pageY } = event
const height = children.length * 38
const isOverflow = pageY + height < window.innerHeight
this.placement = isOverflow ? 'right-start' : 'right-end'
},
},
mounted() {
let dropdown = findNodeUpperByClasses(this.$refs.dropdown.$el, ['ivu-select-dropdown', 'ivu-dropdown-transfer'])
if (dropdown) dropdown.style.overflow = 'visible'
},
}
</script>

View File

@@ -0,0 +1,2 @@
import SideMenu from './side-menu.vue'
export default SideMenu

View File

@@ -0,0 +1,21 @@
export default {
props: {
parentItem: {
type: Object,
default: () => {}
},
theme: String,
iconSize: Number
},
computed: {
parentName() {
return this.parentItem.name
},
children() {
return this.parentItem.children
},
textColor() {
return this.theme === 'dark' ? '#fff' : '#495060'
}
}
}

View File

@@ -0,0 +1,18 @@
import CommonIcon from "@component/common-icon";
import { showTitle } from "@/utils/tools";
export default {
components: {
CommonIcon
},
methods: {
showTitle(item) {
return showTitle(item, this);
},
showChildren(item) {
return item.type === "菜单";
},
getNameOrHref(item, children0) {
return item.href ? `isTurnByHref_${item.href}` : item.name;
}
}
};

View File

@@ -0,0 +1,25 @@
<template>
<Submenu :name="`${parentName}`">
<template slot="title">
<common-icon :type="parentItem.meta.icon || ''" />
<span>{{ showTitle(parentItem) }}</span>
</template>
<template v-for="item in children">
<template v-if="item.is_show_menu">
<side-menu-item v-if="showChildren(item)" :key="`menu-${item.name}`" :parent-item="item"></side-menu-item>
<menu-item v-else :name="getNameOrHref(item)" :key="`menu-${item.name}`">
<common-icon :type="item.meta.icon || ''" /><span>{{ showTitle(item) }}</span>
</menu-item>
</template>
</template>
</Submenu>
</template>
<script>
import mixin from './mixin'
import itemMixin from './item-mixin'
export default {
name: 'SideMenuItem',
mixins: [mixin, itemMixin],
mounted() {},
}
</script>

View File

@@ -0,0 +1,39 @@
.side-menu-wrapper {
user-select: none;
.menu-collapsed {
padding-top: 10px;
.ivu-dropdown {
width: 100%;
.ivu-dropdown-rel a {
width: 100%;
}
}
.ivu-tooltip {
width: 100%;
.ivu-tooltip-rel {
width: 100%;
}
.ivu-tooltip-popper .ivu-tooltip-content {
.ivu-tooltip-arrow {
border-right-color: #fff;
}
.ivu-tooltip-inner {
background: #fff;
color: #495060;
}
}
}
}
a.drop-menu-a {
display: inline-block;
padding: 6px 15px;
width: 100%;
text-align: center;
color: #495060;
}
}
.menu-title {
padding-left: 6px;
}

View File

@@ -0,0 +1,112 @@
<template>
<div class="side-menu-wrapper">
<slot></slot>
<Menu ref="menu" v-show="!collapsed" :active-name="activeName" :open-names="openedNames" :accordion="true" :theme="theme" width="auto" @on-select="handleSelect">
<template v-for="item in menuList">
<template>
<side-menu-item v-if="showChildren(item)" :key="`menu-${item.name}`" :parent-item="item"></side-menu-item>
<menu-item v-else :name="getNameOrHref(item)" :key="`menu-${item.name}`">
<common-icon :type="item.meta.icon || ''" /><span>{{ showTitle(item) }}</span>
</menu-item>
</template>
</template>
</Menu>
<div class="menu-collapsed" v-show="collapsed" :list="menuList">
<template v-for="item in menuList">
<collapsed-menu v-if="item.type==='菜单'" @on-click="handleSelect" hide-title :root-icon-size="rootIconSize" :icon-size="iconSize" :theme="theme" :parent-item="item" :key="`drop-menu-${item.name}`">
</collapsed-menu>
<Tooltip transfer v-else :content="showTitle(item.children && item.children[0] ? item.children[0] : item)" placement="right" :key="`drop-menu-${item.name}`">
<a @click="handleSelect(getNameOrHref(item, true))" class="drop-menu-a" :style="{textAlign: 'center'}">
<common-icon :size="rootIconSize" :color="textColor" :type="item.meta.icon" />
</a>
</Tooltip>
</template>
</div>
</div>
</template>
<script>
import SideMenuItem from './side-menu-item.vue'
import CollapsedMenu from './collapsed-menu.vue'
import { getUnion } from '@/utils/tools'
import mixin from './mixin'
export default {
name: 'SideMenu',
mixins: [mixin],
components: {
SideMenuItem,
CollapsedMenu,
},
props: {
menuList: {
type: Array,
default() {
return []
},
},
collapsed: {
type: Boolean,
},
theme: {
type: String,
default: 'light',
},
rootIconSize: {
type: Number,
default: 20,
},
iconSize: {
type: Number,
default: 16,
},
activeName: {
type: String,
default: '',
},
openNames: {
type: Array,
default: () => [],
},
},
data() {
return {
openedNames: [],
}
},
methods: {
handleSelect(name) {
this.$emit('on-select', name)
},
getOpenedNamesByActiveName(name) {
let names = this.$route.matched.map((item) => item.name).filter((item) => item !== name)
return names
},
},
computed: {
textColor() {
return this.theme === 'dark' ? '#fff' : '#495060'
},
},
watch: {
activeName(name) {
this.openedNames = this.getOpenedNamesByActiveName(name)
},
openNames(newNames) {
this.openedNames = newNames
},
openedNames() {
this.$nextTick(() => {
this.$refs.menu.updateOpened()
})
},
},
mounted() {
let openedNames = getUnion(this.openedNames, this.getOpenedNamesByActiveName(this.activeName))
this.openedNames = openedNames
},
}
</script>
<style lang="less">
@import './side-menu.less';
</style>

View File

@@ -0,0 +1,63 @@
<template>
<div class="terminal-box">
<Icon :class="iconclass" type="ios-radio" @click="show" />
<asyncModal ref="asyncModal" title="终端" top="30" :footer-hide="true">
<Terminal></Terminal>
</asyncModal>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Terminal from './terminal.vue'
export default {
components: {
Terminal
},
computed: {
...mapGetters({
isServerRun: 'isServerRun'
}),
iconclass() {
let curClass = 'terminal-icon ml10 '
if (this.isServerRun) {
curClass += ' run'
}
return curClass
}
},
methods: {
show() {
this.$refs['asyncModal'].show()
}
}
}
</script>
<style lang="less" scoped>
.terminal-box {
margin-top: 3px;
}
.terminal-icon {
color: #c5c8ce;
font-size: 22px;
cursor: pointer;
&.run {
animation: colorChange 0.4s infinite; /* 调用颜色变化动画 */
}
}
@keyframes colorChange {
0% {
color: #19be6b; /* 初始颜色 */
}
100% {
color: red; /* 返回到初始颜色 */
}
}
</style>

View File

@@ -0,0 +1,62 @@
<template>
<div class="content-view">
<div class="log-box">
<div class="pa5 flex" style="align-items: flex-end; justify-content: flex-end;">
<Button class="ml10" size="small" @click="reloadLog">重新加载日志</Button>
<Button type="error" size="small" @click="clearLog">清空日志</Button>
</div>
<div class="view-log-info" id="view-log-info" style="height:70vh;width: 100%;">{{ infoMsg }}</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import uiTool from '@/utils/uiTool'
export default {
data() {
return {}
},
mounted() {},
computed: {
...mapGetters({
infoMsg: 'infoMsg'
})
},
watch: {
infoMsg: {
handler() {
this.scrollEnd()
}
}
},
methods: {
clearLog() {
this.$store.commit('clearInfoMsg')
},
reloadLog() {
this.$store.dispatch('setInteverLog')
},
scrollEnd() {
setTimeout(() => {
let outerDiv = document.querySelector('#view-log-info')
if (outerDiv) {
outerDiv.scrollTop = outerDiv.scrollHeight + 5
}
}, 300)
}
}
}
</script>
<style lang="less" scoped>
.log-box {
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
width: 100%;
}
</style>

View File

@@ -0,0 +1,2 @@
import User from './user.vue'
export default User

View File

@@ -0,0 +1,12 @@
.user{
&-avator-dropdown{
cursor: pointer;
display: inline-block;
// height: 64px;
vertical-align: middle;
// line-height: 64px;
.ivu-badge-dot{
top: 16px;
}
}
}

View File

@@ -0,0 +1,68 @@
<template>
<div class="user-avator-dropdown">
<label class="loginName-box">{{userName}}</label>
<Dropdown>
<Avatar :src="typeof userAvator === 'string' ? userAvator : userIcon" />
<Icon :size="18" type="md-arrow-dropdown"></Icon>
<DropdownMenu slot="list">
<a @click="logout">
<DropdownItem name="logout">
<Icon type="md-exit" />
退出登录
</DropdownItem>
</a>
</DropdownMenu>
</Dropdown>
</div>
</template>
<script>
import './user.less'
import { mapMutations, mapActions } from 'vuex'
const userIcon = require("@/assets/images/administrato.png").default
export default {
name: 'User',
props: {
userName: String,
userAvator: {
type: [String, Object],
default: '',
},
},
data(){
return {
userIcon: userIcon
}
},
methods: {
...mapActions(['handleLogOut']),
logout() {
this.handleLogOut(this)
},
message() {
this.$router.push({
name: 'message_page',
})
},
},
}
</script>
<style lang="less" scoped>
.user-avator-dropdown {
position: absolute;
top: 0px;
right: 10px;
}
.loginName-box {
font-weight: bold;
color: #4b81d3;
margin-right: 10px;
}
</style>

View File

@@ -0,0 +1,2 @@
import Main from './main.vue'
export default Main

View File

@@ -0,0 +1,109 @@
.main {
.logo-con {
height: 64px;
padding: 10px;
padding-left: 0px;
color: white;
img {
width: auto;
display: block;
margin: 0 auto;
}
}
.header-con {
padding: 0px 10px;
width: 100%;
background: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
margin-bottom: 5px;
}
.main-content-con {
height: 100%;
overflow: hidden;
color: darkgray;
display: flex;
}
.main-layout-con {
display: flex;
display: -webkit-flex;
overflow: hidden;
}
.tag-nav-wrapper {
padding: 0;
height: 40px;
background: #f0f0f0;
}
.content-wrapper {
padding: 0px 0.05rem;
height: ~"calc(100% - 40px)";
display: flex;
display: -webkit-flex;
flex-direction: column;
overflow: auto;
}
.left-sider {
.ivu-layout-sider-children {
overflow-y: scroll;
margin-right: -10px;
}
}
}
.ivu-menu-item > i {
margin-right: 12px !important;
}
.ivu-menu-submenu > .ivu-menu > .ivu-menu-item > i {
margin-right: 8px !important;
}
.collased-menu-dropdown {
width: 100%;
margin: 0;
line-height: normal;
padding: 7px 0 6px 16px;
clear: both;
font-size: 12px !important;
white-space: nowrap;
list-style: none;
cursor: pointer;
transition: background 0.2s ease-in-out;
&:hover {
background: rgba(100, 100, 100, 0.1);
}
& * {
color: #515a6e;
}
.ivu-menu-item > i {
margin-right: 12px !important;
}
.ivu-menu-submenu > .ivu-menu > .ivu-menu-item > i {
margin-right: 8px !important;
}
}
.ivu-select-dropdown.ivu-dropdown-transfer {
max-height: 400px;
}
.police-box {
margin-left: 10px;
color: darkgoldenrod;
overflow: hidden;
height: 100%;
span {
margin: 0px 5px;
}
}

View File

@@ -0,0 +1,145 @@
<template>
<Layout style="height: 100%" class="main">
<Sider hide-trigger collapsible :width="256" :collapsed-width="64" v-model="collapsed" class="left-sider" :style="{overflow: 'hidden'}">
<div class="sidebar-brand" @click="goHome" v-if="!collapsed">
<img style="width:50px" :src="sysFormModel.logoUrl" />
<span class="ml10">{{sysFormModel.title}}</span>
</div>
<side-menu class="mt30" theme="dark" ref="sideMenu" :active-name="$route.name" :collapsed="collapsed" @on-select="turnToPage" :menu-list="menuList"> </side-menu>
</Sider>
<Content class="main-content-con">
<Layout class="main-layout-con">
<Header>
<headerBar class="header-con" @on-coll-change="collpasedChange" :collapsed="collapsed">
<Terminal></Terminal>
<user :userName="userName" :user-avator="userAvator || ''" />
</headerBar>
</Header>
<Layout>
<Content class="content-wrapper">
<router-view />
<loadFlower> </loadFlower>
<ABackTop :height="100" :bottom="80" :right="50" container=".content-wrapper"></ABackTop>
</Content>
</Layout>
</Layout>
</Content>
</Layout>
</template>
<script>
const { title } = require('../../config')
import SideMenu from './components/side-menu'
import HeaderBar from './components/header-bar'
import User from './components/user'
import ABackTop from './components/a-back-top'
import Fullscreen from './components/fullscreen'
import Language from './components/language'
import { mapGetters } from 'vuex'
import headerBar from './components/header-bar'
import loadFlower from '../load-flower/index'
import Terminal from './components/terminal'
import './main.less'
export default {
name: 'Main',
components: {
SideMenu,
HeaderBar,
Language,
Fullscreen,
User,
Terminal,
ABackTop,
loadFlower,
headerBar
},
data() {
return {
title,
collapsed: false,
isFullscreen: false
}
},
computed: {
...mapGetters({
sysFormModel: 'sysFormModel',
menuList: 'menuList',
tagRouter: 'tagRouter',
userName: 'userName',
userAvator: 'avatorImgPath'
}),
cacheList() {
return ['ParentView']
}
},
watch: {},
created() {
this.init()
},
methods: {
async init() {
await this.$store.dispatch('getSysTitle')
},
collpasedChange(collapsed) {
this.collapsed = collapsed
},
goHome() {
this.$router.push({ path: '/' })
},
turnToPage(route) {
let { name, params, query } = {}
if (typeof route === 'string') name = route
else {
name = route.name
params = route.params
query = route.query
}
if (name.indexOf('isTurnByHref_') > -1) {
window.open(name.split('_')[1])
return
}
this.$router.push({
name,
params,
query
})
},
handleCollapsedChange(state) {
this.collapsed = state
},
handleClick(item) {
this.turnToPage(item)
}
}
}
</script>
<style lang="less" scoped>
.shop-select {
z-index: 999999;
}
.sidebar-brand {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
text-align: center;
height: 60px;
line-height: 25px;
color: #fff;
font-size: 18px;
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,23 @@
<template>
<div class="table-head-tool ss">
<Button shape="circle" v-if="$route.meta.type==='功能'" icon="ios-undo" @click="goBack">返回</Button>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {}
},
created() {},
methods: {
goBack() {
this.$router.go(-1)
},
},
}
</script>
<style lang="less" scoped>
</style>