feat(消息中心): 实现消息列表接口集成和未读消息显示
添加消息相关API接口文件并集成到消息中心页面 在个人中心页面显示未读消息数量 优化消息列表页面样式和空状态提示
Showing
3 changed files
with
73 additions
and
49 deletions
src/api/news.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-06-12 14:11:09 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-06-12 14:12:22 | ||
| 5 | + * @FilePath: /mlaj/src/api/news.js | ||
| 6 | + * @Description: 消息相关接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from './fn' | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + NEWS_LIST: '/srv/?a=website_msg&t=my_list', | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * @description: 我的消息列表 | ||
| 16 | + */ | ||
| 17 | +export const getNewsListAPI = (params) => fn(fetch.get(Api.NEWS_LIST, params)) |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-24 12:56:07 | 2 | * @Date: 2025-03-24 12:56:07 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-06-12 10:53:01 | 4 | + * @LastEditTime: 2025-06-12 15:34:41 |
| 5 | * @FilePath: /mlaj/src/views/profile/MessagesPage.vue | 5 | * @FilePath: /mlaj/src/views/profile/MessagesPage.vue |
| 6 | * @Description: 消息中心页面 | 6 | * @Description: 消息中心页面 |
| 7 | --> | 7 | --> |
| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | <van-list | 11 | <van-list |
| 12 | v-model:loading="loading" | 12 | v-model:loading="loading" |
| 13 | :finished="finished" | 13 | :finished="finished" |
| 14 | - finished-text="没有更多了" | 14 | + :finished-text="finishText" |
| 15 | @load="onLoad" | 15 | @load="onLoad" |
| 16 | class="px-4 py-4" | 16 | class="px-4 py-4" |
| 17 | > | 17 | > |
| ... | @@ -24,18 +24,38 @@ | ... | @@ -24,18 +24,38 @@ |
| 24 | <div class="p-4"> | 24 | <div class="p-4"> |
| 25 | <div class="flex justify-between items-start mb-2"> | 25 | <div class="flex justify-between items-start mb-2"> |
| 26 | <h3 class="text-base font-medium flex items-center"> | 26 | <h3 class="text-base font-medium flex items-center"> |
| 27 | - <span | 27 | + <span v-if="!message.isRead" class="w-2 h-2 bg-red-500 rounded-full mr-2"></span> |
| 28 | - v-if="!message.isRead" | 28 | + <!-- {{ message.title }} --> |
| 29 | - class="w-2 h-2 bg-red-500 rounded-full mr-2" | 29 | + 消息 |
| 30 | - ></span> | ||
| 31 | - {{ message.title }} | ||
| 32 | </h3> | 30 | </h3> |
| 33 | - <span class="text-xs text-gray-500">{{ message.time }}</span> | 31 | + <span class="text-xs text-gray-500">{{ message.created_time }}</span> |
| 34 | </div> | 32 | </div> |
| 35 | - <p class="text-sm text-gray-600 line-clamp-2">{{ message.content }}</p> | 33 | + <p class="text-sm text-gray-600 line-clamp-2">{{ message.note }}</p> |
| 36 | </div> | 34 | </div> |
| 37 | </FrostedGlass> | 35 | </FrostedGlass> |
| 38 | </van-list> | 36 | </van-list> |
| 37 | + | ||
| 38 | + <!-- 无数据提示 --> | ||
| 39 | + <div | ||
| 40 | + v-if="!loading && messages.length === 0" | ||
| 41 | + class="flex flex-col items-center justify-center py-12" | ||
| 42 | + > | ||
| 43 | + <svg | ||
| 44 | + xmlns="http://www.w3.org/2000/svg" | ||
| 45 | + class="h-16 w-16 text-gray-300" | ||
| 46 | + fill="none" | ||
| 47 | + viewBox="0 0 24 24" | ||
| 48 | + stroke="currentColor" | ||
| 49 | + > | ||
| 50 | + <path | ||
| 51 | + stroke-linecap="round" | ||
| 52 | + stroke-linejoin="round" | ||
| 53 | + stroke-width="2" | ||
| 54 | + d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" | ||
| 55 | + /> | ||
| 56 | + </svg> | ||
| 57 | + <p class="mt-4 text-gray-500">暂无消息</p> | ||
| 58 | + </div> | ||
| 39 | </div> | 59 | </div> |
| 40 | </AppLayout> | 60 | </AppLayout> |
| 41 | </template> | 61 | </template> |
| ... | @@ -47,6 +67,9 @@ import AppLayout from '@/components/layout/AppLayout.vue'; | ... | @@ -47,6 +67,9 @@ import AppLayout from '@/components/layout/AppLayout.vue'; |
| 47 | import FrostedGlass from '@/components/ui/FrostedGlass.vue'; | 67 | import FrostedGlass from '@/components/ui/FrostedGlass.vue'; |
| 48 | import { useTitle } from '@vueuse/core'; | 68 | import { useTitle } from '@vueuse/core'; |
| 49 | 69 | ||
| 70 | +// 导入接口 | ||
| 71 | +import { getNewsListAPI } from '@/api/news'; | ||
| 72 | + | ||
| 50 | const $route = useRoute(); | 73 | const $route = useRoute(); |
| 51 | const $router = useRouter(); | 74 | const $router = useRouter(); |
| 52 | useTitle($route.meta.title); | 75 | useTitle($route.meta.title); |
| ... | @@ -55,46 +78,23 @@ const router = useRouter(); | ... | @@ -55,46 +78,23 @@ const router = useRouter(); |
| 55 | const loading = ref(false); | 78 | const loading = ref(false); |
| 56 | const finished = ref(false); | 79 | const finished = ref(false); |
| 57 | const messages = ref([]); | 80 | const messages = ref([]); |
| 81 | +const limit = ref(10); | ||
| 58 | const page = ref(0); | 82 | const page = ref(0); |
| 59 | - | 83 | +const finishText = ref('没有更多了'); |
| 60 | -// 模拟消息数据 | ||
| 61 | -const mockMessages = [ | ||
| 62 | - { | ||
| 63 | - id: 1, | ||
| 64 | - title: '课程更新通知', | ||
| 65 | - content: '您关注的课程《亲子教育入门》已更新最新一期内容,快来查看吧!', | ||
| 66 | - time: '2024-01-10 10:30', | ||
| 67 | - isRead: false | ||
| 68 | - }, | ||
| 69 | - { | ||
| 70 | - id: 2, | ||
| 71 | - title: '活动提醒', | ||
| 72 | - content: '您报名的「亲子互动工作坊」将于本周六下午2点开始,请准时参加。', | ||
| 73 | - time: '2024-01-09 15:20', | ||
| 74 | - isRead: true | ||
| 75 | - }, | ||
| 76 | - { | ||
| 77 | - id: 3, | ||
| 78 | - title: '系统通知', | ||
| 79 | - content: '为了给您提供更好的服务,我们的App将于今晚凌晨2点进行系统升级维护。', | ||
| 80 | - time: '2024-01-08 18:00', | ||
| 81 | - isRead: false | ||
| 82 | - } | ||
| 83 | -]; | ||
| 84 | 84 | ||
| 85 | // 加载更多 | 85 | // 加载更多 |
| 86 | -const onLoad = () => { | 86 | +const onLoad = async() => { |
| 87 | - // 模拟异步加载数据 | 87 | + const res = await getNewsListAPI({ page: page.value, limit: limit.value }); |
| 88 | - setTimeout(() => { | 88 | + if (res.code) { |
| 89 | - if (page.value === 0) { | 89 | + messages.value = [...messages.value, ...res.data]; |
| 90 | - messages.value = mockMessages; | 90 | + finished.value = res.data.length < limit.value; |
| 91 | - } else { | ||
| 92 | - // 模拟没有更多数据 | ||
| 93 | - finished.value = true; | ||
| 94 | - } | ||
| 95 | - loading.value = false; | ||
| 96 | page.value++; | 91 | page.value++; |
| 97 | - }, 1000); | 92 | + loading.value = false; |
| 93 | + } else { | ||
| 94 | + loading.value = false; | ||
| 95 | + finished.value = true; | ||
| 96 | + finishText.value = ''; | ||
| 97 | + } | ||
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | // 更新消息已读状态 | 100 | // 更新消息已读状态 |
| ... | @@ -107,6 +107,7 @@ const updateMessageReadStatus = (messageId) => { | ... | @@ -107,6 +107,7 @@ const updateMessageReadStatus = (messageId) => { |
| 107 | 107 | ||
| 108 | // 处理消息点击 | 108 | // 处理消息点击 |
| 109 | const handleMessageClick = (message) => { | 109 | const handleMessageClick = (message) => { |
| 110 | + return; | ||
| 110 | updateMessageReadStatus(message.id); | 111 | updateMessageReadStatus(message.id); |
| 111 | router.push(`/profile/messages/${message.id}`); | 112 | router.push(`/profile/messages/${message.id}`); |
| 112 | }; | 113 | }; | ... | ... |
| ... | @@ -143,6 +143,12 @@ onMounted(async () => { | ... | @@ -143,6 +143,12 @@ onMounted(async () => { |
| 143 | if (code) { | 143 | if (code) { |
| 144 | profile.value = data.user; | 144 | profile.value = data.user; |
| 145 | checkIns.value = data.checkin; | 145 | checkIns.value = data.checkin; |
| 146 | + // 处理消息中心的未读消息数量 | ||
| 147 | + menuItems3.value.forEach(item => { | ||
| 148 | + if (item.path === '/profile/messages') { | ||
| 149 | + item.badge = data.unread_msg_count || 0; | ||
| 150 | + } | ||
| 151 | + }); | ||
| 146 | } | 152 | } |
| 147 | }) | 153 | }) |
| 148 | 154 | ||
| ... | @@ -221,7 +227,7 @@ const menuItems1 = [ | ... | @@ -221,7 +227,7 @@ const menuItems1 = [ |
| 221 | icon: "clock", | 227 | icon: "clock", |
| 222 | title: "学习记录", | 228 | title: "学习记录", |
| 223 | path: "/profile/learning-records", | 229 | path: "/profile/learning-records", |
| 224 | - badge: "NEW", | 230 | + badge: "", |
| 225 | }, | 231 | }, |
| 226 | { | 232 | { |
| 227 | icon: "user", | 233 | icon: "user", |
| ... | @@ -258,12 +264,12 @@ const menuItems2 = [ | ... | @@ -258,12 +264,12 @@ const menuItems2 = [ |
| 258 | }, | 264 | }, |
| 259 | ]; | 265 | ]; |
| 260 | 266 | ||
| 261 | -const menuItems3 = [ | 267 | +const menuItems3 = ref([ |
| 262 | { | 268 | { |
| 263 | icon: "email", | 269 | icon: "email", |
| 264 | title: "消息中心", | 270 | title: "消息中心", |
| 265 | path: "/profile/messages", | 271 | path: "/profile/messages", |
| 266 | - badge: "3", | 272 | + badge: "", |
| 267 | }, | 273 | }, |
| 268 | { | 274 | { |
| 269 | icon: "question", | 275 | icon: "question", |
| ... | @@ -275,7 +281,7 @@ const menuItems3 = [ | ... | @@ -275,7 +281,7 @@ const menuItems3 = [ |
| 275 | title: "设置", | 281 | title: "设置", |
| 276 | path: "/profile/settings", | 282 | path: "/profile/settings", |
| 277 | }, | 283 | }, |
| 278 | -]; | 284 | +]); |
| 279 | 285 | ||
| 280 | const handleCheckin = () => { | 286 | const handleCheckin = () => { |
| 281 | if (checkinData.value.length) { | 287 | if (checkinData.value.length) { | ... | ... |
-
Please register or login to post a comment