/** * 用户资料服务(API_INVENTORY 行 17-25, 68-70) * * 封装:本人资料、择偶条件、生活照、隐私设置、审核状态、关系状态切换。 * 严格区分 GET 与 PUT,避免误操作;PUT 调用走幂等键防重。 * 自我介绍/择偶条件字数限制由 stores/profileStore 校验,本层只负责传输。 */ const api = require('../utils/api'); /** * 获取本人资料(API_INVENTORY 行 17) * @returns {Promise} */ function getProfile() { return api.get('/me/profile'); } /** * 更新本人资料(API_INVENTORY 行 18) * @param {Partial} payload * @returns {Promise} 服务端返回的最新资料 */ function updateProfile(payload) { // PUT 默认幂等:用 userId + 字段指纹作为幂等键,避免重复提交时脏写 const idempotencyKey = 'profile-put:' + (payload && payload.userId || 'me') + ':' + Date.now(); return api.put('/me/profile', payload, undefined, idempotencyKey); } /** * 获取择偶条件(API_INVENTORY 行 19) * @returns {Promise} */ function getPreferences() { return api.get('/me/preferences'); } /** * 更新择偶条件(API_INVENTORY 行 20) * @param {Partial} payload * @returns {Promise} */ function updatePreferences(payload) { const idempotencyKey = 'preferences-put:' + Date.now(); return api.put('/me/preferences', payload, undefined, idempotencyKey); } /** * 获取生活照列表(API_INVENTORY 行 21) * @returns {Promise<{ photos: Array<{ photoId: string, url: string, status: string }> }>} */ function getPhotos() { return api.get('/me/photos'); } /** * 删除生活照(API_INVENTORY 行 21b) * @param {string} photoId * @returns {Promise} */ function deletePhoto(photoId) { return api.delete(`/me/photos/${photoId}`); } /** * 设置主头像(将指定照片设为主头像) * @param {string} photoId * @returns {Promise<{ avatarUrl: string }>} */ function setMainPhoto(photoId) { const idempotencyKey = 'photo-main:' + photoId + ':' + Date.now(); return api.put(`/me/photos/${photoId}/main`, {}, undefined, idempotencyKey); } /** * 申请照片上传凭证(API_INVENTORY 行 22) * @param {{ fileName: string, contentType?: string }} payload * @returns {Promise<{ uploadUrl: string, photoId: string, expiresAt: number, accessUrl: string }>} */ function requestUploadToken(payload) { return api.post('/me/photos/upload-token', payload, undefined, payload.fileName); } /** * 获取隐私设置(API_INVENTORY 行 23) * @returns {Promise} */ function getPrivacySettings() { return api.get('/me/privacy-settings'); } /** * 更新隐私设置(API_INVENTORY 行 24) * @param {Partial} payload * @returns {Promise} */ function updatePrivacySettings(payload) { const idempotencyKey = 'privacy-put:' + Date.now(); return api.put('/me/privacy-settings', payload, undefined, idempotencyKey); } /** * 获取审核状态(API_INVENTORY 行 25,REST §36-39) * * 服务端返回结构: * { * status: 'not_submitted' | 'pending' | 'approved' | 'need_edit' | 'rejected', * items: [ * { itemType: 'avatar'|'self_intro'|'basic'|'lifestyle'|'intent'|'preference'|'interests', * status: 'pending'|'approved'|'need_edit'|'rejected', * reasonCode?: string, // 驳回时存在,如 AVATAR_NOT_CLEAR * reasonText?: string } // 驳回时存在,用户可读文案 * ], * submittedAt?: number, * reviewedAt?: number * } * * @returns {Promise<{ status: string, items: Array<{itemType:string,status:string,reasonCode?:string,reasonText?:string}>, submittedAt?: number, reviewedAt?: number }>} */ function getReviewStatus() { return api.get('/me/profile/review-status'); } /** * 提交资料审核(REST §37,POST /me/profile/submit-review) * * 幂等:用 Idempotency-Key 防止网络重试导致重复生成审核任务。 * 服务端校验资料完整度、敏感词、实名认证前置条件后生成 ReviewTask。 * * @returns {Promise<{ reviewStatus: 'pending', submittedAt: number }>} */ function submitReview() { const idempotencyKey = 'review-submit:' + Date.now(); return api.post('/me/profile/submit-review', {}, undefined, idempotencyKey); } /** * 获取婚恋关系状态(REST §83 章 GET /me/relationship-status) * @returns {Promise<{ status: string, recommendationEnabled: boolean, matchingWith?: { matchId: string, displayName: string } }>} */ function getRelationshipStatus() { return api.get('/me/relationship-status'); } /** * 暂停寻找(REST §84 章 PATCH /me/relationship-status) * 成功牵手不能通过此接口直接设置(后端返回 SUCCESS_CONFIRMATION_REQUIRED)。 * @returns {Promise<{ status: 'paused', recommendationEnabled: boolean }>} */ function pauseSearching() { const idempotencyKey = 'rel-pause:' + Date.now(); return api.patch('/me/relationship-status', { status: 'paused' }, undefined, idempotencyKey); } /** * 恢复寻找(REST §84 章 PATCH /me/relationship-status) * @returns {Promise<{ status: 'searching', recommendationEnabled: boolean }>} */ function resumeSearching() { const idempotencyKey = 'rel-resume:' + Date.now(); return api.patch('/me/relationship-status', { status: 'searching' }, undefined, idempotencyKey); } /** * 设置为"正在了解"(REST §84 章 PATCH /me/relationship-status) * @returns {Promise<{ status: 'getting_to_know', recommendationEnabled: boolean }>} */ function markGettingToKnow() { const idempotencyKey = 'rel-gtk:' + Date.now(); return api.patch('/me/relationship-status', { status: 'getting_to_know' }, undefined, idempotencyKey); } module.exports = { getProfile, updateProfile, getPreferences, updatePreferences, getPhotos, deletePhoto, setMainPhoto, requestUploadToken, getPrivacySettings, updatePrivacySettings, getReviewStatus, submitReview, getRelationshipStatus, pauseSearching, resumeSearching, markGettingToKnow, };