Files
danyang-match/miniapp/services/profileService.js
T

190 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 用户资料服务(API_INVENTORY 行 17-25, 68-70)
*
* 封装:本人资料、择偶条件、生活照、隐私设置、审核状态、关系状态切换。
* 严格区分 GET 与 PUT,避免误操作;PUT 调用走幂等键防重。
* 自我介绍/择偶条件字数限制由 stores/profileStore 校验,本层只负责传输。
*/
const api = require('../utils/api');
/**
* 获取本人资料(API_INVENTORY 行 17)
* @returns {Promise<import('../types').Profile>}
*/
function getProfile() {
return api.get('/me/profile');
}
/**
* 更新本人资料(API_INVENTORY 行 18)
* @param {Partial<import('../types').Profile>} payload
* @returns {Promise<import('../types').Profile>} 服务端返回的最新资料
*/
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<import('../types').PartnerPreference>}
*/
function getPreferences() {
return api.get('/me/preferences');
}
/**
* 更新择偶条件(API_INVENTORY 行 20)
* @param {Partial<import('../types').PartnerPreference>} payload
* @returns {Promise<import('../types').PartnerPreference>}
*/
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<void>}
*/
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<import('../types').PrivacySettings>}
*/
function getPrivacySettings() {
return api.get('/me/privacy-settings');
}
/**
* 更新隐私设置(API_INVENTORY 行 24)
* @param {Partial<import('../types').PrivacySettings>} payload
* @returns {Promise<import('../types').PrivacySettings>}
*/
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,
};