const app = getApp() import Dialog from '@vant/weapp/dialog/dialog'; import Notify from '@vant/weapp/notify/notify'; import { selfFormatTimeYMD, selfFormatTimeHM, getWeekday, getNowDate } from "../../../../utils/util.js" import { selectReservationListByUserIdRq, selectVisitorInvitationRecordRq, cancelOrderRq, approveOrderRq, approveOrderDel, selectReservationByIdRq, getStaff } from "../../../../api/meeting/meetingRoom.js" // 引入消息通知相关API import { repairRemindListRq, repairRemindListByRepairIdRq, repairRemindReadRq } from "../../../../api/repair/repair.js" Page({ /** * 页面的初始数据 */ data: { IMG_NAME: app.IMG_NAME, userData: null, dataChange: false, tabTitle: '预约记录', // 预约记录参数 reservationPageNum: 1, reservationPageSize: 10, reservationDataList: [], reservationIsDataAll: false, // 会务人员通知状态 staffNotifications: {}, search: { title: { text: '会议名称', value: '' }, status: { text: '', value: 5, option: [{ text: '全部预约', value: '' }, { text: '待审核', value: 5 }, { text: '待开始', value: 7 }, { text: '已结束', value: 11 }, { text: '已取消', value: 1 }, { text: '已驳回', value: 3 }, { text: '占用', value: 4 }, { text: '进行中', value: 9 }, ] }, sort: { value: 'start', option: [{ text: '排序方式', value: '' }, { text: '会议开始时间', value: 'start' }, { text: '创建时间', value: 'create' }, ] } }, showRejectReason: false, // 是否展示弹出层 rejectlId: '', // 驳回预约会议id rejectReason: '', // 驳回预约原因 beforeReject(action) { return new Promise(resolve => { if (action === 'confirm') { resolve(false) } else { resolve(true) } }); }, // 弹出层点击确认不关闭,手动关 // 会议重新预约需要参数 editId: '', showEdit: false, editAction: [{ name: '重新选择时间、会议室', type: 1 }, { name: '重新编辑会议信息', type: 2 }, ], timeShow: false, currentDate: new Date().getTime(), minDate: new Date().getTime(), maxDate: '', formatter(type, value) { if (type === 'year') { return `${value}年`; } if (type === 'month') { return `${value}月`; } if (type === 'day') { return `${value}日`; } return value; }, // 参与记录参数,不需要 // participatePageNum: 1, // participatePageSize: 10, // participateDataList: [], // participateIsDataAll: false, }, changeSearchTitle(e) { this.setData({ ['search.title.value']: e.detail, }) }, searchTitle() { // 刷新预约数据 this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, }) this.getDataList() this.selectComponent('#item').toggle() }, changeSearchStatus(e) { // 刷新预约数据 this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, ['search.status.value']: e.detail }) // 更新状态文本 const statusOption = this.data.search.status.option; const selectedOption = statusOption.find(option => option.value === e.detail); if (selectedOption) { this.setData({ ['search.status.text']: selectedOption.text }); } this.getDataList() }, changeSearchSort(e) { // 刷新预约数据 this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, ['search.sort.value']: e.detail }) // 更新排序文本 const sortOption = this.data.search.sort.option; const selectedOption = sortOption.find(option => option.value === e.detail); if (selectedOption) { this.setData({ ['search.sort.text']: selectedOption.text }); } this.getDataList() }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // 这里opt接收options以处理查看更多 if (options.act == 'show') { wx.setNavigationBarTitle({ title: '预约记录', }) this.setData({ 'search.status.value': '' }) } // 检查是否有URL参数指定状态 if (options && options.status) { this.setData({ 'search.status.value': parseInt(options.status) || 7 }); // 初始化状态文本 const statusOption = this.data.search.status.option; const selectedOption = statusOption.find(option => option.value === this.data.search.status.value); if (selectedOption) { this.setData({ 'search.status.text': selectedOption.text }); } } let _this = this; let userDetail = wx.getStorageSync('user') _this.setData({ userData: userDetail }) // 获取两周后时间,默认只能选两周之后,管理员可以选一年后的 const today = new Date() const newDate = new Date(today) if (userDetail.roomRole == 5) { newDate.setFullYear(newDate.getFullYear() + 1) } else { newDate.setDate(newDate.getDate() + 14) } _this.setData({ maxDate: newDate.getTime() }) // 注册全局通知状态更新监听器 const app = getApp(); if (app && app.registerNotificationStatusChange) { this.notificationStatusChangeCallback = (data) => { console.log('approve页面收到全局通知状态更新:', data); // 如果是会务人员(音控或服务人员)的通知,则更新状态 if (data && data.meetingId && data.isStaffUser) { _this.updateNotificationStatus(data); } }; app.registerNotificationStatusChange(this.notificationStatusChangeCallback); console.log('已注册全局通知状态更新监听器'); } // 获取数据 _this.getDataList() // 页面加载完成后获取通知状态 wx.nextTick(() => { console.log('页面加载完成,获取通知状态'); _this.getStaffNotificationStatus(); }); }, /** * 获取会议列表数据 */ getDataList() { let _this = this; let { userData } = _this.data; console.log('页面加载完成,获取通知状态'); if (!userData) return; let userId = userData.id; // 请求参数 let isDataAll = _this.data.reservationIsDataAll let pageNum = _this.data.reservationPageNum let pageSize = _this.data.reservationPageSize // 判断数据是否已全部加载 if (isDataAll) { return; } // 传递参数 let param = { userId, pageNum, pageSize } _this.getReservationData(param) .then(() => { console.log('所有预约数据加载完成,共', _this.data.reservationDataList.length, '条记录'); // 注意:不要在这里调用getStaffNotificationStatus // 通知状态会在loadStaffInfoForItems函数中处理 }) .catch(err => { console.error('加载预约数据失败:', err); }); }, // 获取会务人员通知状态 getStaffNotificationStatus() { let _this = this; console.log('开始获取会务人员通知状态...'); // 获取当前会议列表 const meetingItems = _this.data.reservationDataList || []; // 过滤出有会务负责人的会议 const meetingsWithStaff = meetingItems.filter(item => (item.serviceStaff || item.musicStaff) && ((item.serviceIds && item.serviceIds.length > 0) || (item.musicIds && item.musicIds.length > 0))); console.log('需要获取通知状态的会议数量:', meetingsWithStaff.length); if (meetingsWithStaff.length === 0) { return Promise.resolve(); } // 为每个有会务人员的会议项查询通知状态 const notificationPromises = meetingsWithStaff.map(item => { return this.queryMeetingNotificationStatus(item); }); // 等待所有会议通知状态查询完成 return Promise.all(notificationPromises).then(() => { console.log('所有会议通知状态处理完成'); }); }, // 判断是否为会议相关通知 isMeetingNotification(content) { if (!content) return false; return content.includes('会议预约') || content.includes('会务负责人') || (content.includes('您收到会议预约') && content.includes('待审核')) || (content.includes('会议预约') && content.includes('已取消')) || (content.includes('您的会议预约') && ( content.includes('被驳回') || content.includes('已被管理员修改') || content.includes('已审核通过') || content.includes('即将开始') )); }, // 获取预约数据 getReservationData(param) { let _this = this; let { pageNum, pageSize, userId } = param // 确保使用最新的用户角色 let currentUserData = wx.getStorageSync('user'); let currentRole = currentUserData ? currentUserData.roomRole : _this.data.userData.roomRole; wx.showLoading({ title: '加载中...', mask: true }); // 查询数据并返回Promise return selectReservationListByUserIdRq({ role: currentRole, // 使用最新的角色 pageNum, pageSize, userId: _this.data.userData.id, // 确保传递用户ID title: _this.data.search.title.value, status: _this.data.search.status.value === '' ? null : _this.data.search.status.value, sort: _this.data.search.sort.value, // 排序 }).then(res => { wx.hideLoading(); console.log('获取预约列表数据:', res); // 判断数据是否全部查询 let queryDataList = res.rows || []; // 检查是否还有更多数据可加载 if (_this.data.reservationDataList.length < res.total) { // 更新数据 let reservationDataList = _this.data.reservationDataList.concat(_this.formartData(queryDataList)); let reservationPageNum = _this.data.reservationPageNum + 1; _this.setData({ reservationPageNum, reservationDataList, }); } else { // 所有数据已加载完成 _this.setData({ reservationIsDataAll: true }); } return res; // 返回结果以便链式调用 }).catch(err => { wx.hideLoading(); console.error('获取预约列表数据失败:', err); throw err; // 抛出错误以便在上层处理 }); }, // 获取参与数据,此处不需要 getParticipateData(param) { let _this = this; let { pageNum, pageSize, userId } = param // 查询数据 selectVisitorInvitationRecordRq({ pageNum, pageSize, userId }).then(res => { console.log('selectVisitorInvitationRecordRq', res); // 判断数据是否全部查询 let queryDataList = res.page.records; if (queryDataList && queryDataList.length > 0) { // 更新参数 let participateDataList = _this.data.participateDataList.concat(_this.formartData(queryDataList)); let participatePageNum = _this.data.participatePageNum + 1; _this.setData({ participatePageNum, participateDataList, }) } else { _this.setData({ participateIsDataAll: true }) } }) }, // 格式化数据 formartData(queryDataList) { // 格式化数据 let _this = this; let userRole = _this.data.userData.roomRole; // 获取用户角色 // 获取当前日期、第二天日期和第三天日期 let nowDate = new Date(); let secondDate = new Date(); secondDate.setDate(nowDate.getDate() + 1); let thirdDate = new Date(); thirdDate.setDate(nowDate.getDate() + 2); // 格式化当前日期、第二天日期和第三天日期为YYYY-MM-DD格式 let nowDateStr = selfFormatTimeYMD(nowDate); let secondDateStr = selfFormatTimeYMD(secondDate); let thirdDateStr = selfFormatTimeYMD(thirdDate); console.log('格式化数据,记录数量:', queryDataList.length); // 首先进行基本格式化 let formattedData = queryDataList.map(item => { // 会议开始日期 let meetingDateStr = selfFormatTimeYMD(item.start); // 判断是哪一天 item.isToday = meetingDateStr === nowDateStr; item.isSecondDay = meetingDateStr === secondDateStr; item.isThirdDay = meetingDateStr === thirdDateStr; item.isNowDay = item.isToday; // 保持兼容性 // 添加星期几属性,但不再用于颜色判断 item.weekDay = getWeekday(item.start); // 完全移除基于星期几的颜色逻辑 // 确保不保留任何可能影响颜色的旧数据 if(item.dateColor) { delete item.dateColor; } item.timeSlot = selfFormatTimeYMD(item.start) + ' '+ getWeekday(item.start) +' ' + selfFormatTimeHM(item.start) + '~' + selfFormatTimeHM(item.end); // 状态字体颜色 let statusColor = "#FFB119"; // 按钮是否显示 let statusValue = item.status; let showCancel = false // 显示取消操作 let showEdit = false // 显示编辑操作 let showStaff = false // 显示会务人员 let showApprove = false // 显示审批操作 let statusName = '' // 预约状态,1 取消 3 驳回 4 占用 5 待审核 7 审核通过,待开始 9 进行中 11已结束 if (statusValue == 1) { // 取消 // 状态字体颜色 statusColor = "#333333" statusName = '已取消' } if (statusValue == 3) { // 驳回,可以修改 statusColor = "#333333" statusName = '已驳回' } if (statusValue == 4) { // 占用,仅管理员可以修改 statusName = '已占用' if (userRole == 5) { // 只有管理员可以编辑和取消占用 showEdit = true showCancel = true } } if (statusValue == 5) { // 待审核,管理员可以审批 statusName = '待审核' if (userRole == 5) { // 只有管理员可以编辑和审批 showEdit = true showApprove = true } } if (statusValue == 7) { // 审核通过,管理员可修改 statusName = '待开始' if (userRole == 5) { // 只有管理员可以取消、编辑和分配会务人员 showCancel = true showEdit = true showStaff = true // 根据会务负责人选择状态设置按钮颜色和提示 // 预先进行一次状态判断,稍后将异步获取详细信息 this.processStaffStatus(item); } } if (statusValue == 9) { // 进行中 statusName = '进行中' } if (statusValue == 11) { // 已结束 statusColor = "#333333" statusName = '已结束' } // 赋值 item.showCancel = showCancel item.showEdit = showEdit item.showApprove = showApprove item.showStaff = showStaff item.statusName = statusName // 状态字体颜色 item.statusColor = statusColor; // 图片 if (item.imgs) { try { item.indoorPicUrlFirst = item.imgs[0].url } catch (error) { console.log(`JSON error : ${error}`); } } // 初始化会务通知状态 item.isStaffNotificationRead = false; // 默认未读 // 初始化已读计数 item.readCount = 0; // 默认0人已读 item.totalStaffCount = 0; // 默认总会务人员数量为0,后续从通知接口获取 // 音控组和会务组初始化 item.serviceReadCount = 0; // 会务组已读人数 item.musicReadCount = 0; // 音控组已读人数 item.serviceTotalCount = 0; // 会务组总人数 item.musicTotalCount = 0; // 音控组总人数 item.serviceIds = []; // 会务组ID列表 item.musicIds = []; // 音控组ID列表 item.serviceStaff = false; // 是否有会务组 item.musicStaff = false; // 是否有音控组 // 未读通知显示逻辑: // 1. 会务负责人按钮上的红点 - 只在status为7且showStaff为true时显示 // 2. 左侧的红条 - 在status为5(待审核)时显示 // 3. 状态文字 - 在status为5或7时显示 item.hasUnreadNotification = (item.status == 5 || item.status == 7); // 如果是待审核或待开始状态,默认显示未读标记 for (let key in item) { // null设置为空 if (item[key] == null) { item[key] = '' } } return item }); // 异步加载所有"待开始"状态的预约记录的会务人员信息 this.loadStaffInfoForItems(formattedData); return formattedData; }, // 为所有待开始状态的预约记录加载会务人员信息 loadStaffInfoForItems(items) { if (!items || items.length === 0) return; // 过滤出所有"待开始"状态的记录 const pendingItems = items.filter(item => item.status == 7); console.log('需要获取会务人员信息的记录数:', pendingItems.length); if (pendingItems.length === 0) return; // 为每个待开始的预约记录异步获取会务人员信息 pendingItems.forEach(item => { selectReservationByIdRq({ id: item.id }).then(res => { console.log('获取预约详情(ID:' + item.id + '):', res); // 1. 检查waiters数组格式 if (res && res.waiters && Array.isArray(res.waiters)) { item.waiters = res.waiters; console.log('使用waiters数组格式数据'); } // 2. 检查voiceWaiter和serveWaiter字段 else if (res) { // 创建一个模拟的waiters数组 item.waiters = []; // 处理音控组数据 - voiceWaiter if (res.voiceWaiter) { const voiceIds = typeof res.voiceWaiter === 'string' ? res.voiceWaiter.split(',').filter(id => id) : (Array.isArray(res.voiceWaiter) ? res.voiceWaiter : []); voiceIds.forEach(id => { item.waiters.push({ userId: id, type: '1' // 音控组类型为1 }); }); // 同步数据到会议项中 item.voiceWaiter = res.voiceWaiter; } // 处理会务服务组数据 - serveWaiter if (res.serveWaiter) { const serveIds = typeof res.serveWaiter === 'string' ? res.serveWaiter.split(',').filter(id => id) : (Array.isArray(res.serveWaiter) ? res.serveWaiter : []); serveIds.forEach(id => { item.waiters.push({ userId: id, type: '3' // 会务服务组类型为3 }); }); // 同步数据到会议项中 item.serveWaiter = res.serveWaiter; } console.log('从voiceWaiter和serveWaiter字段构建waiters数组:', item.waiters); } // 重新处理会务人员状态 this.processStaffStatus(item); // 为单个会议项查询通知状态 this.queryMeetingNotificationStatus(item); // 触发视图更新 this.setData({ reservationDataList: this.data.reservationDataList }); }).catch(err => { console.error('获取预约详情失败(ID:' + item.id + '):', err); }); }); }, // 为单个会议项查询通知状态 queryMeetingNotificationStatus(item) { if (!item || (!item.serviceIds || !item.musicIds)) { console.log('会议项缺少必要信息,无法查询通知状态:', item?.id); return Promise.resolve(); } console.log('开始查询会议(ID:' + item.id + ')的通知状态'); let _this = this; const meetingId = item.id; // 初始化音控组和会务组已读计数 let serviceReadCount = 0; let musicReadCount = 0; // 处理音控组通知状态 const processAudioStaffStatus = () => { if (item.musicIds && item.musicIds.length > 0) { console.log('开始查询音控组通知状态,音控组成员:', item.musicIds); const musicPromises = item.musicIds.map(userId => { return repairRemindListByRepairIdRq({ repairId: meetingId, userId: userId, pageNum: 1, pageSize: 10 }).then(res => { console.log('诊断: 会议ID ' + meetingId + ' 音控人员ID ' + userId + ' 通知状态:', res); // 检查是否有通知并且是否已读 if (res && res.rows && res.rows.length > 0) { const isRead = res.rows.some(notice => notice.read === 1); if (isRead) { musicReadCount++; } return { userId, isRead }; } return { userId, isRead: false }; }).catch(err => { console.error('获取音控人员通知状态失败:', err); return { userId, isRead: false }; }); }); return Promise.all(musicPromises).then(() => { // 更新音控组已读数量 item.musicReadCount = musicReadCount; console.log('会议ID:', meetingId, '音控组:', '已读人数:', musicReadCount, '总人数:', item.musicTotalCount); // 刷新显示 _this.setData({ reservationDataList: _this.data.reservationDataList }); }); } else { return Promise.resolve(); } }; // 处理会务服务组通知状态 const processServiceStaffStatus = () => { if (item.serviceIds && item.serviceIds.length > 0) { console.log('开始查询会务组通知状态,会务组成员:', item.serviceIds); const servicePromises = item.serviceIds.map(userId => { return repairRemindListByRepairIdRq({ repairId: meetingId, userId: userId, pageNum: 1, pageSize: 10 }).then(res => { console.log('诊断: 会议ID ' + meetingId + ' 会务人员ID ' + userId + ' 通知状态:', res); // 检查是否有通知并且是否已读 if (res && res.rows && res.rows.length > 0) { const isRead = res.rows.some(notice => notice.read === 1); if (isRead) { serviceReadCount++; } return { userId, isRead }; } return { userId, isRead: false }; }).catch(err => { console.error('获取会务人员通知状态失败:', err); return { userId, isRead: false }; }); }); return Promise.all(servicePromises).then(() => { // 更新会务服务组已读数量 item.serviceReadCount = serviceReadCount; console.log('会议ID:', meetingId, '会务服务组:', '已读人数:', serviceReadCount, '总人数:', item.serviceTotalCount); // 刷新显示 _this.setData({ reservationDataList: _this.data.reservationDataList }); }); } else { return Promise.resolve(); } }; // 顺序处理会务服务组和音控组状态 return processServiceStaffStatus() .then(() => processAudioStaffStatus()) .then(() => { // 诊断输出会务人员和音控人员的阅读状态 console.log('诊断结果 - 会议ID ' + meetingId + ':'); console.log('音控组已读人数: ' + item.musicReadCount + ' / ' + item.musicTotalCount); console.log('会务组已读人数: ' + item.serviceReadCount + ' / ' + item.serviceTotalCount); }) .catch(err => { console.error('处理通知状态失败:', err); }); }, // 处理会务人员状态 processStaffStatus(item) { try { console.log('处理会务负责人状态:', item.id, item.title); // 初始化音控组和会务服务组状态 let hasMusicStaffFromServer = false; let hasServiceStaffFromServer = false; let musicIdsFromServer = []; let serviceIdsFromServer = []; let staffIds = []; // 存储所有会务负责人的ID // 处理从服务器获取的会务负责人数据 if (item.waiters) { // 如果waiters是数组形式 if (Array.isArray(item.waiters)) { console.log('处理数组形式的waiters数据'); // 分别检查服务器返回的数据中是否有音控组和会务服务组的人员 for (let i = 0; i < item.waiters.length; i++) { // 音控组 if (item.waiters[i].type === '1' || item.waiters[i].type === 1) { hasMusicStaffFromServer = true; const userId = item.waiters[i].userId; musicIdsFromServer.push(userId); staffIds.push(userId); } // 会务服务组 else if (item.waiters[i].type === '3' || item.waiters[i].type === 3) { hasServiceStaffFromServer = true; const userId = item.waiters[i].userId; serviceIdsFromServer.push(userId); staffIds.push(userId); } } } // 如果waiters是字符串形式(后台可能直接返回字符串ID) else if (typeof item.waiters === 'string') { console.log('处理字符串形式的waiters数据'); const waiterIds = item.waiters.split(',').filter(id => id); if (waiterIds.length > 0) { hasServiceStaffFromServer = true; waiterIds.forEach(id => { serviceIdsFromServer.push(id); staffIds.push(id); }); } } } // 处理单独的音控组和会务服务组字段 if (item.voiceWaiter) { console.log('处理voiceWaiter字段'); const voiceIds = typeof item.voiceWaiter === 'string' ? item.voiceWaiter.split(',').filter(id => id) : (Array.isArray(item.voiceWaiter) ? item.voiceWaiter : []); if (voiceIds.length > 0) { hasMusicStaffFromServer = true; voiceIds.forEach(id => { if (!musicIdsFromServer.includes(id)) { musicIdsFromServer.push(id); staffIds.push(id); } }); } } if (item.serveWaiter) { console.log('处理serveWaiter字段'); const serveIds = typeof item.serveWaiter === 'string' ? item.serveWaiter.split(',').filter(id => id) : (Array.isArray(item.serveWaiter) ? item.serveWaiter : []); if (serveIds.length > 0) { hasServiceStaffFromServer = true; serveIds.forEach(id => { if (!serviceIdsFromServer.includes(id)) { serviceIdsFromServer.push(id); staffIds.push(id); } }); } } // 去重获取实际会务人员ID列表 const uniqueStaffIds = [...new Set(staffIds)]; // 更新会务人员总数计数 - 使用实际选择的负责人数量,而不是默认值或来自其他地方的计数 item.totalStaffCount = uniqueStaffIds.length; // 保存音控组和会务服务组的信息 item.serviceStaff = hasServiceStaffFromServer; item.musicStaff = hasMusicStaffFromServer; item.serviceTotalCount = serviceIdsFromServer.length; item.musicTotalCount = musicIdsFromServer.length; item.serviceIds = serviceIdsFromServer; item.musicIds = musicIdsFromServer; // 初始化已读计数(如果不存在) if (typeof item.serviceReadCount === 'undefined') { item.serviceReadCount = 0; } if (typeof item.musicReadCount === 'undefined') { item.musicReadCount = 0; } item.showNotification = hasServiceStaffFromServer || hasMusicStaffFromServer; console.log('服务器返回的会务负责人状态(ID:' + item.id + '):', { 音控组: hasMusicStaffFromServer, 会务服务组: hasServiceStaffFromServer, 音控组IDs: musicIdsFromServer, 会务服务组IDs: serviceIdsFromServer, 音控组人数: musicIdsFromServer.length, 会务服务组人数: serviceIdsFromServer.length, 会务人员总数: item.totalStaffCount, 实际负责人IDs: uniqueStaffIds }); let hasMusicStaff = hasMusicStaffFromServer; let hasServiceStaff = hasServiceStaffFromServer; console.log('最终判断的会务负责人状态(ID:' + item.id + '):', { hasMusicStaff, hasServiceStaff, musicTotalCount: item.musicTotalCount, serviceTotalCount: item.serviceTotalCount, musicReadCount: item.musicReadCount, serviceReadCount: item.serviceReadCount }); if (hasMusicStaff && hasServiceStaff) { // 音控组和会务服务组都有选择 item.staffBtnType = ''; // 绿色(无类型) item.staffTip = ''; item.isStaffComplete = true; } else if (!hasMusicStaff && !hasServiceStaff) { // 音控组和会务服务组都没有选择 item.staffBtnType = 'danger'; // 红色 item.staffTip = '请选择音控组和会务服务组'; item.isStaffComplete = false; } else if (hasMusicStaff && !hasServiceStaff) { // 只选择了音控组 item.staffBtnType = 'warning'; // 灰色 item.staffTip = '请选择会务服务组'; item.isStaffComplete = false; } else if (!hasMusicStaff && hasServiceStaff) { // 只选择了会务服务组 item.staffBtnType = 'warning'; // 灰色 item.staffTip = '请选择音控组'; item.isStaffComplete = false; } // 存储会务人员ID列表 item.staffUserIds = uniqueStaffIds; return uniqueStaffIds; // 返回会务人员ID列表 } catch (error) { console.error('处理会务负责人状态异常(ID:' + item.id + '):', error); return []; // 出错时返回空数组 } }, // 标记通知为已读 markNotificationAsRead(id, userId) { let _this = this; let staffNotifications = _this.data.staffNotifications || {}; // 获取该用户对应的通知ID const notificationId = staffNotifications[id + '_notificationId_' + userId]; if (notificationId) { console.log('准备标记通知为已读 - 通知ID:', notificationId, '用户ID:', userId, '会议ID:', id); // 调用后端接口标记为已读 return repairRemindReadRq({ id: notificationId }).then(res => { console.log('通知标记已读成功:', res); // 更新本地通知状态 let readUserIds = staffNotifications[id + '_readUserIds'] || []; if (!readUserIds.includes(userId)) { readUserIds.push(userId); // 更新已读人数 const readCount = readUserIds.length; const totalCount = parseInt(staffNotifications[id + '_totalCount'] || 1); // 更新存储的通知状态 staffNotifications[id + '_readCount'] = readCount; staffNotifications[id + '_readUserIds'] = readUserIds; staffNotifications[id] = readCount > 0; // 查找并更新会议项 const meetingItem = _this.data.reservationDataList.find(item => item.id === id); if (meetingItem) { meetingItem.readCount = readCount; meetingItem.isStaffNotificationRead = readCount > 0; meetingItem.hasUnreadNotification = readCount < totalCount; meetingItem.readUserIds = readUserIds; // 更新未读标签文本 meetingItem.notificationText = readCount > 0 ? `已读(${readCount}/${totalCount})` : `未读(${readCount}/${totalCount})`; // 更新状态 _this.setData({ staffNotifications: staffNotifications, reservationDataList: _this.data.reservationDataList }); } else { _this.setData({ staffNotifications: staffNotifications }); } // 在本地存储通知状态更新信息,以便其他页面同步 wx.setStorageSync('meeting_notification_updated', { meetingId: id, userId: userId, notificationId: notificationId, isStaffUser: true, timestamp: new Date().getTime(), readCount: readCount, totalCount: totalCount }); // 触发全局通知状态更新 const app = getApp(); if (app && app.notifyNotificationStatusChange) { app.notifyNotificationStatusChange({ meetingId: id, userId: userId, isStaffUser: true, readCount: readCount, totalCount: totalCount }); } } return Promise.resolve(res); }).catch(err => { console.error('标记通知已读失败:', err); return Promise.reject(err); }); } else { console.log('未找到对应的通知ID - 用户ID:', userId, '会议ID:', id); // 尝试重新获取该用户的通知状态 return repairRemindListByRepairIdRq({ repairId: id, userId: userId, pageNum: 1, pageSize: 10 }).then(notifyRes => { if (notifyRes && notifyRes.rows && notifyRes.rows.length > 0) { const notification = notifyRes.rows[0]; // 取最新一条 staffNotifications[id + '_notificationId_' + userId] = notification.id; // 如果通知未读,则标记为已读 if (notification.read !== 1) { return _this.markNotificationAsRead(id, userId); // 递归调用标记为已读 } else { console.log('通知已经是已读状态,无需再次标记'); // 更新已读状态计数 const meetingItem = _this.data.reservationDataList.find(item => item.id === id); if (meetingItem) { let readUserIds = staffNotifications[id + '_readUserIds'] || []; if (!readUserIds.includes(userId)) { readUserIds.push(userId); const readCount = readUserIds.length; const totalCount = parseInt(staffNotifications[id + '_totalCount'] || meetingItem.totalStaffCount || 1); // 更新通知状态 staffNotifications[id + '_readCount'] = readCount; staffNotifications[id + '_readUserIds'] = readUserIds; staffNotifications[id] = readCount > 0; // 更新会议项 meetingItem.readCount = readCount; meetingItem.isStaffNotificationRead = readCount > 0; meetingItem.hasUnreadNotification = readCount < totalCount; meetingItem.readUserIds = readUserIds; meetingItem.notificationText = readCount > 0 ? `已读(${readCount}/${totalCount})` : `未读(${readCount}/${totalCount})`; _this.setData({ staffNotifications: staffNotifications, reservationDataList: _this.data.reservationDataList }); } } return Promise.resolve(null); } } else { console.log('没有找到该用户的通知'); return Promise.resolve(null); } }).catch(err => { console.error('获取通知状态失败:', err); return Promise.resolve(null); }); } }, // 跳转-预约详情 jumpMeetingDetail(e) { let _this = this; let id = e.currentTarget.dataset.id; console.log('跳转会议详情,ID:', id); // 获取当前用户信息 let userId = _this.data.userData ? _this.data.userData.id : ''; if (!userId) { console.error('未获取到当前用户ID'); wx.navigateTo({ url: `/pages/meeting/reservationRecord/meetingRecord/meetingDetail/meetingDetail?act=approve&id=${id}`, }); return; } // 先标记该用户的通知为已读 _this.markNotificationAsRead(id, userId).then(() => { // 无论是否成功标记已读,都跳转到详情页 wx.navigateTo({ url: `/pages/meeting/reservationRecord/meetingRecord/meetingDetail/meetingDetail?act=approve&id=${id}`, }); }).catch(err => { console.error('标记通知已读失败:', err); // 出错时仍然跳转 wx.navigateTo({ url: `/pages/meeting/reservationRecord/meetingRecord/meetingDetail/meetingDetail?act=approve&id=${id}`, }); }); }, /** * 跳转-会务负责人 */ goStaff(e) { let _this = this; let id = e.currentTarget.dataset.id; console.log('跳转会务负责人页面,ID:', id); // 获取当前用户信息 let userId = _this.data.userData ? _this.data.userData.id : ''; if (!userId) { console.error('未获取到当前用户ID'); wx.navigateTo({ url: `/pages/meeting/meetingRoom/meetingStaff/meetingStaff?rId=${id}`, }); return; } // 标记该用户的通知为已读 _this.markNotificationAsRead(id, userId).then(() => { // 跳转到会务负责人页面 wx.navigateTo({ url: `/pages/meeting/meetingRoom/meetingStaff/meetingStaff?rId=${id}`, }); }).catch(err => { console.error('标记通知已读失败:', err); // 出错时仍然跳转 wx.navigateTo({ url: `/pages/meeting/meetingRoom/meetingStaff/meetingStaff?rId=${id}`, }); }); }, /** * 更新通知状态 - 当用户阅读通知后调用 */ updateNotificationStatus(data) { let _this = this; if (!data || !data.meetingId) { console.error('更新通知状态失败:缺少必要参数'); return; } console.log('收到通知状态更新请求:', data); const meetingId = data.meetingId; const userId = data.userId; // 获取会议项 const meetingItem = _this.data.reservationDataList.find(item => item.id === meetingId); if (!meetingItem) { console.error('未找到相关会议:', meetingId); return; } // 获取当前通知状态 let staffNotifications = _this.data.staffNotifications || {}; // 获取已读用户ID列表 let readUserIds = staffNotifications[meetingId + '_readUserIds'] || []; // 如果用户ID不在已读列表中,添加到已读列表 if (userId && !readUserIds.includes(userId)) { readUserIds.push(userId); staffNotifications[meetingId + '_readUserIds'] = readUserIds; // 更新已读计数 const totalCount = Math.max( meetingItem.totalStaffCount || 0, meetingItem.staffUserIds ? meetingItem.staffUserIds.length : 0, 1 ); const readCount = Math.min(readUserIds.length, totalCount); // 更新通知状态 staffNotifications[meetingId] = readCount > 0; staffNotifications[meetingId + '_readCount'] = readCount; // 更新会议项的通知状态 meetingItem.readCount = readCount; meetingItem.isStaffNotificationRead = readCount > 0; meetingItem.hasUnreadNotification = readCount < totalCount; meetingItem.notificationText = readCount > 0 ? `已读(${readCount}/${totalCount})` : `未读(${readCount}/${totalCount})`; // 更新数据 _this.setData({ staffNotifications: staffNotifications }); console.log('已更新会议通知状态 - 会议ID:', meetingId, '用户ID:', userId, '已读人数:', readCount, '总人数:', totalCount); // 调用后端API标记通知为已读 if (data.notificationId) { repairRemindReadRq({ id: data.notificationId }).then(res => { console.log('标记通知已读成功:', res); // 在成功后重新获取通知状态,确保UI更新 setTimeout(() => { _this.getStaffNotificationStatus(); }, 500); }).catch(err => { console.error('标记通知已读失败:', err); }); } } }, /** * 生命周期函数--监听页面显示 * 添加刷新会务负责人状态按钮显示逻辑 */ onShow() { let _this = this; // 每次页面显示时检查用户角色是否有变化 let currentUserData = wx.getStorageSync('user'); let userRoleChanged = false; // 检查用户角色是否发生变化 if(_this.data.userData && currentUserData && _this.data.userData.roomRole !== currentUserData.roomRole) { userRoleChanged = true; // 更新用户数据 _this.setData({ userData: currentUserData }); console.log('用户角色已变更,重新加载数据'); } // 数据是否变化或用户角色变化 if (_this.data.dataChange || userRoleChanged) { // 重置数据变化标志 _this.setData({ dataChange: false }); // 检查是否从会务负责人页面返回 const staffPageUpdated = wx.getStorageSync('staffPage_updated'); if (staffPageUpdated) { console.log('检测到会务负责人页面有更新:', staffPageUpdated); // 清除标记,避免重复处理 wx.removeStorageSync('staffPage_updated'); // 如果会务人员选择页面提供了会议ID,优先处理特定会议的通知状态 if (staffPageUpdated.meetingId) { // 获取会议详情并更新通知状态 selectReservationByIdRq({ id: staffPageUpdated.meetingId }).then(res => { console.log('获取会议详情成功:', res); if (res) { // 查找对应的会议项 const meetingItem = _this.data.reservationDataList.find( item => item.id === staffPageUpdated.meetingId ); if (meetingItem) { console.log('找到需要更新的会议项:', meetingItem.id, meetingItem.title); // 更新会议项的会务人员信息 if (res.waiters) { meetingItem.waiters = res.waiters; } if (res.voiceWaiter) { meetingItem.voiceWaiter = res.voiceWaiter; } if (res.serveWaiter) { meetingItem.serveWaiter = res.serveWaiter; } // 重新处理会务人员状态 const staffUserIds = _this.processStaffStatus(meetingItem); // 对单个会议项查询通知状态 _this.queryMeetingNotificationStatus(meetingItem); } else { // 未找到会议项,可能需要重新加载数据 console.log('未找到对应的会议项,重新加载会议列表'); _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, }); _this.getDataList(); } } }).catch(err => { console.error('获取会议详情失败:', err); }); return; } // 仅刷新通知状态,不需要重新获取整个列表 // 不要在这里调用getStaffNotificationStatus,会在loadStaffInfoForItems中处理 } else { // 检查是否有全局通知状态更新 const notificationUpdated = wx.getStorageSync('meeting_notification_updated'); if (notificationUpdated) { console.log('检测到通知状态有更新:', notificationUpdated); // 清除标记,避免重复处理 wx.removeStorageSync('meeting_notification_updated'); // 如果有特定会议ID,只更新该会议的通知状态 if (notificationUpdated.meetingId) { const meetingItem = _this.data.reservationDataList.find( item => item.id === notificationUpdated.meetingId ); if (meetingItem) { _this.queryMeetingNotificationStatus(meetingItem); return; } } // 重新加载数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, }); _this.getDataList(); } else { // 重新加载数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, }); _this.getDataList(); } } } // 注意:不要在这里调用getStaffNotificationStatus,会在loadStaffInfoForItems中处理 }, // 取消预约一系列方法 cancelConfirm(e) { console.log('cancelConfirm', e); let status = e.currentTarget.dataset.status let _this = this; let id = e.currentTarget.dataset.id if (status == '4') { // 占用,占用的取消直接删除 Dialog.confirm({ title: '确认', message: '取消后不可撤销,是否确认?', }) .then(() => { // on confirm approveOrderDel({ id: id, }).then(res => { console.log('delApprove', res) if (res.code == 0) { // 刷新预约数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, showRejectReason: false }) Notify({ type: 'success', message: '已取消' }) _this.getDataList() } else { // 危险通知 Notify({ type: 'danger', message: res.msg }); } }) }) .catch(() => { // on cancel }); } else { // 其余的取消,需要输入原因 _this.setData({ cancelId: id, showCancelReason: true, cancelReason: '' }) } }, onCloseCancel(e) { let _this = this; _this.setData({ cancelId: '', showCancelReason: false, cancelReason: '' }) }, onChangeCancelReason(e) { let _this = this; _this.setData({ cancelReason: e.detail }) }, // 取消订单 cancelOrder() { let _this = this; let id = _this.data.cancelId let reason = _this.data.cancelReason if (id === '') { return } if (reason === '') { Notify('请输入取消原因!') return } cancelOrderRq({ id: id, content: reason }).then(res => { console.log('cancelOrderRq', res); if (res.code == 0) { // 刷新预约数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, showCancelReason: false }) _this.getDataList() } else { // 危险通知 Notify({ type: 'danger', message: res.msg }); } }) }, editConfirm(e) { let id = e.currentTarget.dataset.id this.setData({ editId: id, showEdit: true }) }, hideEdit() { this.setData({ showEdit: false }) }, editMode(e) { let _this = this if (e.detail.type === 1) { // 重选时间会议室 this.setData({ showEdit: false, timeShow: true }) } else { // 直接跳转 console.log('重新编辑会议基本信息!') this.setData({ showEdit: false, }) wx.navigateTo({ url: "/pages/meeting/meetingRoom/meetingOrder/meetingOrder?rId=" + _this.data.editId, }) } }, showTimePicker() { this.setData({ timeShow: true }); }, hideTimePicker() { this.setData({ timeShow: false }); }, // 跳转会议预约页面 goRes(e) { let _this = this let date = new Date(e.detail); let year = date.getFullYear() let month = date.getMonth() + 1 let day = date.getDate() // IOS不支持-,必须用/ let chooseTime = year + '/' + month + '/' + day + ' 00:00:00' let chooseTimeStr = new Date(chooseTime).getTime() // 加入rId参数,为预约id,用于重新修改 wx.navigateTo({ url: '/pages/meeting/meetingReservation/meetingReservation?rId=' + _this.data.editId + '&time=' + chooseTimeStr, }) }, pass(e) { let _this = this; let id = e.currentTarget.dataset.id Dialog.confirm({ title: '确认', message: '是否确认通过会议室申请?', }) .then(() => { // on confirm approveOrderRq({ id: id, content: '审核通过', operate: 'PASS' }).then(res => { console.log('passOrder', res) if (res.code == 0) { // 通知成功 Notify({ type: 'success', message: '已通过该申请!' }) // 先提示用户选择会务负责人,再刷新数据 wx.showModal({ title: '会务负责人', content: '请选择会议的音控组和会务服务组负责人', confirmText: '去选择', cancelText: '我知道了', success(res) { if (res.confirm) { // 点击"去选择",跳转到会务负责人页面 wx.navigateTo({ url: "/pages/meeting/meetingRoom/meetingStaff/meetingStaff?rId=" + id, }) } else { // 点击"我知道了",只刷新数据 console.log('用户选择稍后设置会务负责人') // 刷新预约数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, showRejectReason: false }) _this.getDataList() } } }) } else { // 危险通知 Notify({ type: 'danger', message: res.msg }); } }) }) .catch(() => { // on cancel }); }, // 驳回预约 rejectConfirm(e) { console.log('rejectConfirm', e); let _this = this; let id = e.currentTarget.dataset.id _this.setData({ rejectId: id, showRejectReason: true, rejectReason: '' }) }, onCloseReject(e) { let _this = this; _this.setData({ rejectId: '', showRejectReason: false, rejectReason: '' }) }, onChangeRejectReason(e) { let _this = this; _this.setData({ rejectReason: e.detail }) }, // 取消订单 rejectOrder() { let _this = this; let id = _this.data.rejectId let reason = _this.data.rejectReason if (id === '') { return } if (reason === '') { Notify('请输入驳回原因!') return } // 执行驳回方法 console.log('驳回,原因为' + reason) approveOrderRq({ id: id, content: reason, operate: 'REJECTED' }).then(res => { console.log('rejectOrder', res); if (res.code == 0) { // 刷新预约数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, showRejectReason: false }) Notify({ type: 'danger', message: '已驳回该申请!' }) _this.getDataList() } else { // 危险通知 Notify({ type: 'danger', message: res.msg }); } }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { // 取消注册通知状态更新监听器 const app = getApp(); if (app && app.unregisterNotificationStatusChange && this.notificationStatusChangeCallback) { app.unregisterNotificationStatusChange(this.notificationStatusChangeCallback); console.log('已取消注册全局通知状态更新监听器'); } }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { console.log('onPullDownRefresh', '页面相关事件处理函数--监听用户下拉动作'); let _this = this; // 重置数据 _this.setData({ reservationPageNum: 1, reservationDataList: [], reservationIsDataAll: false, }); // 重新获取数据 _this.getDataList(); // 停止下拉刷新动画 wx.stopPullDownRefresh(); // 提示用户 Notify({ type: 'success', message: '刷新成功' }); }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { console.log('onReachBottom', '页面上拉触底事件的处理函数'); let _this = this; // 如果数据已全部加载完成,则不再请求 if (_this.data.reservationIsDataAll) { Notify({ type: 'primary', message: '已加载全部数据' }); return; } // 显示加载中提示 wx.showLoading({ title: '加载更多...', mask: true }); // 延迟一下再加载,避免频繁请求 setTimeout(() => { // 获取数据 _this.getDataList(); wx.hideLoading(); }, 300); }, /** * 用户点击右上角分享 */ onShareAppMessage(e) { console.log('onShareAppMessage', e); let _this = this; let id = e.target.dataset.id; let detail = _this.data.reservationDataList.find(item => item.id == id) // let param = { title: detail.title, path: "/pages/meeting/invite/invite?id=" + id, imageUrl: app.IMG_NAME + detail.roomContent.indoorPicUrlFirst, } console.log('onShareAppMessage', param); return param; } })