207 lines
6.2 KiB
JavaScript
207 lines
6.2 KiB
JavaScript
/**
|
||||
|
|
* 婚恋状态页 U25(重构:用 userStore + matchStore + DangerActionDialog)
|
|||
|
|
*
|
|||
|
|
* 状态:searching / paused / getting_to_know / matched_successfully / service_exited
|
|||
|
|
* 操作:暂停寻找 / 恢复寻找 / 设置正在了解 / 解除匹配
|
|||
|
|
*
|
|||
|
|
* 不变量(AGENTS.md):
|
|||
|
|
* - 第 6 条:成功牵手必须双确认——matched_successfully 不能通过本页直接设置,
|
|||
|
|
* 仅由 /matches/{id}/success/request + confirm 双确认流程触发;本页只做状态展示与暂停/恢复/解除。
|
|||
|
|
* - 第 4 条:解除匹配后双方会话立即停用——unmatch 走 matchStore.unmatchConversation 同步 MessageStore。
|
|||
|
|
* - 第 9 条:PostgreSQL 是 Source of Truth——状态以 userStore.fetchRelationshipStatus 服务端返回为准。
|
|||
|
|
*/
|
|||
|
|
const { userStore, appStore, unmatchConversation } = require('../../stores');
|
|||
|
|
const { RELATIONSHIP_STATUS, DANGER_ACTION } = require('../../constants');
|
|||
|
|
|
|||
|
|
const STATUS_META = {
|
|||
|
|
[RELATIONSHIP_STATUS.SEARCHING]: {
|
|||
|
|
label: '正在寻找',
|
|||
|
|
desc: '你正在被推荐给合适的对象,也会收到新的喜欢提示。',
|
|||
|
|
kind: 'success',
|
|||
|
|
},
|
|||
|
|
[RELATIONSHIP_STATUS.PAUSED]: {
|
|||
|
|
label: '已暂停寻找',
|
|||
|
|
desc: '你暂时不会被推荐给他人,也无法收到新的喜欢提示。已有聊天仍可继续使用。',
|
|||
|
|
kind: 'warning',
|
|||
|
|
},
|
|||
|
|
[RELATIONSHIP_STATUS.GETTING_TO_KNOW]: {
|
|||
|
|
label: '正在了解',
|
|||
|
|
desc: '你正在与某位对象互相了解中,平台会适当减少新推荐,让你专注这段关系。',
|
|||
|
|
kind: 'info',
|
|||
|
|
},
|
|||
|
|
[RELATIONSHIP_STATUS.MATCHED_SUCCESSFULLY]: {
|
|||
|
|
label: '已成功牵手',
|
|||
|
|
desc: '恭喜!你与对方已成功牵手,平台将不再为你推荐其他人。如有需要可联系公益红娘。',
|
|||
|
|
kind: 'success',
|
|||
|
|
},
|
|||
|
|
[RELATIONSHIP_STATUS.SERVICE_EXITED]: {
|
|||
|
|
label: '已退出婚恋服务',
|
|||
|
|
desc: '你已退出婚恋服务,不再出现在推荐和搜索结果中。历史匹配与聊天记录已保留。',
|
|||
|
|
kind: 'disabled',
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Page({
|
|||
|
|
data: {
|
|||
|
|
status: RELATIONSHIP_STATUS.SEARCHING,
|
|||
|
|
statusLabel: '',
|
|||
|
|
statusDesc: '',
|
|||
|
|
statusKind: 'success',
|
|||
|
|
matchingWith: null,
|
|||
|
|
recommendationEnabled: true,
|
|||
|
|
loading: false,
|
|||
|
|
actionLoading: false,
|
|||
|
|
|
|||
|
|
// DangerActionDialog
|
|||
|
|
showDangerDialog: false,
|
|||
|
|
dangerAction: DANGER_ACTION.PAUSE,
|
|||
|
|
dangerTargetName: '',
|
|||
|
|
|
|||
|
|
statusBarHeight: 20,
|
|||
|
|
navBarHeight: 44,
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad() {
|
|||
|
|
try {
|
|||
|
|
const info = (wx.getWindowInfo && wx.getWindowInfo()) || wx.getSystemInfoSync();
|
|||
|
|
this.setData({
|
|||
|
|
statusBarHeight: info.statusBarHeight || 20,
|
|||
|
|
navBarHeight: info.platform === 'android' ? 48 : 44,
|
|||
|
|
});
|
|||
|
|
} catch (e) { /* 使用默认值 */ }
|
|||
|
|
|
|||
|
|
this._unsub = userStore.bindToPage(this, {
|
|||
|
|
userState: 'userState',
|
|||
|
|
});
|
|||
|
|
this.loadStatus();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onUnload() {
|
|||
|
|
if (this._unsub) this._unsub();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onShow() {
|
|||
|
|
this.loadStatus();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
async loadStatus() {
|
|||
|
|
if (this.data.loading) return;
|
|||
|
|
this.setData({ loading: true });
|
|||
|
|
try {
|
|||
|
|
const result = await userStore.fetchRelationshipStatus();
|
|||
|
|
this._applyStatus(result.status, result.matchingWith, result.recommendationEnabled);
|
|||
|
|
} catch (err) {
|
|||
|
|
// 兜底:用 userState 缓存渲染
|
|||
|
|
const us = userStore.state.userState || {};
|
|||
|
|
this._applyStatus(us.relationshipStatus || RELATIONSHIP_STATUS.SEARCHING, us.matchingWith || null, us.recommendationEnabled ?? true);
|
|||
|
|
appStore.toastError(err);
|
|||
|
|
} finally {
|
|||
|
|
this.setData({ loading: false });
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
_applyStatus(status, matchingWith, recommendationEnabled) {
|
|||
|
|
const meta = STATUS_META[status] || STATUS_META[RELATIONSHIP_STATUS.SEARCHING];
|
|||
|
|
this.setData({
|
|||
|
|
status,
|
|||
|
|
statusLabel: meta.label,
|
|||
|
|
statusDesc: meta.desc,
|
|||
|
|
statusKind: meta.kind,
|
|||
|
|
matchingWith: matchingWith || null,
|
|||
|
|
recommendationEnabled: recommendationEnabled ?? true,
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// ============ 操作(先弹 DangerActionDialog 二次确认) ============
|
|||
|
|
|
|||
|
|
onPause() {
|
|||
|
|
this.setData({
|
|||
|
|
showDangerDialog: true,
|
|||
|
|
dangerAction: DANGER_ACTION.PAUSE,
|
|||
|
|
dangerTargetName: '',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onResume() {
|
|||
|
|
// 恢复寻找为正向操作,直接执行
|
|||
|
|
this._doAction(async () => {
|
|||
|
|
await userStore.resumeSearching();
|
|||
|
|
appStore.toastSuccess('已恢复寻找');
|
|||
|
|
this.loadStatus();
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onSetGettingToKnow() {
|
|||
|
|
this.setData({
|
|||
|
|
showDangerDialog: true,
|
|||
|
|
dangerAction: DANGER_ACTION.PAUSE, // 复用"暂停类"确认样式(非 danger)
|
|||
|
|
dangerTargetName: '',
|
|||
|
|
});
|
|||
|
|
this._pendingGtk = true;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onUnmatch() {
|
|||
|
|
const m = this.data.matchingWith;
|
|||
|
|
if (!m || !m.matchId) return;
|
|||
|
|
this.setData({
|
|||
|
|
showDangerDialog: true,
|
|||
|
|
dangerAction: DANGER_ACTION.UNMATCH,
|
|||
|
|
dangerTargetName: m.displayName || '对方',
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** DangerActionDialog 确认回调 */
|
|||
|
|
async onDangerConfirm() {
|
|||
|
|
this.setData({ showDangerDialog: false });
|
|||
|
|
const action = this.data.dangerAction;
|
|||
|
|
if (this._pendingGtk) {
|
|||
|
|
this._pendingGtk = false;
|
|||
|
|
this._doAction(async () => {
|
|||
|
|
await userStore.markGettingToKnow();
|
|||
|
|
appStore.toastSuccess('已设置为正在了解');
|
|||
|
|
this.loadStatus();
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (action === DANGER_ACTION.PAUSE) {
|
|||
|
|
this._doAction(async () => {
|
|||
|
|
await userStore.pauseSearching();
|
|||
|
|
appStore.toastSuccess('已暂停寻找');
|
|||
|
|
this.loadStatus();
|
|||
|
|
});
|
|||
|
|
} else if (action === DANGER_ACTION.UNMATCH) {
|
|||
|
|
const m = this.data.matchingWith;
|
|||
|
|
if (!m || !m.matchId) return;
|
|||
|
|
this._doAction(async () => {
|
|||
|
|
await unmatchConversation(m.matchId);
|
|||
|
|
this.setData({ matchingWith: null });
|
|||
|
|
appStore.toastSuccess('已解除匹配');
|
|||
|
|
this.loadStatus();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** DangerActionDialog 取消回调 */
|
|||
|
|
onDangerCancel() {
|
|||
|
|
this.setData({ showDangerDialog: false });
|
|||
|
|
this._pendingGtk = false;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 统一执行带 loading 的动作(防重) */
|
|||
|
|
async _doAction(fn) {
|
|||
|
|
if (this.data.actionLoading) return;
|
|||
|
|
this.setData({ actionLoading: true });
|
|||
|
|
try {
|
|||
|
|
await fn();
|
|||
|
|
} catch (err) {
|
|||
|
|
appStore.toastError(err);
|
|||
|
|
} finally {
|
|||
|
|
this.setData({ actionLoading: false });
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onBack() {
|
|||
|
|
wx.navigateBack();
|
|||
|
|
},
|
|||
|
|
});
|