router ==> index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// import cookie from 'js-cookie'
import Home from '../views/index'
import Error from '../views/error/index.vue'
import MessageCenter from '../views/message-center/center.vue'
import HelpCenter from '../views/help-center/index.vue'
import MessageCenterDetail from '../views/message-center/message-details.vue'
import MessageWrapper from '../views/message-center/index.vue'
// import cookieKeys from '@/const/cookie-keys'
import {passWithouTokenValidate} from '@/utils/token'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/error',
name: 'error',
component: Error,
},
{ //嵌套路由写法
path: '/main/message',
name: 'messageWrapper',
component: MessageWrapper,
children: [
{
path: '/',
name: 'messageCenter',
component: MessageCenter,
},
{
path: 'details/:id',
name: 'messageCenterDetail',
component: MessageCenterDetail,
props: true,
},
],
},
{
path: '/main/help-center',
name: 'helpCenter',
component: HelpCenter,
},
{
path: '&',
name: 'Error',
component: Error,
},
]
const router = new VueRouter({
routes,
mode: 'hash',
})
router.beforeEach((to, from, next) => {
// 不需要做重定向跳转
if (passWithouTokenValidate(to)) {
return next()
}
next()
})
export default router
嵌套路由 文件夹以及对应的文件情况

index.vue
<template>
<div class="message-center">
<div class="left-wrapper">
<vui-tag-view
:menu="messageTypeList"
ref="menuTitle"
menuType="tree"
:props="menuProps"
:showTags="false"
@node-click="onNodeClick"
/>
</div>
<div class="right-wrapper">
<router-view :activeName="activeName"></router-view>
</div>
</div>
</template>
<script>
import {utils} from '@vv-package/utils/lib'
import {mapGetters, mapState} from 'vuex'
import {
tableConfig,
getTableDataHeader,
messageTypeList,
readStatus_hadRead,
barsData,
} from './config'
import {getMessages, markReadedAll} from '@/services/deepexi-cloud'
import pick from 'lodash/pick'
const tableConfigObject = tableConfig()
export default {
data() {
return {
dataPath: 'payload.content',
totalPath: 'payload.totalElements',
pageSizeName: 'size',
pageNumName: 'page',
tableData: {
...tableConfigObject.tableData,
},
query: {},
activeName: messageTypeList[0].value,
messageTypeList,
tableBodyMaxHeight: 0,
menuProps: {
label: 'label',
count: 'count',
id: 'id',
},
barsData: [],
}
},
computed: {
...mapState('notification', ['unReadCount']),
...mapGetters(['token', 'userId', 'tenantId', 'user']),
},
watch: {
unReadCount(val, oval) {
// 监听导航栏数据展示,更新页面数据
if (val.toString() !== oval.toString() && this.user && this.user.userId) {
this.$refs.tableCommon && this.$refs.tableCommon.refreshData()
}
},
user: {
handler(val, oval) {
if (val && val !== oval && val.userId) {
// 由于页面初始化时,可能还未获取到user,需要在这里重新获取
this.init()
}
},
},
},
created() {
this.barsData = barsData
},
mounted() {
if (this.user && this.user.userId) {
this.$nextTick(() => {
this.init()
})
}
this.$nextTick(() => {
this.tableBodyMaxHeight = utils.getTableBobyHeight() - 70
})
},
methods: {
handleBtnClick(comData) {
this[comData.funName](comData)
},
onNodeClick(data) {
this.activeName = data.value
if (this.$route.path === '/main/message') {
return
}
this.$router.push('/main/message')
},
cellClassName({row}) {
if (row.readStatus === readStatus_hadRead) {
return 'opacity-low'
}
return
},
init() {
this.activeName = messageTypeList[0].value
this.tableData.header = getTableDataHeader(this)
this.query = pick(this.user, ['userId', 'admin'])
this.query.registerTime = this.user.createdTime
this.getMessageCount()
this.$refs.tableCommon && this.$refs.tableCommon.refreshData()
},
updateUnReadCount(val) {
this.$store.commit('notification/unReadCount', val ? val : '')
},
getMessages(params) {
return getMessages({...this.query, ...params})
},
async getMessageCount() {
// 获取各类型消息数量, 受限于接口,这里通过获取消息列表(传类型)的length作为数量展示
for (let i = 0; i < messageTypeList.length; i++) {
const res = await this.getMessages({
type: messageTypeList[i].bizIdentification,
})
this.$refs.menuTitle.setCount(
this.messageTypeList[i].id,
res.payload.totalElements
)
}
},
markReadedAll() {
this.barsData[0].isShowLoading = true
this.barsData[0].isActive = true
markReadedAll({...this.query, userId: this.user.userId})
.then(() => {
this.messageList = []
// 默认操作成功,未读列表更新为0
this.updateUnReadCount('')
this.$vui_message({
type: 'success',
message: '操作成功',
})
})
.finally(() => {
this.barsData[0].isShowLoading = false
this.barsData[0].isActive = false
// 重新获取数据, 这里监听了导航栏数据变动,不需要主动更新列表
})
},
},
}
</script>
center.vue
<template>
<div class="message-center">
<div class="right-wrapper">
<vui-toolbar
:bars-data="barsData"
:column="4"
:handle-click="handleBtnClick"
:last-set-right="false"
class="vui-todo-toolbar-top"
type="tool"
/>
<vui-table-common
id="tableId"
ref="tableCommon"
v-model="tableData"
:axios-config="axiosConfig"
:data-default-path="dataPath"
:page-size-name="pageSizeName"
:page-num-name="pageNumName"
:data-total-path="totalPath"
data-src="fakeUrl"
:autoHandleSearch="false"
:is-selection="false"
:cellClassName="cellClassName"
:max-height="tableBodyMaxHeight"
style="margin-top: 16px;"
>
<!-- slot 自定义应用名称 -->
<template slot-scope="{scope}" slot="subject">
<div class="app-name-wrapper">
<a @click="routerLinkTodetail(scope)">{{ scope.subject }}</a>
</div>
</template>
</vui-table-common>
</div>
</div>
</template>
<script>
import {utils} from '@vv-package/utils/lib'
import {mapGetters, mapState} from 'vuex'
import {
tableConfig,
getTableDataHeader,
messageTypeList,
readStatus_hadRead,
barsData,
} from './config'
import {
getMessages,
getMessagesUrl,
markReadedAll,
} from '@/services/deepexi-cloud'
import pick from 'lodash/pick'
import {stringify} from 'qs'
const tableConfigObject = tableConfig()
export default {
props: {
activeName: {
type: String,
default: '',
},
},
data() {
return {
dataPath: 'payload.content',
totalPath: 'payload.totalElements',
pageSizeName: 'size',
pageNumName: 'page',
tableData: {
...tableConfigObject.tableData,
},
query: {},
messageTypeList,
tableBodyMaxHeight: 0,
menuProps: {
label: 'label',
count: 'count',
id: 'id',
},
barsData: [],
}
},
computed: {
...mapState('notification', ['unReadCount']),
...mapGetters(['token', 'userId', 'tenantId', 'user']),
axiosConfig() {
return config => {
config.headers.Authorization = `Bearer ${this.token}`
let target = messageTypeList.find(i => i.value === this.activeName)
let q = stringify(this.query)
if (target.value !== messageTypeList[0].value)
q += `&type=${target.bizIdentification}`
config.url = `${getMessagesUrl()}?${q}&tenantId=${this.tenantId}`
return config
}
},
},
watch: {
unReadCount(val, oval) {
// 监听导航栏数据展示,更新页面数据
if (val.toString() !== oval.toString() && this.user && this.user.userId) {
this.$refs.tableCommon && this.$refs.tableCommon.refreshData()
}
},
activeName: {
handler(val, oval) {
if (val && val !== oval && this.user && this.user.userId) {
this.tableData.page = tableConfigObject.tableData.page
this.$nextTick(() => {
this.$refs.tableCommon && this.$refs.tableCommon.refreshData()
})
}
},
},
user: {
handler(val, oval) {
if (val && val !== oval && val.userId) {
// 由于页面初始化时,可能还未获取到user,需要在这里重新获取
this.init()
}
},
},
},
created() {
this.barsData = barsData
},
mounted() {
if (this.user && this.user.userId) {
this.$nextTick(() => {
this.init()
})
}
this.$nextTick(() => {
this.tableBodyMaxHeight = utils.getTableBobyHeight() - 70
})
},
methods: {
handleBtnClick(comData) {
this[comData.funName](comData)
},
cellClassName({row}) {
if (row.readStatus === readStatus_hadRead) {
return 'opacity-low'
}
return
},
init() {
this.activeName = messageTypeList[0].value
this.tableData.header = getTableDataHeader(this)
this.query = pick(this.user, ['userId', 'admin'])
this.query.registerTime = this.user.createdTime
this.getMessageCount()
this.$refs.tableCommon && this.$refs.tableCommon.refreshData()
},
updateUnReadCount(val) {
this.$store.commit('notification/unReadCount', val ? val : '')
},
getMessages(params) {
return getMessages({...this.query, ...params})
},
async getMessageCount() {
// 获取各类型消息数量, 受限于接口,这里通过获取消息列表(传类型)的length作为数量展示
// for (let i = 0; i < messageTypeList.length; i++) {
// const res = await this.getMessages({
// type: messageTypeList[i].bizIdentification,
// })
// console.log(res)
// // this.$nextTick(() => {
// // this.$refs.menuTitle.setCount(
// // this.messageTypeList[i].id,
// // res.payload.totalElements
// // )
// // })
// }
},
markReadedAll() {
this.barsData[0].isShowLoading = true
this.barsData[0].isActive = true
markReadedAll({...this.query, userId: this.user.userId})
.then(() => {
this.messageList = []
// 默认操作成功,未读列表更新为0
this.updateUnReadCount('')
this.$vui_message({
type: 'success',
message: '操作成功',
})
})
.finally(() => {
this.barsData[0].isShowLoading = false
this.barsData[0].isActive = false
// 重新获取数据, 这里监听了导航栏数据变动,不需要主动更新列表
})
},
routerLinkTodetail(item) {
this.$router.push({
path: `/main/message/details/${item.id}`,
})
// 这里需要更新详情内容的状态,更新未读列表状态, 自动标记的,不需要前端调用接口
},
},
}
</script>
message-details.vue
<template>
<div class="message-details" v-loading="pageLoading">
<div>
<div class="msg-header">
<div class="msg-details-title">
<div class="title-text">{{ content.subject }}</div>
<div class="line"></div>
</div>
<div class="msg-info">
<div class="msg-details-time">
{{ content.createDate | formatterTime }}
</div>
<div class="msg-details-type">
{{ content.bizIdentification | getMsgType }}
</div>
</div>
</div>
<div class="msg-content markdown-body" v-html="content.content"></div>
<div class="pre-next-nav">
<div class="pre btn-item">
<div class="btn-inner" v-show="preItem">
<vui-button text @click="handleClick(preItem)" class="btn"
><i class="vui-icon-arrow-pagination-left"></i>上一条</vui-button
>
<span class="nav-info" :title="preItem && preItem.subject">{{
preItem && preItem.subject
}}</span>
</div>
</div>
<div class="next btn-item">
<div class="btn-inner" v-show="nextItem">
<span class="nav-info" :title="nextItem && nextItem.subject">{{
nextItem && nextItem.subject
}}</span>
<vui-button text @click="handleClick(nextItem)" class="btn"
>下一条
<i class="vui-icon-arrow-pagination-right"></i>
</vui-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {messageTypeList, breadcrumbData, formatDate} from './config'
import {mapGetters} from 'vuex'
import {getMessages, getMessageDetail} from '@/services/deepexi-cloud'
import pick from 'lodash/pick'
export default {
name: 'messageDetails',
props: {
id: {
type: [String, Number],
default: null,
},
},
filters: {
formatterTime: function(time) {
return formatDate(parseInt(time, 10))
},
getMsgType(val) {
const target =
messageTypeList.find(i => i.bizIdentification === val) || {}
return target.label
},
},
data() {
return {
query: {},
content: '',
msgList: [],
preItem: null,
nextItem: null,
pageLoading: false,
}
},
beforeRouteLeave(_, __, next) {
this.$store.commit('breadcrumb/setBreadcrumb', [])
next()
},
created() {
setTimeout(() => {
this.$store.commit('breadcrumb/setBreadcrumb', breadcrumbData)
}, 0)
if (this.user && this.user.userId) this.init()
},
computed: {
...mapGetters(['user']),
},
watch: {
id: {
handler(val, oval) {
if (val && oval && val !== oval) {
// 由于 vue-router 使用动态路由时,进行push,会复用当前页面组件,导致不会进行生命周期的变化,这里对路由参数进行监听,重新获取数据
this.pageLoading = true
this.getMessageDetail()
.then(() => {
this.getPreAndNext()
})
.finally(() => {
this.pageLoading = false
})
}
},
},
user: {
handler(val, oval) {
// 由于页面初始化时,可能还未获取到user,需要在这里重新获取
if (val && val !== oval && val.userId) {
this.init()
}
},
},
},
methods: {
getPreAndNext() {
// 获取上一条和下一条消息,目前通过获取全部消息列表进行比对,获取到当前消息的上一条和下一条消息
const currentId = this.id
const index = this.msgList.findIndex(
i => i.id.toString() === currentId.toString()
)
this.preItem =
index - 1 >= 0 ? this.msgList.slice(index - 1, index)[0] : null
this.nextItem =
index + 1 < this.msgList.length
? this.msgList.slice(index + 1, index + 2)[0]
: null
},
init() {
this.query = pick(this.user, ['userId', 'admin'])
this.query.registerTime = this.user.createdTime
this.pageLoading = true
Promise.all([this.getMessages(), this.getMessageDetail()])
.then(() => {
this.getPreAndNext()
})
.finally(() => {
this.pageLoading = false
})
},
getMessages() {
// 用来获取前后条数据
const params = {...this.query}
return getMessages(params).then(({payload}) => {
this.msgList = payload.content
})
},
getMessageDetail() {
const params = {messageId: this.id}
return getMessageDetail(params).then(res => {
this.content = res.payload
// 通知未读列表去更新数据
this.$store.commit('notification/noticeMessage')
})
},
handleClick(item = {}) {
this.$router.push({
path: `/main/message/details/${item.id}`,
})
// 这里需要更新下一条的状态,更新未读列表状态, 是自动标记的,不需要前端调用接口
},
},
}
</script>
浙公网安备 33010602011771号