agri-app/pages/news/index.vue

539 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="message-center-page">
<!-- 顶部导航栏 -->
<view class="nav-bar">
<view class="nav-left">
<text class="nav-title" @click="navBack">{{ title }}&nbsp;</text>
<image style="width: 25rpx; height: 25rpx; margin-left: 8rpx; "
@click="navBack" src="https://img.xiaoces.com/photos/next.png"/>
<uni-drawer ref="showLeft" mode="left" :width="320" @change="change($event,'showLeft')">
<view class="close">
<button @click="closeDrawer('showLeft')"><text class="word-btn-white">暂未开发</text></button>
</view>
</uni-drawer>
</view>
<view class="nav-right">
<!-- 把文字 + 图标放在同一个 nav-btn -->
<view class="nav-btn" @click="clearUnread">
<text>清除未读</text>
<uni-icons type="trash" size="24" color="#666" />
</view>
<text class="divider"> | </text>
<text class="nav-btn" @click="openSetting"></text>
</view>
</view>
<!-- -->
<view class="notice-out">
<view class="notice-bar" v-if="isShowTips">
<view class="notice-left">
<uni-icons @click="goToClose" style="margin-right: 12rpx" type="closeempty" color="#FF6D00" size="15"/>
<text class="notice-text">系统通知未开启报警消息无法通知</text>
</view>
<view class="notice-btn" @click="goToOpen"></view>
</view>
</view>
<!-- -->
<view class="func-wrap">
<view class="func-item" @click="goToSubscribe">
<view class="func-icon">
<image style="width: 40rpx; height: 30rpx; "
src="https://img.xiaoces.com/photos/news/new2.png"/>
</view>
<view class="func-title">消息订阅</view>
<view class="func-desc">成员收不到设备/应用消息?</view>
</view>
<view class="func-item" @click="goToAI">
<view class="func-icon">
<image style="width: 40rpx; height: 30rpx; "
src="https://img.xiaoces.com/photos/news/ai1.png"/>
</view>
<view class="func-title">AI识别</view>
<view class="func-desc">AI识别精准过滤无效报警</view>
</view>
</view>
<uni-swipe-action ref="swipeAction" class="message-list">
<uni-swipe-action-item
v-for="(item, index) in msgList"
:right-options="options"
:key="index"
@click="deleteItem($event, item)"
>
<view class="message-item" @click="handleItemClick(item)">
<view class="item-icon-wrap">
<view class="item-icon" :style="{ backgroundColor: item.iconBg }">
<image mode="aspectFit" :style="{width: item.width,
height: '70rpx' }" :src="item.imgUrl" />
</view>
<view v-if="item.numBadge>0 && item.badge" class="item-badge"></view>
</view>
<view class="item-content">
<view class="item-title">
<text>{{ item.title }}</text>
<view class="item-time">
<uni-dateformat v-if="item.createTime" :date="item.createTime" :format="formatTime(item.createTime)"
:threshold="[60000, 3600000]"></uni-dateformat>
<text v-else>--</text>
</view>
</view>
<view class="item-desc">
<view v-if="item.content">{{ item.content }}</view>
<view v-else>暂无更多{{item.title.substring(0,2)}}消息 ... </view>
<view v-if="item.numBadge>0 && !item.badge">
<uni-badge :text="item.numBadge" type="error" size="mini" />
</view>
</view>
</view>
</view>
</uni-swipe-action-item>
</uni-swipe-action>
<!-- 底部提示 -->
<uni-divider-text margin="10rpx 0"
width="50%"
font-size="24rpx"
lineText="只展示最近7天的消息"/>
</view>
</template>
<script>
import UniDividerText from "../../components/uni-divider/uni-divider-text.vue";
import {isTodayDate,formatTime} from "@/utils/agri";
import {getMsgOverview, removeBatch, updateRead} from "@/api/warn/message";
import * as mqttUtil from "@/utils/mqtt";
export default {
components: {
UniDividerText
},
data() {
return {
title: '消息中心',
isShowTips: true,
messageList: [],
msgList: [
{
// video111 / camera_
imgUrl: 'https://img.xiaoces.com/photos/news/camera_.png', // 对应视频中心
title: '视频中心',
msgType: 'video',
badge: true,
numBadge: null, // 有值则显示角标
width: '60rpx'
},
{
// device imei1 device_status3
imgUrl: 'https://img.xiaoces.com/photos/news/device_status3.png', // 对应设备状态
// iconBg: '#4285F4',
msgType: 'status',
title: '设备状态',
badge: false,
numBadge: null,
width: '60rpx'
},
{
// notice_1 notice_2 notice_
imgUrl: 'https://img.xiaoces.com/photos/news/notice_.png', // 对应系统通知
iconBg: '#FFA726',
msgType: 'notice',
title: '系统通知',
badge: false,
numBadge: null, // 无值则不显示
width: '40rpx'
},
{
// play1 play
imgUrl: 'https://img.xiaoces.com/photos/news/play1.png',
// iconBg: '#FFA726',
title: '活动中心',
msgType: 'event',
badge: false,
numBadge: null, // 无值则不显示
width: '100rpx'
}
],
options: [
{
text: '删除',
style: {
backgroundColor: '#E83A30'
}
}
],
}
},
onShow() {
console.info("消息中心监听")
mqttUtil.setOnMessageCallback(this.ackMsg);
this.getMsgOverview();
},
onHide() {
console.info("消息中心取消监听")
mqttUtil.removeOnMessageCallback();
},
onUnload() {
console.info("消息中心取消监听")
mqttUtil.removeOnMessageCallback();
},
beforeDestroy() {
console.info("消息中心取消监听")
mqttUtil.removeOnMessageCallback();
},
methods: {
isTodayDate,
formatTime,
navBack() {
// 消息推送设置
this.showDrawer('showLeft');
console.log('点击消息中心:消息推送设置')
},
clearUnread() {
// 全部已读
uni.showModal({
title: '操作提示',
content: `确认全部已读?`,
cancelText: '取消',
confirmText: '确定',
success: (res) => {
var unReadNum = this.messageList.filter(item => item.readStatus === 0).length;
if (unReadNum === 0) {
return;
}
updateRead({}).then(response => {
if (response.code === 200) {
this.getMsgOverview();
}
})
}
})
},
openSetting() {
// 当前页面勿扰模式设置
this.$modal.showToast('模块建设中~')
console.log('打开通知设置:当前页面勿扰模式设置')
},
goToOpen() {
this.$modal.showToast('模块建设中~')
console.log('去开启系统通知:同左侧消息中心')
},
goToClose() {
this.isShowTips = false
this.$modal.showToast('模块建设中~')
console.log('关闭系统通知提示')
},
goToSubscribe() {
this.$modal.showToast('模块建设中~')
console.log('进入消息订阅:暂未开发')
},
goToAI() {
this.$modal.showToast('模块建设中~')
console.log('进入AI识别暂未开发')
},
getMsgOverview() {
getMsgOverview().then(response => {
if (response.code === 200) {
this.messageList = response.data;
// this.messageList.forEach((msgItem, msgIndex) => {
// this.msgList[msgItem.msgType].numBadge = msgItem.unreadCount || null
// this.msgList[msgItem.msgType].content = msgItem.content || null
// this.msgList[msgItem.msgType].createTime = msgItem.createTime || null
// })
this.msgList.forEach((item, index) => {
item.numBadge = null;
item.content = null;
item.createTime = null;
this.messageList.forEach((msgItem, msgIndex) => {
if (msgItem.msgType === item.msgType) {
item.numBadge = msgItem.unreadCount
item.content = msgItem.content
item.createTime = msgItem.createTime
}
})
});
if (this.messageList.filter(item => item.readStatus === 0).length>0) {
uni.showTabBarRedDot({index: 2})
} else {
uni.hideTabBarRedDot({index: 2 })
}
}
})
},
handleItemClick(item) {
this.$modal.showToast('敬请期待~')
console.log('点击消息:', item.title)
if (item.title === '系统通知') {
this.$tab.navigateTo('/pages/news/subpages/sysNotice/index');
} else if (item.title === '活动中心') {
this.$tab.navigateTo('/pages/news/subpages/eventCenter/index');
} else if (item.title === '视频中心') {
this.$tab.navigateTo('/pages/news/subpages/videoCenter/index');
} else if (item.title === '设备状态') {
this.$tab.navigateTo('/pages/news/subpages/deviceCenter/index');
}
},
deleteItem(event, item) {
// 删除当条消息
uni.showModal({
title: '操作提示',
content: `确认删除${item.title}`,
cancelText: '取消',
confirmText: '确定',
success: (res) => {
removeBatch({msgType:item.msgType}).then(response => {
if (response.code === 200) {
this.getMsgOverview()
}
})
}
},)
},
// 打开窗口
showDrawer(e) {
this.$refs[e].open()
},
// 关闭窗口
closeDrawer(e) {
this.$refs[e].close()
},
// 抽屉状态发生变化触发
change(e, type) {
console.log((type === 'showLeft' ? '左窗口' : '右窗口') + (e ? '打开' : '关闭'));
this[type] = e
},
ackMsg(topic, payload) {
var words = topic.split("/");
if (words.length!==3) {
return;
}
const agriList = uni.getStorageSync('agri_list')
if (agriList.length === 0 || !agriList.includes(words[1])) {
return;
}
const tag = topic.match(/[^/]+$/)?.[0]
var regex = {
alarm:1,
notice:2,
event:3
}
if (!regex[tag]) return;
let msgData = {};
// 优化捕获JSON解析异常
try {
msgData = JSON.parse(payload);
var msg = msgData.msgType;
if (!regex[tag]) return;
const item = this.msgList[regex[tag]];
item.numBadge+=1;
item.content = msg.content;
item.createTime = msg.createTime;
uni.showTabBarRedDot({index: 2})
} catch (e) {
console.error("MQTT消息解析失败", e, payload);
}
}
}
}
</script>
<style lang="scss" scoped>
/* 页面全屏 + 禁止横向滚动 */
.message-center-page {
min-height: 100vh;
height: calc(100vh - 180rpx);
/* #ifdef MP-WEIXIN */
height: calc(100vh - var(--status-bar-height) - 180rpx);
/* #endif */
background: linear-gradient(180deg, #e8f0ff 0%, #f5f7fa 60%, #ffffff 100%);
padding-bottom: 120rpx;
box-sizing: border-box;
overflow-x: hidden; /* 禁止横向滚动条 */
width: 100%;
}
/* 顶部导航栏 */
.nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 44rpx 30rpx 20rpx;
// #ifdef MP-WEIXIN
padding-top: calc(140rpx + var(--status-bar-height));
// #endif
// #ifdef H5
padding-top: 44px;
// #endif
.nav-left {
display: flex;
align-items: center;
color: #333;
.nav-title {
font-size: 36rpx;
font-weight: 500;
}
}
.nav-right {
display: flex;
align-items: center;
/* 核心:文字+图标同行+居中 */
.nav-btn {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666;
uni-icons {
margin-left: 8rpx;
}
}
.divider {
margin: 0 20rpx;
color: #c5c3c3;
font-size: 28rpx;
}
}
}
.notice-out {
margin: 20rpx 30rpx;
}
/* 系统通知提示条 */
.notice-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
background-color: #FFF3E0;
border-radius: 12rpx;
.notice-left {
display: flex;
align-items: center;
.notice-text {
font-size: 28rpx;
color: #E65100;
}
}
.notice-btn {
padding: 8rpx 20rpx;
background-color: #FF9800;
color: #fff;
font-size: 26rpx;
border-radius: 20rpx;
}
}
/* 功能入口区 */
.func-wrap {
display: flex;
margin: 0 30rpx 20rpx;
gap: 20rpx;
.func-item {
flex: 1;
padding: 24rpx;
background-color: #fff;
border-radius: 12rpx;
.func-icon {
margin-bottom: 12rpx;
}
.func-title {
font-size: 30rpx;
color: #333;
font-weight: 500;
margin-bottom: 8rpx;
}
.func-desc {
font-size: 26rpx;
color: #666;
line-height: 1.4;
}
}
}
/* 消息列表 ———— 核心修复:不挤时间 + 不换行 */
.message-list {
background-color: #fff;
border-radius: 12rpx;
.message-item {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
width: 100%;
box-sizing: border-box;
.item-icon-wrap {
position: relative;
margin-right: 24rpx;
flex-shrink: 0; /* 图片不被挤压 */
.item-icon {
width: 60rpx;
height: 60rpx;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
}
.item-badge {
position: absolute;
top: -6rpx;
right: -6rpx;
width: 20rpx;
height: 20rpx;
background-color: #f5222d;
border-radius: 50%;
border: 2rpx solid #fff;
}
}
/* 核心:内容区域不挤压时间 */
.item-content {
flex: 1;
min-width: 0; /* 必须加防止flex溢出 */
display: flex;
flex-direction: column;
.item-title {
font-size: 32rpx;
color: #333;
margin-bottom: 8rpx;
display: flex;
align-items: center;
justify-content: space-between;
text:first-child {
flex-shrink: 0;
}
}
.item-desc {
font-size: 26rpx;
color: #999;
line-height: 1.4;
max-height: 18.19px;
display: flex;
align-items: center;
justify-content: space-between;
view:first-child {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex: 1;
min-width: 0;
}
view:last-child {
flex-shrink: 0;
}
}
.item-time {
font-size: 26rpx;
color: #999;
flex-shrink: 0;
}
}
}
}
</style>