index.vue
3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!--
* @Date:2026-02-03 21:26:58
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-02-12 21:09:32
* @FilePath: /manulife-weapp/src/pages/message-detail/index.vue
* @Description: 消息详情页
-->
<template>
<view class="min-h-screen bg-gray-50 pb-safe">
<NavHeader title="消息详情" />
<view v-if="detail" class="p-4">
<!-- 消息卡片 -->
<view class="bg-white rounded-lg p-5 shadow-sm">
<!-- 标题区域 (模拟) -->
<view class="mb-3">
<text class="text-xl font-bold text-gray-900 leading-snug block">
{{ detail.title || '系统消息通知' }}
</text>
</view>
<!-- 发布时间 -->
<view class="mb-6 flex items-center">
<text class="text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded">
{{ detail.created_time }}
</text>
</view>
<!-- 分割线 -->
<view class="h-px bg-gray-100 w-full mb-6"></view>
<!-- 内容区域 -->
<view class="rich-text-content">
<rich-text :nodes="formattedContent" />
</view>
</view>
</view>
<!-- 加载中 -->
<view v-else-if="loading" class="flex justify-center py-10">
<view class="w-8 h-8 border-4 border-gray-200 border-t-blue-600 rounded-full animate-spin"></view>
</view>
<!-- 错误/空状态 -->
<nut-empty v-else description="未找到消息内容" image="error" />
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { useLoad } from '@tarojs/taro'
import NavHeader from '@/components/navigation/NavHeader.vue'
import { detailAPI } from '@/api/news'
import { useUserStore } from '@/stores/user'
const detail = ref(null)
const loading = ref(true)
/**
* @description 格式化富文本内容,处理图片宽度等问题
*/
const formattedContent = computed(() => {
if (!detail.value?.note) return ''
// 简单的正则替换,确保图片宽度不超过容器
const content = detail.value.note.replace(
/<img/g,
'<img style="max-width:100%;height:auto;display:block;border-radius:8px;margin:10px 0;"'
)
return content
})
/**
* @description 获取消息详情
* @param {string|number} id 消息ID
*/
const fetchDetail = async (id) => {
loading.value = true
try {
const res = await detailAPI({ i: id })
if (res.code === 1) {
// 模拟标题数据,实际项目中应由后端返回
// 这里为了演示效果,如果后端没有返回 title,就模拟一个
const mockTitle = '关于系统维护升级的通知公告'
detail.value = {
...res.data,
title: res.data.title || mockTitle
}
// 查看消息后刷新用户信息,更新未读消息数
const userStore = useUserStore()
await userStore.fetchUserInfo(true)
}
} catch (err) {
console.error('获取消息详情失败:', err)
} finally {
loading.value = false
}
}
useLoad((options) => {
if (options.id) {
fetchDetail(options.id)
}
})
</script>
<style lang="less">
.rich-text-content {
font-size: 30rpx; /* 稍微调大字号提升阅读体验 */
color: #333;
line-height: 1.8;
text-align: justify; /* 两端对齐 */
/* 确保富文本样式正确 */
p {
margin-bottom: 24rpx;
}
/* 列表样式优化 */
ul, ol {
padding-left: 20px;
margin-bottom: 20rpx;
}
li {
margin-bottom: 10rpx;
}
}
</style>