123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- <template>
- <div :class="{content: !fullScreen}">
- <!-- 全屏 -->
- <template v-if="fullScreen">
- <keep-alive>
- <router-view v-if="$route.meta.keepAlive" />
- </keep-alive>
- <router-view v-if="!$route.meta.keepAlive" />
- </template>
- <template v-else>
- <navbar :left="width">
- <template #tools>
- <!-- 判断按钮权限 -->
- <v-badge
- :value="bellMessage"
- bordered
- dot
- color="error"
- overlap
- >
- <v-btn
- fab
- x-small
- @click="drawer = true"
- >
- <v-icon size="24">mdi-bell-outline</v-icon>
- </v-btn>
- </v-badge>
- </template>
- </navbar>
- <div class="body" ref="body">
- <side class="stick" :style="`height: calc(100% - ${this.top}px)`" />
- <div class="view d-flex flex-column" :style="`padding-left: ${width}px;`">
- <div class="breadcrumbs_sticky">
- <div class=" d-flex align-center justify-space-between">
- <v-breadcrumbs :items="title" elevation="3">
- <template v-slot:item="{ item }">
- <span class="text" :class="{active: !item.disabled}" @click="toPath(item)">{{ item.text }}</span>
- </template>
- </v-breadcrumbs>
- <v-btn v-if="$route.meta.editModules" text color="primary" class="mr-5" @click="handleClickModules">{{ $t('common.moduleEditing') }}</v-btn>
- </div>
- <v-divider></v-divider>
- <!-- <div v-if="list.length && showChip">
- <scroll-tabs class="px-3" :items="list" @handleClick="$event => handleToHref(`${$event.name}${$event.id}`)"></scroll-tabs>
- <v-divider></v-divider>
- </div> -->
- </div>
- <div class="box pa-3 d-flex" :style="`width: calc(100vw - ${width}px); position: relative`">
- <m-knowledge v-if="showKnowledge"></m-knowledge>
- <!-- 避免容器因为文字影响 设置字体大小为0 -->
- <div class="box-content" style="font-size: 0;">
- <keep-alive>
- <router-view v-if="$route.meta.keepAlive" />
- </keep-alive>
- <router-view v-if="!$route.meta.keepAlive" />
- </div>
- </div>
- </div>
- <v-navigation-drawer
- v-model="drawer"
- absolute
- temporary
- right
- width="400"
- style="z-index: var(--zIndex-drawers);"
- >
- <the-drawer v-if="drawer" @checkRead="getMessageUnRead"></the-drawer>
- </v-navigation-drawer>
- </div>
- </template>
- </div>
- </template>
- <script>
- // import ScrollTabs from '@/components/ScrollTabs'
- import Navbar from '@/components/Header/navbar.vue'
- import Side from '@/components/Side/index.vue'
- import { mapGetters } from 'vuex'
- import TheDrawer from './components/bellDrawer.vue'
- // import cloneDeep from 'lodash/cloneDeep'
- import MKnowledge from '@/components/Knowledge'
- // import {
- // getMessageList
- // } from '@/api/system'
- const showAI = [
- '/data-book/data-metadata',
- '/data-book/data-resource',
- '/data-book/data-model',
- '/data-book/data-indicator',
- '/data-book/data-standard',
- '/data-book/data-label'
- ]
- export default {
- name: 'layoutIndex',
- components: { Navbar, Side, TheDrawer, MKnowledge },
- data () {
- return {
- showKnowledge: true,
- drawer: false,
- width: 230,
- selectTabs: 0,
- list: [],
- scrollTop: null,
- showChip: true,
- top: 0,
- bellMessage: false,
- timer: null
- }
- },
- computed: {
- ...mapGetters(['lang', 'userInfo']),
- fullScreen () {
- return this.$route.meta.fullScreen
- },
- title () {
- const route = this.$route.matched.map((item, index) => {
- if (item.path === this.$route.matched[index - 1]?.path) return false
- const text = this.lang === 'zh' ? item.meta.title : item.meta.enName
- const obj = {
- text,
- to: item.path
- }
- if (!item.meta?.allowClick) {
- obj.disabled = true
- obj.link = false
- }
- return obj
- }).filter(e => e)
- route[route.length - 1].disabled = true
- route[route.length - 1].link = true
- // route.unshift({ text: '首页', to: '/home' })
- return route
- }
- },
- watch: {
- $route: {
- handler: function (val) {
- const item = val.matched.find(e => showAI.includes(e.path))
- this.showKnowledge = !!item
- this.selectTabs = 0
- this.list = []
- const roles = val.meta.roles.filter(e => e.active === '1').sort((a, b) => a.sort - b.sort)
- if (!['/home'].includes(val.path) && roles && roles.length > 1) {
- this.list = roles.map(e => ({ label: e.label, name: e.name, id: e.id }))
- }
- },
- immediate: true
- }
- },
- created () {
- this.$eventBus.$on('scroll-top', (num) => {
- // console.log('scroll-top', num)
- this.scrollTop = num
- })
- this.$eventBus.$on('show-chip', (show) => {
- // console.log('show-chip', show)
- this.showChip = show
- })
- // this.getMessageUnRead()
- // if (this.timer) {
- // clearInterval(this.timer)
- // }
- // this.timer = setInterval(() => {
- // this.getMessageUnRead()
- // }, 10000)
- },
- mounted () {
- if (!this.$refs.body) return
- this.top = this.$refs.body.offsetTop
- window.addEventListener('scroll', this.handleScroll)
- },
- beforeDestroy () {
- clearInterval(this.timer)
- if (!this.$refs.body) return
- // 在组件销毁前移除滚动事件监听
- window.removeEventListener('scroll', this.handleScroll)
- },
- methods: {
- handleScroll () {
- if (!this.list.length) return
- this.list.forEach((section, index) => {
- const selector = document.getElementById(section.name + section.id)
- if (!selector) return
- if (window.scrollY - selector.offsetTop > -400) {
- this.selectTabs = index
- }
- })
- },
- handleToHref (id) {
- // 获取需要跳转到的元素
- const selector = document.getElementById(id)
- if (!selector) return
- // 使用scrollIntoView方法滚动到指定元素
- // selector.scrollIntoView({ behavior: 'smooth', block: 'center' })
- window.scrollTo({
- top: selector.offsetTop - (this.scrollTop ? this.scrollTop : 188), // 滚动到距离顶部280的位置
- behavior: 'smooth' // 平滑滚动
- })
- },
- handleToggle () {
- this.width = 300 - this.width
- },
- handleClick () {
- const path = this.$route.path
- this.$router.push(`${path}/edit`)
- },
- toPath ({ disabled, to }) {
- if (disabled) {
- event.preventDefault()
- return
- }
- this.$router.push(to)
- },
- handleClickModules () {
- this.$emit('$HANDLE_EDIT_MODULES')
- }
- // 查询是否存在未读消息
- // async getMessageUnRead () {
- // try {
- // const { data } = await getMessageList({ readState: 0, userId: this.userInfo.id })
- // this.bellMessage = data.total > 0
- // } catch (error) {
- // this.$snackbar.error(error)
- // }
- // }
- }
- }
- </script>
- <style lang="scss" scoped>
- .stick {
- position: fixed;
- overflow: auto;
- background: #FFF;
- transition: .1s;
- /* 针对 WebKit 浏览器(如 Chrome 和 Safari)使用伪元素 */
- &::-webkit-scrollbar {
- width: 0;
- }
- overflow: -moz-scrollbars-none; /* 针对 Firefox */
- // -ms-overflow-style: none; /* 针对 IE 10+ */
- scrollbar-width: none; /* 针对 Firefox */
- -webkit-overflow-scrolling: touch; /* 针对 iOS Safari */
- }
- .breadcrumbs_sticky {
- background: #FFF;
- z-index: var(--zIndex-breadcrumbs);
- border-left: 1px solid #eaecef;
- }
- .content {
- height: 100%;
- display: flex;
- flex-direction: column;
- flex: 1;
- .body {
- position: relative;
- overflow: hidden;
- height: 0;
- flex: 1;
- display: flex;
- .view {
- background: #f0f2f5;
- box-sizing: border-box;
- .box {
- height: 0;
- flex: 1;
- // overflow-x: hidden;
- &-content {
- width: 100%;
- min-height: 100%;
- position: relative;
- overflow-y: auto;
- overflow-x: hidden;
- }
- }
- }
- }
- }
- .text {
- color: #999;
- font-size: 14px;
- &.active {
- color: #1867c0;
- cursor: pointer;
- }
- }
- // .item {
- // padding: 0 8px;
- // cursor: auto;
- // &:focus {
- // color: inherit !important;
- // }
- // }
- </style>
|