/** * 消息服务(API_INVENTORY 行 75-79, 84-87) * * 封装:会话列表 / 详情 / 历史消息 / 发送 / 未读数 + 通知列表 / 标记已读。 * 关键不变量(AGENTS.md): * - 第 3 条:Mutual Match 后才能聊天——后端会返回 MATCH_REQUIRED, * 前端在 send 失败时给出对应引导,不在 services 层做客户端校验。 * - 第 4 条:Block/Unmatch 后会话 canSendMessage=false,send 直接拒绝。 * - 第 7 条:工作人员不可看私人聊天——本层无任何 staff 入口。 * 消息发送走幂等键 messageId(规范 §106),防止弱网下重复入库。 */ const api = require('../utils/api'); /** * 获取会话列表(API_INVENTORY 行 75) * @param {{ cursor?: string, pageSize?: number }} params * @returns {Promise<{ items: Array, nextCursor: string|null }>} */ function getConversations(params = {}) { return api.get('/conversations', params); } /** * 获取会话详情(API_INVENTORY 行 76) * @param {string} conversationId * @returns {Promise} */ function getConversation(conversationId) { return api.get(`/conversations/${encodeURIComponent(conversationId)}`); } /** * 发送消息(API_INVENTORY 行 77) * @param {string} conversationId * @param {{ content: string, messageId: string, clientSentAt: number }} payload * @returns {Promise<{ messageId: string, sentAt: number, status: 'sent' }>} */ function sendMessage(conversationId, payload) { // 幂等键 = 客户端生成的 messageId(规范 §106),后端去重 return api.post( `/conversations/${encodeURIComponent(conversationId)}/messages`, payload, undefined, payload.messageId, ); } /** * 获取消息历史(API_INVENTORY 行 78) * @param {string} conversationId * @param {{ before?: string, after?: string, pageSize?: number }} params * @returns {Promise<{ items: Array, nextCursor: string|null, hasMore: boolean }>} */ function getMessages(conversationId, params = {}) { return api.get(`/conversations/${encodeURIComponent(conversationId)}/messages`, params); } /** * 获取会话未读数(API_INVENTORY 行 79) * @param {string} conversationId * @returns {Promise<{ unreadCount: number }>} */ function getUnreadCount(conversationId) { return api.get(`/conversations/${encodeURIComponent(conversationId)}/unread`); } /** * 获取通知列表(API_INVENTORY 行 84) * @param {{ cursor?: string, pageSize?: number, type?: string }} params * @returns {Promise<{ items: Array, nextCursor: string|null }>} */ function getNotifications(params = {}) { return api.get('/notifications', params); } /** * 标记单条通知已读(API_INVENTORY 行 85) * @param {string} notificationId * @returns {Promise<{ read: true }>} */ function markNotificationRead(notificationId) { return api.put(`/notifications/${encodeURIComponent(notificationId)}/read`, {}, undefined, `notif-read:${notificationId}:${Date.now()}`); } /** * 全部通知已读(API_INVENTORY 行 86) * @returns {Promise<{ updated: number }>} */ function markAllNotificationsRead() { return api.put('/notifications/read-all', {}, undefined, 'notif-read-all:' + Date.now()); } /** * 通知未读总数(API_INVENTORY 行 87) * @returns {Promise<{ unreadCount: number }>} */ function getNotificationsUnreadCount() { return api.get('/notifications/unread-count'); } module.exports = { getConversations, getConversation, sendMessage, getMessages, getUnreadCount, getNotifications, markNotificationRead, markAllNotificationsRead, getNotificationsUnreadCount, };