mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-07 09:56:48 +08:00
feat(layout): 菜单重构布局并调整样式
- 修改了 AppMain组件的最小高度和样式 - 更新了 Sidebar 组件的背景色和内边距 -调整了 Logo 组件的宽度 - 重构了 layout 目录的结构 - 优化了路由配置
This commit is contained in:
@@ -349,7 +349,8 @@ h3 {
|
|||||||
#app .sidebar-container {
|
#app .sidebar-container {
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
width: 210px !important;
|
width: 210px !important;
|
||||||
background-color: #304156;
|
background-color: #f0f4fa;
|
||||||
|
padding: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#app {
|
#app {
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
transition: margin-left .28s;
|
transition: margin-left 0.28s;
|
||||||
margin-left: $sideBarWidth;
|
margin-left: $sideBarWidth;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -10,10 +9,11 @@
|
|||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: width 0.28s;
|
transition: width 0.28s;
|
||||||
width: $sideBarWidth !important;
|
width: $sideBarWidth !important;
|
||||||
background-color: $menuBg;
|
background-color: #f0f4fa;
|
||||||
|
padding: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
font-size: 0px;
|
font-size: 12px;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -71,11 +71,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active>.el-submenu__title {
|
.is-active > .el-submenu__title {
|
||||||
color: $subMenuActiveText !important;
|
color: $subMenuActiveText !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .nest-menu .el-submenu>.el-submenu__title,
|
& .nest-menu .el-submenu > .el-submenu__title,
|
||||||
& .el-submenu .el-menu-item {
|
& .el-submenu .el-menu-item {
|
||||||
min-width: $sideBarWidth !important;
|
min-width: $sideBarWidth !important;
|
||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
.el-submenu {
|
.el-submenu {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&>.el-submenu__title {
|
& > .el-submenu__title {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
@@ -126,8 +126,8 @@
|
|||||||
|
|
||||||
.el-menu--collapse {
|
.el-menu--collapse {
|
||||||
.el-submenu {
|
.el-submenu {
|
||||||
&>.el-submenu__title {
|
& > .el-submenu__title {
|
||||||
&>span {
|
& > span {
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: transform .28s;
|
transition: transform 0.28s;
|
||||||
width: $sideBarWidth !important;
|
width: $sideBarWidth !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.withoutAnimation {
|
.withoutAnimation {
|
||||||
|
|
||||||
.main-container,
|
.main-container,
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
transition: none;
|
transition: none;
|
||||||
@@ -174,13 +173,13 @@
|
|||||||
|
|
||||||
// when menu collapsed
|
// when menu collapsed
|
||||||
.el-menu--vertical {
|
.el-menu--vertical {
|
||||||
&>.el-menu {
|
& > .el-menu {
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nest-menu .el-submenu>.el-submenu__title,
|
.nest-menu .el-submenu > .el-submenu__title,
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
&:hover {
|
&:hover {
|
||||||
// you can use $subMenuHover
|
// you can use $subMenuHover
|
||||||
@@ -189,7 +188,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the scroll bar appears when the subMenu is too long
|
// the scroll bar appears when the subMenu is too long
|
||||||
>.el-menu--popup {
|
> .el-menu--popup {
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
|
|||||||
@@ -18,24 +18,7 @@ $width-list: 5 8 10 20 30 40 50 60 65 70 80 86 100 110 120 140 150 155 160 180 1
|
|||||||
|
|
||||||
// 内外边距列表
|
// 内外边距列表
|
||||||
$distance-list: 0 1 2 5 6 8 9 10 12 15 20 25 30 35 40 45 50 60 80 86 90 100 120 140;
|
$distance-list: 0 1 2 5 6 8 9 10 12 15 20 25 30 35 40 45 50 60 80 86 90 100 120 140;
|
||||||
$distance-class-list: m,
|
$distance-class-list: m, mv, mh, mt, ml, mr, mb, p, pv, ph, pt, pl, pr, pb, top, left, right, bottom;
|
||||||
mv,
|
|
||||||
mh,
|
|
||||||
mt,
|
|
||||||
ml,
|
|
||||||
mr,
|
|
||||||
mb,
|
|
||||||
p,
|
|
||||||
pv,
|
|
||||||
ph,
|
|
||||||
pt,
|
|
||||||
pl,
|
|
||||||
pr,
|
|
||||||
pb,
|
|
||||||
top,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
bottom;
|
|
||||||
|
|
||||||
//圆角弧度
|
//圆角弧度
|
||||||
$radius: 1 2 3 4 5 6 7 8 9 10 12 13 14 15 18 20 50 100;
|
$radius: 1 2 3 4 5 6 7 8 9 10 12 13 14 15 18 20 50 100;
|
||||||
@@ -54,7 +37,7 @@ $menuHover: #263445;
|
|||||||
$subMenuBg: #1f2d3d;
|
$subMenuBg: #1f2d3d;
|
||||||
$subMenuHover: #001528;
|
$subMenuHover: #001528;
|
||||||
|
|
||||||
$sideBarWidth: 210px;
|
$sideBarWidth: 270px;
|
||||||
|
|
||||||
// the :export directive is the magic sauce for webpack
|
// the :export directive is the magic sauce for webpack
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import layout from '@/views/app/layout/index.vue'
|
import layout from '@/views/app/layout/layout.vue'
|
||||||
import redirect from '@/views/app/redirect/index.vue'
|
import redirect from '@/views/app/redirect/index.vue'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
@@ -135,7 +135,7 @@ export default [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.app-main {
|
.app-main {
|
||||||
/*50 = navbar */
|
/*50 = navbar */
|
||||||
min-height: calc(100vh - 50px);
|
min-height: calc(100vh - 250px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.fixed-header + .app-main {
|
.fixed-header + .app-main {
|
||||||
padding-top: 50px;
|
//padding-top: 50px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default {
|
|||||||
|
|
||||||
.sidebar-logo-container {
|
.sidebar-logo-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
/*background: #2b2f3a;*/
|
/*background: #2b2f3a;*/
|
||||||
|
|||||||
335
src/views/app/layout/components/Sidebar/Sidebar.vue
Normal file
335
src/views/app/layout/components/Sidebar/Sidebar.vue
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="{ 'has-logo': showLogo }" class="sidebar-container">
|
||||||
|
<div class="sidebar-layout">
|
||||||
|
<!-- Left side - Primary menu -->
|
||||||
|
<div class="primary-menu">
|
||||||
|
<logo class="logo" v-if="showLogo" :collapse="isCollapse" />
|
||||||
|
<div
|
||||||
|
v-for="route in menuList"
|
||||||
|
:key="route.path"
|
||||||
|
class="primary-menu-item"
|
||||||
|
:class="{ active: activeParent === route.path }"
|
||||||
|
@click="selectParentMenu(route)"
|
||||||
|
>
|
||||||
|
<svg t="1745323232253" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4148" width="24" height="24">
|
||||||
|
<path
|
||||||
|
d="M523.73504 319.29344h-204.8c-16.896 0-30.72-13.824-30.72-30.72s13.824-30.72 30.72-30.72h204.8c16.896 0 30.72 13.824 30.72 30.72s-13.824 30.72-30.72 30.72zM605.65504 452.41344h-286.72c-16.896 0-30.72-13.824-30.72-30.72s13.824-30.72 30.72-30.72h286.72c16.896 0 30.72 13.824 30.72 30.72s-13.824 30.72-30.72 30.72z"
|
||||||
|
fill="#FFFFFF"
|
||||||
|
p-id="4149"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M706.56 870.4H317.44c-67.584 0-122.88-55.296-122.88-122.88V276.48c0-67.584 55.296-122.88 122.88-122.88h389.12c67.584 0 122.88 55.296 122.88 122.88v471.04c0 67.584-55.296 122.88-122.88 122.88z"
|
||||||
|
fill="#3889FF"
|
||||||
|
p-id="4150"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M358.4 153.6h61.44v716.8h-61.44zM545.20832 153.6h61.44v215.04h-61.44zM653.81376 153.6h61.44v215.04h-61.44z"
|
||||||
|
fill="#FFFFFF"
|
||||||
|
p-id="4151"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M673.67936 312.32l-21.71904-21.71904a30.72 30.72 0 0 0-43.44832 0L586.78272 312.32l-32.58368 32.58368a30.72 30.72 0 1 0 43.44832 43.44832l10.86464-10.86464a30.72 30.72 0 0 1 43.44832 0l10.86464 10.86464a30.72 30.72 0 1 0 43.44832-43.44832L673.67936 312.32z"
|
||||||
|
fill="#FFFFFF"
|
||||||
|
p-id="4152"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
<!-- <svg-icon v-if="route.meta && route.meta.icon" :icon-class="route.meta.icon" />-->
|
||||||
|
<span class="menu-title">{{ route.meta ? route.meta.title : '' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right side - Submenu -->
|
||||||
|
<div class="submenu-container" v-if="activeParent && currentSubmenu.length">
|
||||||
|
<!-- <div class="submenu-header">-->
|
||||||
|
<!-- <span>{{ currentParentTitle }}</span>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||||
|
<div class="submenu-list">
|
||||||
|
<pre style="font-size: 12px; padding: 10px; display: none;">{{ JSON.stringify(currentSubmenu, null, 2) }}</pre>
|
||||||
|
<div
|
||||||
|
v-for="subItem in currentSubmenu"
|
||||||
|
:key="subItem.path"
|
||||||
|
class="submenu-item"
|
||||||
|
:class="{ active: activeMenu === subItem.path }"
|
||||||
|
@click="navigateTo(subItem.path)"
|
||||||
|
>
|
||||||
|
<!-- <svg-icon v-if="subItem.meta && subItem.meta.icon" :icon-class="subItem.meta.icon" />-->
|
||||||
|
<span>{{ subItem.meta ? subItem.meta.title : subItem.name || 'Unnamed Item' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapActions } from 'vuex'
|
||||||
|
import Logo from './Logo'
|
||||||
|
import variables from '@/assets/sass/variables.scss'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { Logo },
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['sidebar', 'sidebarList']),
|
||||||
|
routes() {
|
||||||
|
return this.$router.options.routes
|
||||||
|
},
|
||||||
|
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
|
||||||
|
},
|
||||||
|
variables() {
|
||||||
|
return variables
|
||||||
|
},
|
||||||
|
isCollapse() {
|
||||||
|
return !this.sidebar.opened
|
||||||
|
},
|
||||||
|
currentSubmenu() {
|
||||||
|
if (!this.activeParent) return []
|
||||||
|
const parent = this.menuList.find(item => item.path === this.activeParent)
|
||||||
|
console.log('Parent found:', parent)
|
||||||
|
console.log('Children:', parent ? parent.children : 'No children')
|
||||||
|
return parent ? parent.children || [] : []
|
||||||
|
},
|
||||||
|
currentParentTitle() {
|
||||||
|
if (!this.activeParent) return ''
|
||||||
|
const parent = this.menuList.find(item => item.path === this.activeParent)
|
||||||
|
return parent && parent.meta ? parent.meta.title : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
menuList: [],
|
||||||
|
activeParent: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
setSidebarList: 'app/setSidebarList'
|
||||||
|
}),
|
||||||
|
formatList(menu, state, parentPath = null) {
|
||||||
|
menu.map(item => {
|
||||||
|
if (parentPath) {
|
||||||
|
item.path = '/' + parentPath + '/' + item.url
|
||||||
|
} else {
|
||||||
|
item.path = item.url
|
||||||
|
}
|
||||||
|
if (item.otherInfo1 == 0) {
|
||||||
|
item.name = item.menuName
|
||||||
|
item.alwaysShow = state
|
||||||
|
item.meta = {
|
||||||
|
title: item.menuName,
|
||||||
|
icon: item.img
|
||||||
|
}
|
||||||
|
if (item.children != null) {
|
||||||
|
this.formatList(item.children, undefined, item.path)
|
||||||
|
} else {
|
||||||
|
item.children = []
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.children = []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return menu
|
||||||
|
},
|
||||||
|
selectParentMenu(route) {
|
||||||
|
this.activeParent = route.path
|
||||||
|
|
||||||
|
// If this parent has children, don't navigate
|
||||||
|
if (route.children && route.children.length > 0) {
|
||||||
|
// Optionally navigate to the first child
|
||||||
|
// this.navigateTo(route.children[0].path)
|
||||||
|
} else {
|
||||||
|
// If no children, navigate to the parent route
|
||||||
|
this.navigateTo(route.path)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigateTo(path) {
|
||||||
|
if (path && path !== this.$route.path) {
|
||||||
|
this.$router.push(path)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
findParentForCurrentRoute() {
|
||||||
|
const currentPath = this.$route.path
|
||||||
|
|
||||||
|
// Try to find the parent menu that contains the current route
|
||||||
|
for (const parent of this.menuList) {
|
||||||
|
// Check if current route is the parent itself
|
||||||
|
if (parent.path === currentPath) {
|
||||||
|
this.activeParent = parent.path
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if current route is one of the children
|
||||||
|
if (parent.children && parent.children.length) {
|
||||||
|
const childMatch = parent.children.find(child => child.path === currentPath || currentPath.startsWith(child.path + '/'))
|
||||||
|
|
||||||
|
if (childMatch) {
|
||||||
|
this.activeParent = parent.path
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no match found, default to first menu item if available
|
||||||
|
if (this.menuList.length > 0 && !this.activeParent) {
|
||||||
|
this.activeParent = this.menuList[0].path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (sessionStorage.token !== 'MockToken') {
|
||||||
|
// 获取路由数据
|
||||||
|
let data = this.$store.state.app.sidebarList
|
||||||
|
|
||||||
|
// 只获取顶级路由,不需要硬编码路径
|
||||||
|
// 通过检查路由结构来确定顶级菜单
|
||||||
|
const topLevelRoutes = data.filter(route => {
|
||||||
|
// 如果路由有 meta 和 children,则认为它是顶级菜单
|
||||||
|
return route.meta && route.path && !route.hidden
|
||||||
|
})
|
||||||
|
|
||||||
|
this.menuList = topLevelRoutes
|
||||||
|
} else {
|
||||||
|
// 从路由配置中获取顶级路由
|
||||||
|
const topLevelRoutes = this.routes.filter(route => {
|
||||||
|
// 只显示有 meta 和 children 的路由,并且不是隐藏的
|
||||||
|
return route.meta && route.children && !route.hidden
|
||||||
|
})
|
||||||
|
|
||||||
|
this.menuList = topLevelRoutes
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据当前路由设置活动的父菜单
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.findParentForCurrentRoute()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route() {
|
||||||
|
// Update active parent when route changes
|
||||||
|
this.findParentForCurrentRoute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.sidebar-container {
|
||||||
|
height: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-right: 1px solid #e6e6e6;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-layout {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-menu {
|
||||||
|
width: 95px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #ebeef2;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 0 10px;
|
||||||
|
text-align: center;
|
||||||
|
.logo {
|
||||||
|
margin-bottom: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-menu-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 58px;
|
||||||
|
width: 68px;
|
||||||
|
padding: 10px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #606266;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
color: #000;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #f8f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-title {
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 23px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-header {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
padding: 0 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-list {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenu-item {
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
padding: 0 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #000;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
color: #000;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #f8f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
export { default as Navbar } from './Navbar'
|
export { default as Navbar } from './Navbar'
|
||||||
export { default as Sidebar } from './Sidebar'
|
export { default as Sidebar } from './Sidebar/Sidebar'
|
||||||
export { default as AppMain } from './AppMain'
|
export { default as AppMain } from './AppMain'
|
||||||
|
|||||||
97
src/views/app/layout/layout.vue
Normal file
97
src/views/app/layout/layout.vue
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-wrapper">
|
||||||
|
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
||||||
|
<sidebar class="sidebar-container" />
|
||||||
|
<div class="main-container">
|
||||||
|
<app-main />
|
||||||
|
</div>
|
||||||
|
<!--<app-main v-else />-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { AppMain } from './components'
|
||||||
|
import Sidebar from './components/Sidebar/Sidebar.vue'
|
||||||
|
import ResizeMixin from './mixin/ResizeHandler'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Layout',
|
||||||
|
components: {
|
||||||
|
// Navbar,
|
||||||
|
Sidebar,
|
||||||
|
AppMain
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
type: process.env.VUE_APP_FLAG
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixins: [ResizeMixin],
|
||||||
|
computed: {
|
||||||
|
sidebar() {
|
||||||
|
return this.$store.state.app.sidebar
|
||||||
|
},
|
||||||
|
device() {
|
||||||
|
return this.$store.state.app.device
|
||||||
|
},
|
||||||
|
fixedHeader() {
|
||||||
|
return this.$store.state.settings.fixedHeader
|
||||||
|
},
|
||||||
|
classObj() {
|
||||||
|
return {
|
||||||
|
hideSidebar: !this.sidebar.opened,
|
||||||
|
openSidebar: this.sidebar.opened,
|
||||||
|
withoutAnimation: this.sidebar.withoutAnimation,
|
||||||
|
mobile: this.device === 'mobile'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClickOutside() {
|
||||||
|
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/assets/sass/mixin.scss';
|
||||||
|
@import '~@/assets/sass/variables.scss';
|
||||||
|
|
||||||
|
.app-wrapper {
|
||||||
|
@include clearfix;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
&.mobile.openSidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.drawer-bg {
|
||||||
|
background: #000;
|
||||||
|
opacity: 0.3;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 9;
|
||||||
|
width: calc(100% - #{$sideBarWidth});
|
||||||
|
transition: width 0.28s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hideSidebar .fixed-header {
|
||||||
|
width: calc(100% - 54px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile .fixed-header {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'dify',
|
name: 'dify',
|
||||||
data() {
|
data() {
|
||||||
@@ -13,9 +12,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container"></div>
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -74,4 +74,4 @@ export default {
|
|||||||
<el-empty v-else />
|
<el-empty v-else />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ module.exports = {
|
|||||||
target: 'http://localhost:3000',
|
target: 'http://localhost:3000',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
onProxyRes: (proxyRes, req, res) => {
|
onProxyRes: (proxyRes, req, res) => {
|
||||||
delete proxyRes.headers['x-frame-options'];
|
delete proxyRes.headers['x-frame-options']
|
||||||
},
|
},
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
// '^/app': '/'
|
// '^/app': '/'
|
||||||
@@ -49,7 +49,7 @@ module.exports = {
|
|||||||
target: 'http://localhost:3000',
|
target: 'http://localhost:3000',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
onProxyRes: (proxyRes, req, res) => {
|
onProxyRes: (proxyRes, req, res) => {
|
||||||
delete proxyRes.headers['x-frame-options'];
|
delete proxyRes.headers['x-frame-options']
|
||||||
},
|
},
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
// '^/_next': '/'
|
// '^/_next': '/'
|
||||||
|
|||||||
Reference in New Issue
Block a user