diff --git a/client/mobile/api.ts b/client/mobile/api.ts index bc55bc6..8941630 100644 --- a/client/mobile/api.ts +++ b/client/mobile/api.ts @@ -4,7 +4,8 @@ import 'dayjs/locale/zh-cn'; import type { User, FileLibrary, FileCategory, ThemeSettings, SystemSetting, SystemSettingGroupData, - LoginLocation, LoginLocationDetail + LoginLocation, LoginLocationDetail, + Message, MessageType, MessageStatus } from '../share/types.ts'; @@ -575,6 +576,7 @@ export const SystemAPI = { } catch (error) { throw error; } + }, // 更新系统设置 @@ -598,3 +600,96 @@ export const SystemAPI = { } }; + +// 消息API响应类型 +export interface MessageResponse { + message: string; + data?: any; +} + +export interface MessagesResponse { + data: Message[]; + pagination: { + total: number; + current: number; + pageSize: number; + totalPages: number; + }; +} + +export interface UnreadCountResponse { + count: number; +} + +// 消息API +export const MessageAPI = { + // 获取消息列表 + getMessages: async (params?: { + page?: number, + pageSize?: number, + type?: MessageType, + status?: MessageStatus + }): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages`, { params }); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取消息详情 + getMessage: async (id: number): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 发送消息 + sendMessage: async (data: { + title: string, + content: string, + type: MessageType, + receiver_ids: number[] + }): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/messages`, data); + return response.data; + } catch (error) { + throw error; + } + }, + + // 删除消息(软删除) + deleteMessage: async (id: number): Promise => { + try { + const response = await axios.delete(`${API_BASE_URL}/messages/${id}`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 获取未读消息数量 + getUnreadCount: async (): Promise => { + try { + const response = await axios.get(`${API_BASE_URL}/messages/unread-count`); + return response.data; + } catch (error) { + throw error; + } + }, + + // 标记消息为已读 + markAsRead: async (id: number): Promise => { + try { + const response = await axios.post(`${API_BASE_URL}/messages/${id}/read`); + return response.data; + } catch (error) { + throw error; + } + } +}; \ No newline at end of file diff --git a/client/mobile/mobile_app.tsx b/client/mobile/mobile_app.tsx index 0690917..8430e30 100644 --- a/client/mobile/mobile_app.tsx +++ b/client/mobile/mobile_app.tsx @@ -18,7 +18,7 @@ import HomePage from './pages_index.tsx'; import LoginPage from './pages_login.tsx'; import { GlobalConfig } from "../share/types.ts"; import { ExclamationTriangleIcon, HomeIcon, BellIcon, UserIcon } from '@heroicons/react/24/outline'; - +import { NotificationsPage } from './pages_messages.tsx'; // 设置中文语言 dayjs.locale('zh-cn'); @@ -258,25 +258,6 @@ const ProfilePage = () => { ); }; -// 添加通知页面组件 -const NotificationsPage = () => ( -
-

通知

-
-
-

系统通知

-

欢迎使用移动应用!

-

今天 10:00

-
-
-

活动提醒

-

您有一个新的活动邀请

-

昨天 14:30

-
-
-
-); - // 移动端布局组件 - 包含底部导航 const MobileLayout = () => { const location = useLocation(); diff --git a/client/mobile/pages_messages.tsx b/client/mobile/pages_messages.tsx new file mode 100644 index 0000000..eab6d12 --- /dev/null +++ b/client/mobile/pages_messages.tsx @@ -0,0 +1,107 @@ +import React from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; +import { BellIcon } from '@heroicons/react/24/outline'; + + +// 添加通知页面组件 +import { MessageAPI } from './api.ts'; + +export const NotificationsPage = () => { + const queryClient = useQueryClient(); + + // 获取消息列表 + const { data: messages, isLoading } = useQuery({ + queryKey: ['messages'], + queryFn: () => MessageAPI.getMessages(), + }); + + // 获取未读消息数量 + const { data: unreadCount } = useQuery({ + queryKey: ['unreadCount'], + queryFn: () => MessageAPI.getUnreadCount(), + }); + + // 标记消息为已读 + const markAsReadMutation = useMutation({ + mutationFn: (id: number) => MessageAPI.markAsRead(id), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['messages'] }); + queryClient.invalidateQueries({ queryKey: ['unreadCount'] }); + }, + }); + + // 删除消息 + const deleteMutation = useMutation({ + mutationFn: (id: number) => MessageAPI.deleteMessage(id), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['messages'] }); + }, + }); + + const handleMarkAsRead = (id: number) => { + markAsReadMutation.mutate(id); + }; + + const handleDelete = (id: number) => { + if (confirm('确定要删除这条消息吗?')) { + deleteMutation.mutate(id); + } + }; + + if (isLoading) { + return ( +
+

通知

+
+
+
+
+ ); + } + + return ( +
+
+

通知

+ {unreadCount && unreadCount.count > 0 ? ( +
+ + {unreadCount.count}条未读 +
+ ) : null} +
+ +
+ {messages?.data.map((message) => ( +
+
+

{message.title}

+
+ + +
+
+

{message.content}

+

+ {dayjs(message.created_at).format('YYYY-MM-DD HH:mm')} +

+
+ ))} +
+
+ ); +}; \ No newline at end of file