Files
danyang-match/miniapp/stores/matchmakerStore.js
T

157 lines
5.1 KiB
JavaScript
Raw Normal View History

2026-09-09 22:05:00 +08:00
/**
* 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,
});
}
/** 拉取我的红娘服务列表 */
async fetchMyServices(params = {}) {
if (this.state.servicesLoading) return;
this.setState({ servicesLoading: true, lastError: null });
try {
const result = await matchmakerService.getMyServices(params);
const items = result.items || [];
const active = items.find(
(s) =>
s.status !== MATCHMAKER_SERVICE_STATUS.COMPLETED &&
s.status !== MATCHMAKER_SERVICE_STATUS.CANCELLED,
) || null;
this.setState({
myServices: items,
servicesCursor: result.nextCursor || null,
servicesHasMore: !!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, ...(result.items || [])],
servicesCursor: result.nextCursor || null,
servicesHasMore: !!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);
this.setState({
recommendations: result.items || [],
recommendationsCursor: result.nextCursor || null,
recommendationsHasMore: !!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,
});
this.setState({
recommendations: [...this.state.recommendations, ...(result.items || [])],
recommendationsCursor: result.nextCursor || null,
recommendationsHasMore: !!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;