/** * MatchmakerStore(规范 §131) * * 职责: * - 维护我申请的红娘服务列表 * - 维护红娘推荐列表(仅展示,最终 Like/Pass 走 matchStore) * - 维护当前进行中的服务详情 * * 不变量(AGENTS.md): * - 第 5 条:红娘不可替用户 Like——本 Store 不暴露任何代用户 Like/Pass 的方法, * 用户对红娘推荐做出选择时仍走 matchStore.like/pass(userId)。 * - 第 7 条:普通工作人员不能查看私人聊天——本 Store 无聊天接入。 * - 第 1 条:用户永久免费——红娘服务不引入任何"高级红娘/付费红娘"差异化。 */ const BaseStore = require('./baseStore'); const { matchmakerService } = require('../services'); const { MATCHMAKER_SERVICE_STATUS } = require('../constants'); class MatchmakerStore extends BaseStore { constructor() { super({ /** @type {import('../types').MatchmakerService[]} */ myServices: [], servicesCursor: null, servicesHasMore: true, servicesLoading: false, /** 当前进行中的服务(status != completed/cancelled) */ activeService: null, /** @type {import('../types').MatchmakerRecommendation[]} */ recommendations: [], recommendationsCursor: null, recommendationsHasMore: true, recommendationsLoading: false, lastError: null, }); } /** 将 C 端服务实体字段统一为页面组件契约。 */ normalizeService(service) { if (!service) return service; return { ...service, serviceId: service.serviceId || service.id, requirement: service.requirement || service.description || '', }; } /** 拉取我的红娘服务列表 */ async fetchMyServices(params = {}) { if (this.state.servicesLoading) return; this.setState({ servicesLoading: true, lastError: null }); try { const result = await matchmakerService.getMyServices(params); // C 端接口当前返回数组;兼容未来分页响应 { items, nextCursor }。 const items = (Array.isArray(result) ? result : (result.items || [])).map((item) => this.normalizeService(item)); const active = items.find( (s) => s.status !== MATCHMAKER_SERVICE_STATUS.COMPLETED && s.status !== MATCHMAKER_SERVICE_STATUS.CANCELLED, ) || null; this.setState({ myServices: items, servicesCursor: Array.isArray(result) ? null : (result.nextCursor || null), servicesHasMore: Array.isArray(result) ? false : !!result.nextCursor, servicesLoading: false, activeService: active, }); return result; } catch (err) { this.setState({ servicesLoading: false, lastError: err }); throw err; } } /** 加载更多服务 */ async loadMoreServices() { if (this.state.servicesLoading || !this.state.servicesCursor) return; this.setState({ servicesLoading: true }); try { const result = await matchmakerService.getMyServices({ cursor: this.state.servicesCursor, pageSize: 20, }); this.setState({ myServices: [...this.state.myServices, ...(Array.isArray(result) ? result : (result.items || [])).map((item) => this.normalizeService(item))], servicesCursor: Array.isArray(result) ? null : (result.nextCursor || null), servicesHasMore: Array.isArray(result) ? false : !!result.nextCursor, servicesLoading: false, }); } catch (err) { this.setState({ servicesLoading: false, lastError: err }); throw err; } } /** 申请红娘服务 */ async applyService(payload) { const result = await matchmakerService.applyService(payload); // 重新拉取列表以反映最新状态 await this.fetchMyServices(); return result; } /** 拉取服务详情 */ async fetchServiceDetail(serviceId) { return matchmakerService.getServiceDetail(serviceId); } /** 拉取红娘推荐列表 */ async fetchRecommendations(params = {}) { if (this.state.recommendationsLoading) return; this.setState({ recommendationsLoading: true, lastError: null }); try { const result = await matchmakerService.getRecommendations(params); const items = Array.isArray(result) ? result : (result.items || []); this.setState({ recommendations: items, recommendationsCursor: Array.isArray(result) ? null : (result.nextCursor || null), recommendationsHasMore: Array.isArray(result) ? false : !!result.nextCursor, recommendationsLoading: false, }); return result; } catch (err) { this.setState({ recommendationsLoading: false, lastError: err }); throw err; } } /** 加载更多红娘推荐 */ async loadMoreRecommendations() { if (this.state.recommendationsLoading || !this.state.recommendationsCursor) return; this.setState({ recommendationsLoading: true }); try { const result = await matchmakerService.getRecommendations({ cursor: this.state.recommendationsCursor, pageSize: 20, }); const items = Array.isArray(result) ? result : (result.items || []); this.setState({ recommendations: [...this.state.recommendations, ...items], recommendationsCursor: Array.isArray(result) ? null : (result.nextCursor || null), recommendationsHasMore: Array.isArray(result) ? false : !!result.nextCursor, recommendationsLoading: false, }); } catch (err) { this.setState({ recommendationsLoading: false, lastError: err }); throw err; } } /** * 对红娘推荐的用户表达 Like/Pass(实际走 matchStore) * 调用方应直接调用 matchStore.like/pass(userId),本方法仅为统一入口的便利封装。 * 注意:本 Store 自身不替用户做决定,仅做接口转发(AGENTS 第 5 条)。 */ async likeRecommendation(userId, matchStore) { return matchStore.like(userId); } async passRecommendation(userId, matchStore) { return matchStore.pass(userId); } } const matchmakerStore = new MatchmakerStore(); module.exports = matchmakerStore;