Files
pgserver3.0/pgweb/src/components/menu/nxMenu.vue
2026-04-28 13:52:00 +08:00

351 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 可递归菜单 -->
<template>
<div style="height: 100%;">
<!-- 如果有子菜单则渲染子菜单 -->
<el-submenu style="height: 100%;" v-if="item.children && item.children.length > 0" :index="item.routerName" >
<template slot="title">
{{ item.title }}
<!-- 二级菜单未回价显示未回价数量 -->
<span v-if="isUnreturnedPriceMenu && unreturnedCount > 0" class="push-value-badge">{{ unreturnedCount }}</span>
<!-- 二级菜单预估单显示预估总数 -->
<span v-if="isEstimatePendingMenu && estimateCounts.total > 0" class="push-value-badge">{{ estimateCounts.total }}</span>
<!-- 二级菜单查勘列表显示查勘跟进中数量 -->
<span v-if="isSurveyListMenu && surveyFollowCount > 0" class="push-value-badge">{{ surveyFollowCount }}</span>
<!-- 二级菜单报告制作显示报告总数 -->
<span v-if="isReportProduceMenu && reportProduceCounts.total > 0" class="push-value-badge">{{ reportProduceCounts.total }}</span>
</template>
<!-- 递归调用MenuItem组件 -->
<menu-item v-for="(child, index) in item.children" :key="index" :item="child" class="menu-custom"></menu-item>
</el-submenu>
<!-- 如果没有子菜单则渲染菜单项 -->
<el-menu-item v-else :index="item.routerName" class="menu-custom">
{{ item.title }}
<!-- 三级菜单未回价列表显示未回价数量 -->
<span v-if="isUnreturnedPriceListMenu && unreturnedCount > 0" class="push-value-badge">{{ unreturnedCount }}</span>
<!-- 三级菜单待制作(预估)显示预估待制作数量 -->
<span v-if="isEstimatePendingListMenu && estimateCounts.pending > 0" class="push-value-badge">{{ estimateCounts.pending }}</span>
<!-- 三级菜单二审待制作(预估)显示预估二审数量 -->
<span v-if="isSecondReviewListMenu && estimateCounts.secondReview > 0" class="push-value-badge">{{ estimateCounts.secondReview }}</span>
<!-- 三级菜单三审待制作(预估)显示预估三审数量 -->
<span v-if="isThirdReviewListMenu && estimateCounts.thirdReview > 0" class="push-value-badge">{{ estimateCounts.thirdReview }}</span>
<!-- 三级菜单待签章(预估)显示预估待签章数量 -->
<span v-if="isSignListMenu && estimateCounts.sign > 0" class="push-value-badge">{{ estimateCounts.sign }}</span>
<!-- 三级菜单跟进中(查勘)显示查勘跟进中数量 -->
<span v-if="isSurveyFollowMenu && surveyFollowCount > 0" class="push-value-badge">{{ surveyFollowCount }}</span>
<!-- 三级菜单待制作(报告)显示报告待制作数量 -->
<span v-if="isReportPendingMenu && reportProduceCounts.pending > 0" class="push-value-badge">{{ reportProduceCounts.pending }}</span>
<!-- 三级菜单二审待制作(报告)显示报告二审待制作数量 -->
<span v-if="isReportSecondReviewMenu && reportProduceCounts.secondReview > 0" class="push-value-badge">{{ reportProduceCounts.secondReview }}</span>
<!-- 三级菜单三审待制作(报告)显示报告三审待制作数量 -->
<span v-if="isReportThirdReviewMenu && reportProduceCounts.thirdReview > 0" class="push-value-badge">{{ reportProduceCounts.thirdReview }}</span>
</el-menu-item>
</div>
</template>
<script>
import "@/styles/globalSetting.less";
import { EventBus } from '@/libs/eventBus'
import socket from '@/libs/socket'
import { post } from '@/libs/request'
import { getEstimatePendingCount, getSurveyFollowCount, getReportProduceCount } from '@/api/businessManage/inquiry'
export default {
name: 'MenuItem',
props: {
item: Object
},
data() {
return {
unreturnedCount: 0,
estimateCounts: {
pending: 0,
secondReview: 0,
thirdReview: 0,
sign: 0,
total: 0
},
surveyFollowCount: 0,
reportProduceCounts: {
pending: 0,
secondReview: 0,
thirdReview: 0,
total: 0
}
}
},
computed: {
// ==================== 回价项目 ====================
// 判断是否是一级菜单【回价项目】
isHuiJiaMenu() {
return this.item.routerName === 'priceReturn' || this.item.title === '回价项目'
},
// 判断是否是二级菜单【未回价】
isUnreturnedPriceMenu() {
return this.item.routerName === 'unreturnedPrice' || this.item.title === '未回价'
},
// 判断是否是三级菜单【未回价列表】- 使用routerName唯一标识
isUnreturnedPriceListMenu() {
return this.item.routerName && this.item.routerName.includes('unreturnedPrice') ||
this.item.title === '未回价列表'
},
// ==================== 预估项目 ====================
// 判断是否是一级菜单【预估】- 只有当不是预估单时才匹配
isEstimateMenu() {
return (this.item.routerName === 'estimate' || this.item.title === '预估') &&
!this.isEstimatePendingMenu
},
// 判断是否是二级菜单【预估单】
isEstimatePendingMenu() {
return this.item.routerName === 'estimateMake-estimate' || this.item.title === '预估单'
},
// 判断是否是三级菜单【待制作】(预估)-使用routerName区分避免与报告制作下的待制作混淆
isEstimatePendingListMenu() {
return this.item.routerName === 'estimateMake-estimateWaitMakeList' ||
this.item.routerName && this.item.routerName.includes('estimateWaitMakeList')
},
// 判断是否是三级菜单【二审待制作】(预估)-使用routerName区分
isSecondReviewListMenu() {
return this.item.routerName === 'estimateMake-estimateWaitMakeApprovalList' ||
this.item.routerName && this.item.routerName.includes('estimateWaitMakeApprovalList')
},
// 判断是否是三级菜单【三审待制作】(预估)-使用routerName区分
isThirdReviewListMenu() {
return this.item.routerName === 'estimateMake-estimateWaitMakeApprovalThirdList' ||
this.item.routerName && this.item.routerName.includes('estimateWaitMakeApprovalThirdList')
},
// 判断是否是三级菜单【待签章】(预估)
isSignListMenu() {
return this.item.routerName === 'estimateMake-estimateWaitSignSignList' ||
this.item.routerName && this.item.routerName.includes('estimateWaitSignSignList') ||
this.item.title === '待签章'
},
// ==================== 查勘项目 ====================
// 判断是否是一级菜单【查勘项目】
isSurveyMenu() {
return this.item.routerName === 'surveyManage-surveyManage' ||
this.item.routerName === 'survey' ||
this.item.title === '查勘项目' ||
this.item.title === '查勘'
},
// 判断是否是二级菜单【查勘列表】
isSurveyListMenu() {
return this.item.routerName && this.item.routerName.startsWith('surveyManage-') ||
this.item.title === '查勘列表'
},
// 判断是否是三级菜单【跟进中】(查勘)-使用routerName确保是查勘模块下的
isSurveyFollowMenu() {
return this.item.routerName === 'surveyManage-surveyWaitFollowList' ||
(this.item.title === '跟进中' && this.item.routerName && this.item.routerName.includes('survey'))
},
// ==================== 报告项目 ====================
// 判断是否是一级菜单【报告项目】
// isReportMenu() {
// return this.item.routerName === 'report' ||
// this.item.title === '报告项目' ||
// this.item.title === '报告制作'
// },
// 判断是否是二级菜单【报告制作】
isReportProduceMenu() {
return this.item.routerName && this.item.routerName.startsWith('report-') ||
this.item.title === '报告制作'
},
// 判断是否是三级菜单【待制作】(报告)-使用routerName区分避免与预估单下的待制作混淆
isReportPendingMenu() {
return this.item.routerName === 'waitMake'
},
// 判断是否是三级菜单【二审待制作】(报告)-使用routerName区分
isReportSecondReviewMenu() {
return this.item.routerName === 'waitApproval'
},
// 判断是否是三级菜单【三审待制作】(报告)-使用routerName区分
isReportThirdReviewMenu() {
return this.item.routerName === 'waitApprovalThird'
}
},
mounted() {
// 获取所有数据,确保每个菜单项都能显示正确的数值
// 回价相关菜单
this.fetchUnreturnedCount()
// 预估相关菜单 - 包含预估模块下的所有菜单
this.fetchEstimateCount()
// 查勘相关菜单 - 包含查勘模块下的所有菜单
this.fetchSurveyFollowCount()
// 报告相关菜单 - 包含报告模块下的所有菜单
this.fetchReportCount()
// 保存回调引用用于销毁时移除
this.eventBusCallback = (count) => {
this.unreturnedCount = count
console.log('EventBus收到未回价数量更新:', count, '当前item:', this.item.name || this.item.title)
}
this.socketCallback = (data) => {
if (data && data.refresh) {
// 收到刷新事件,只有回价相关菜单才主动获取数据
if (this.isHuiJiaMenu || this.isUnreturnedPriceMenu || this.isUnreturnedPriceListMenu) {
this.fetchUnreturnedCount()
}
} else if (data && data.count !== undefined) {
this.$set(this, 'unreturnedCount', data.count)
console.log('WebSocket收到未回价数量更新:', data.count, '当前item:', this.item.name || this.item.title)
}
}
// 预估制作数量回调
this.estimateEventBusCallback = (counts) => {
this.$set(this, 'estimateCounts', counts)
}
this.estimateSocketCallback = (data) => {
if (data && data.refresh) {
// 收到刷新事件,只有预估相关菜单才主动获取数据
if (this.isEstimateMenu || this.isEstimatePendingMenu || this.isEstimatePendingListMenu || this.isSecondReviewListMenu || this.isThirdReviewListMenu || this.isSignListMenu) {
this.fetchEstimateCount()
}
} else if (data && data.pending !== undefined) {
this.$set(this, 'estimateCounts', data)
console.log('WebSocket收到预估制作数量更新:', data, '当前item:', this.item.name || this.item.title)
}
}
// 查勘跟进中数量回调
this.surveyEventBusCallback = (count) => {
this.$set(this, 'surveyFollowCount', count)
}
this.surveySocketCallback = (data) => {
if (data && data.refresh) {
// 收到刷新事件,只有查勘相关菜单才主动获取数据
if (this.isSurveyMenu || this.isSurveyListMenu || this.isSurveyFollowMenu) {
this.fetchSurveyFollowCount()
}
} else if (data && data.count !== undefined) {
this.$set(this, 'surveyFollowCount', data.count)
console.log('WebSocket收到查勘跟进中数量更新:', data.count, '当前item:', this.item.name || this.item.title)
}
}
// 报告制作数量回调
this.reportEventBusCallback = (counts) => {
this.$set(this, 'reportProduceCounts', counts)
}
this.reportSocketCallback = (data) => {
if (data && data.refresh) {
// 收到刷新事件,只有报告相关菜单才主动获取数据
if (this.isReportMenu || this.isReportProduceMenu || this.isReportPendingMenu || this.isReportSecondReviewMenu || this.isReportThirdReviewMenu) {
this.fetchReportCount()
}
} else if (data && data.pending !== undefined) {
this.$set(this, 'reportProduceCounts', data)
}
}
// 监听EventBus事件
EventBus.$on('updateUnreturnedCount', this.eventBusCallback)
EventBus.$on('updateEstimatePendingCount', this.estimateEventBusCallback)
EventBus.$on('updateSurveyFollowCount', this.surveyEventBusCallback)
EventBus.$on('updateReportProduceCount', this.reportEventBusCallback)
// 监听WebSocket事件
socket.on('updateUnreturnedCount', this.socketCallback)
socket.on('updateEstimatePendingCount', this.estimateSocketCallback)
socket.on('updateSurveyFollowCount', this.surveySocketCallback)
socket.on('updateReportProduceCount', this.reportSocketCallback)
},
beforeDestroy() {
// 移除监听
EventBus.$off('updateUnreturnedCount', this.eventBusCallback)
socket.off('updateUnreturnedCount', this.socketCallback)
EventBus.$off('updateEstimatePendingCount', this.estimateEventBusCallback)
socket.off('updateEstimatePendingCount', this.estimateSocketCallback)
EventBus.$off('updateSurveyFollowCount', this.surveyEventBusCallback)
socket.off('updateSurveyFollowCount', this.surveySocketCallback)
EventBus.$off('updateReportProduceCount', this.reportEventBusCallback)
socket.off('updateReportProduceCount', this.reportSocketCallback)
},
methods: {
async fetchUnreturnedCount() {
try {
const res = await post('admin/Pending/getUnreturnedPriceCount')
if (res && res.code === 1 && res.data) {
this.$set(this, 'unreturnedCount', res.data.count)
}
} catch (error) {
console.error('获取未回价数量失败:', error)
}
},
async fetchEstimateCount() {
try {
const res = await getEstimatePendingCount()
if (res && res.code === 1 && res.data) {
this.$set(this, 'estimateCounts', res.data)
}
} catch (error) {
console.error('获取预估数量失败:', error)
}
},
async fetchSurveyFollowCount() {
try {
const res = await getSurveyFollowCount()
if (res && res.code === 1 && res.data) {
this.$set(this, 'surveyFollowCount', res.data.count)
}
} catch (error) {
console.error('获取查勘跟进中数量失败:', error)
}
},
async fetchReportCount() {
try {
console.log('===== nxMenu 获取报告制作数量 =====')
const res = await getReportProduceCount()
console.log('报告制作数量接口返回:', JSON.stringify(res, null, 2))
if (res && res.code === 1 && res.data) {
const data = res.data
console.log('待制作:', data.pending, '二审:', data.secondReview, '三审:', data.thirdReview, '总数:', data.total)
this.$set(this, 'reportProduceCounts', data)
}
} catch (error) {
console.error('获取报告制作数量失败:', error)
}
}
}
}
</script>
<style lang="less" scoped>
.menu-custom {
color: var(--menu-font-color);
}
:deep .el-menu-item.is-active {
background-color: var(--bg-color);
}
:deep .el-menu-item.is-active.menu-custom {
color: var(--main-color);
}
.push-value-badge {
display: inline-block;
min-width: 20px;
height: 20px;
line-height: 20px;
padding: 0 6px;
font-size: 12px;
color: #fff;
background-color: #f56c6c;
border-radius: 10px;
margin-left: 8px;
text-align: center;
}
.push-dot-badge {
display: inline-block;
width: 8px;
height: 8px;
background-color: #f56c6c;
border-radius: 50%;
margin-left: 8px;
margin-top: 4px;
}
</style>