Files
danyang-match/miniapp/pages/profile-detail/profile-detail.js
T

243 lines
8.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.
/**
* 用户资料详情页 U21
*
* 重构要点(遵循 AGENTS.md 不变量):
* - 数据获取:recommendationService.getUserDetail(API_INVENTORY 行 43),不再直连 api 模块
* - 喜欢:matchStore.like(mutualMatch=true 时跳转会话页,AGENTS 第 3/6 条)
* - 拉黑:blockUser 跨 Store 编排(MatchStore + MessageStore 同步停用,AGENTS 第 4 条)
* - 举报:跳转 report 页,不在本页处理
* - 敏感数据:profile.birthday/身份证/手机号 仅服务端持有,前端不缓存(AGENTS 第 8 条)
* - Required 不可放宽:本页只读展示,无任何放宽择偶条件的入口(AGENTS 第 2 条)
*/
const { matchStore, appStore, blockUser } = require('../../stores');
const { recommendationService } = require('../../services');
const { to, DANGER_ACTION, RELATION_STATUS, BUSINESS_ERROR_CODE } = require('../../constants');
Page({
data: {
userId: '',
profile: null,
loading: true,
loadError: '',
/** @type {import('../../types').RelationStatus} */
relationStatus: RELATION_STATUS.NEUTRAL,
isLiked: false,
isMutual: false,
canChat: false,
actionLoading: false,
statusBarHeight: 20,
navBarHeight: 44,
showBlockDialog: false,
blockAction: DANGER_ACTION.BLOCK,
/** 派生的展示字段 */
displayName: '',
ageText: '',
metaLine: '',
badges: [],
basicInfo: [],
attitudeInfo: [],
},
onLoad(options) {
const userId = options.id || '';
if (!userId) {
this.setData({ loading: false, loadError: '用户不存在' });
return;
}
// 状态栏高度由 app.js 注入到全局,这里读一次
try {
const sysInfo = wx.getSystemInfoSync ? wx.getSystemInfoSync() : null;
if (sysInfo) {
this.setData({
statusBarHeight: sysInfo.statusBarHeight || 20,
navBarHeight: 44,
});
}
} catch (e) { /* 使用默认值 */ }
this.setData({ userId });
this.loadProfile();
},
async loadProfile() {
this.setData({ loading: true, loadError: '' });
try {
const user = await recommendationService.getUserDetail(this.data.userId);
this.setData({ loading: false, profile: user });
this._deriveDisplay(user);
} catch (err) {
this.setData({
loading: false,
loadError: (err && err.message) || '加载失败',
});
appStore.toastError(err, '加载用户资料失败');
}
},
/**
* 把后端 User 字段派生为展示用结构,避免 wxml 内做条件拼接
*/
_deriveDisplay(user) {
if (!user) return;
const relationStatus = user.relationStatus || RELATION_STATUS.NEUTRAL;
const isLiked = relationStatus === RELATION_STATUS.LIKED || relationStatus === RELATION_STATUS.MUTUAL_MATCH;
const isMutual = relationStatus === RELATION_STATUS.MUTUAL_MATCH;
// AGENTS 第 3 条:只有 Mutual 后才能聊天
const canChat = isMutual && relationStatus !== RELATION_STATUS.BLOCKED;
const badges = [];
if (user.verified || user.isRealNameVerified) {
badges.push({ kind: 'success', label: '已实名' });
}
if (user.reviewed || user.profileReviewStatus === 'approved') {
badges.push({ kind: 'info', label: '资料已审核' });
}
const metaParts = [];
if (user.heightCm) metaParts.push(`${user.heightCm}cm`);
if (user.regionName) metaParts.push(user.regionName);
if (user.educationCode) metaParts.push(user.educationCode);
if (user.occupationCode) metaParts.push(user.occupationCode);
const basicInfo = [];
if (user.maritalStatus) basicInfo.push({ label: '婚姻状况', value: user.maritalStatus });
if (user.childrenStatus || user.hasChildren !== undefined) {
basicInfo.push({ label: '子女情况', value: user.childrenStatus || (user.hasChildren ? '有孩' : '无孩') });
}
if (user.educationCode) basicInfo.push({ label: '学历', value: user.educationCode });
if (user.occupationCode) basicInfo.push({ label: '职业', value: user.occupationCode });
if (user.smokingStatus) basicInfo.push({ label: '吸烟', value: user.smokingStatus });
if (user.drinkingStatus) basicInfo.push({ label: '饮酒', value: user.drinkingStatus });
if (user.longTermDanyang) basicInfo.push({ label: '定居意愿', value: user.longTermDanyang, full: true });
if (user.futureDanyang) basicInfo.push({ label: '未来规划', value: user.futureDanyang, full: true });
const attitudeInfo = [];
if (user.relationshipGoal) attitudeInfo.push({ label: '寻找', value: user.relationshipGoal, full: true });
if (user.marriagePlan) attitudeInfo.push({ label: '结婚计划', value: user.marriagePlan, full: true });
this.setData({
relationStatus,
isLiked,
isMutual,
canChat,
displayName: user.displayName || '用户',
ageText: user.age ? `${user.age}岁` : '',
metaLine: metaParts.join(' · '),
badges,
basicInfo,
attitudeInfo,
});
},
onBack() {
wx.navigateBack();
},
onRetry() {
this.loadProfile();
},
/**
* 喜欢(AGENTS 第 3/5/6 条:用户本人操作,mutualMatch 时跳聊天)
*/
async onLike() {
const { userId, actionLoading, isLiked } = this.data;
if (!userId || actionLoading || isLiked) return;
this.setData({ actionLoading: true });
try {
const result = await matchStore.like(userId);
// 本地派生状态更新
if (result && result.mutualMatch) {
this.setData({
isLiked: true,
isMutual: true,
canChat: true,
relationStatus: RELATION_STATUS.MUTUAL_MATCH,
actionLoading: false,
});
appStore.toastSuccess('双向喜欢!可以开始聊天了');
if (result.matchedConversationId) {
wx.navigateTo({ url: to.chat(result.matchedConversationId) });
}
} else {
this.setData({
isLiked: true,
relationStatus: RELATION_STATUS.LIKED,
actionLoading: false,
});
appStore.toastSuccess('已表达喜欢');
}
} catch (err) {
this.setData({ actionLoading: false });
if (err && err.code === BUSINESS_ERROR_CODE.DUPLICATE_ACTION) {
appStore.toast('已表达过喜欢');
} else {
appStore.toastError(err, '操作失败');
}
}
},
/**
* 开始聊天(仅 Mutual 后可见,AGENTS 第 3 条)
*/
onGoChat() {
const { userId, canChat, profile } = this.data;
if (!canChat) {
appStore.toast('双方互相喜欢后才能开始聊天');
return;
}
// matchedConversationId 优先来自最近 like 结果;无则用 userId 占位由 chat 页拉取
const conversationId = (profile && profile.matchedConversationId) || userId;
wx.navigateTo({ url: to.chat(conversationId) });
},
/**
* 举报:跳转 report 页,不在本页处理(AGENTS 第 7 条:举报内容不在此暴露)
*/
onReport() {
const { userId } = this.data;
if (!userId) return;
wx.navigateTo({ url: to.report(userId) });
},
/**
* 拉黑入口:弹出 DangerActionDialog 二次确认(AGENTS 第 4 条)
*/
onBlock() {
if (!this.data.userId) return;
this.setData({ showBlockDialog: true });
},
onConfirmBlock() {
this.setData({ showBlockDialog: false });
this._doBlock();
},
onCancelBlock() {
this.setData({ showBlockDialog: false });
},
/**
* 执行拉黑:调用跨 Store 编排 blockUser
* - MatchStore:从推荐/Mutual 列表移除
* - MessageStore:会话立即标记不可发消息
*/
async _doBlock() {
const { userId, actionLoading } = this.data;
if (!userId || actionLoading) return;
this.setData({ actionLoading: true });
try {
appStore.showLoading('处理中…');
await blockUser(userId, '用户主动拉黑');
appStore.hideLoading();
appStore.toastSuccess('已拉黑');
// 拉黑后离开当前页(AGENTS 第 4 条:Block 即时禁止互动)
setTimeout(() => wx.navigateBack(), 800);
} catch (err) {
appStore.hideLoading();
this.setData({ actionLoading: false });
appStore.toastError(err, '拉黑失败');
}
},
});