chore: establish V1.1 recovery baseline

This commit is contained in:
2026-09-09 22:05:00 +08:00
commit b46b48eb33
947 changed files with 155471 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
/**
* 公益红娘服务页 U33
*
* 重构要点(遵循 AGENTS.md 不变量):
* - 数据:MatchmakerStore.fetchMyServices + activeService 派生
* - 展示:ui-matchmaker-card 展示当前进行中的服务,"查看红娘推荐"按钮触发跳转
* - 申请:跳转 matchmaker-apply 页,不在本页填写(AGENTS 第 1 条:用户永久免费,无高级/付费红娘差异化)
* - 推荐:红娘推荐列表跳 fate-center 页,最终 Like/Pass 仍走 matchStore(AGENTS 第 5 条:红娘不可替用户操作)
* - 进度:跳 matchmaker-progress 页查看服务跟进记录
*/
const { matchmakerStore, appStore } = require('../../stores');
const { to, ROUTE, buildPath, MATCHMAKER_SERVICE_STATUS } = require('../../constants');
Page({
data: {
statusBarHeight: 20,
navBarHeight: 44,
loading: false,
firstLoaded: false,
/** @type {import('../../types').MatchmakerService|null} 进行中的服务 */
activeService: null,
/** @type {import('../../types').MatchmakerService[]} 历史(不含活跃服务) */
historyServices: [],
/** 是否展示"查看红娘推荐"按钮 */
showRecommendations: false,
/** 红娘能力说明(静态文案,无敏感信息) */
capabilities: [
'推荐合适对象(基于你的择偶条件)',
'调整择偶条件的专业建议',
'协助联系你感兴趣的意向对象',
'推荐参加合适的相亲活动',
'聊天沟通的方法指导',
],
/** 空状态操作 */
emptyActions: [
{ text: '申请红娘帮助', event: 'apply', variant: 'primary' },
],
},
onLoad() {
try {
const sysInfo = wx.getSystemInfoSync ? wx.getSystemInfoSync() : null;
if (sysInfo) {
this.setData({
statusBarHeight: sysInfo.statusBarHeight || 20,
navBarHeight: 44,
});
}
} catch (e) { /* 使用默认值 */ }
this._unsub = matchmakerStore.bindToPage(this, {
activeService: 'activeService',
});
this.fetchServices();
},
onShow() {
// 从 apply/progress 页返回后刷新(状态可能已变更)
if (this.data.firstLoaded) {
this.fetchServices();
}
},
onUnload() {
if (this._unsub) this._unsub();
},
async fetchServices() {
if (this.data.loading) return;
this.setData({ loading: true });
try {
await matchmakerStore.fetchMyServices();
const { activeService, myServices } = matchmakerStore.state;
// 仅当服务处于 in_service / waiting_user 时展示"查看推荐"入口
const showRecommendations = !!activeService && (
activeService.status === MATCHMAKER_SERVICE_STATUS.IN_SERVICE ||
activeService.status === MATCHMAKER_SERVICE_STATUS.WAITING_USER
);
// 历史列表排除活跃服务,避免重复展示
const historyServices = activeService
? myServices.filter((s) => s.serviceId !== activeService.serviceId)
: myServices;
this.setData({
loading: false,
firstLoaded: true,
activeService,
historyServices,
showRecommendations,
});
} catch (err) {
this.setData({ loading: false, firstLoaded: true });
appStore.toastError(err, '加载红娘服务失败');
}
},
onBack() {
wx.navigateBack();
},
/** 申请红娘帮助 */
onApplyService() {
wx.navigateTo({ url: ROUTE.DETAIL.MATCHMAKER_APPLY });
},
/** 查看服务进度(卡片头部点击) */
onViewService(e) {
const serviceId = e.detail.serviceId;
if (!serviceId) return;
wx.navigateTo({ url: to.matchmakerProgress(serviceId) });
},
/**
* 查看红娘推荐(AGENTS 第 5 条:红娘不替用户 Like,推荐列表里仍由用户本人操作)
* 跳 fate-center,由该页通过 matchStore.like/pass 完成最终选择
*/
onViewRecommendations(e) {
const serviceId = e.detail.serviceId;
if (!serviceId) return;
wx.navigateTo({ url: buildPath(ROUTE.MAIN.FATE_CENTER, { id: serviceId }) });
},
/** 历史服务列表项点击 */
onHistoryTap(e) {
const serviceId = e.currentTarget.dataset.serviceId;
if (!serviceId) return;
wx.navigateTo({ url: to.matchmakerProgress(serviceId) });
},
/** 空状态操作 */
onEmptyAction(e) {
const { event } = e.detail;
if (event === 'apply') this.onApplyService();
},
});
+12
View File
@@ -0,0 +1,12 @@
{
"navigationBarTitleText": "公益红娘",
"navigationStyle": "custom",
"usingComponents": {
"ui-nav-bar": "/components/nav-bar/index",
"ui-section-header": "/components/section-header/index",
"ui-matchmaker-card": "/components/matchmaker-card/index",
"ui-button": "/components/button/index",
"ui-loading": "/components/loading/index",
"ui-empty": "/components/empty/index"
}
}
+89
View File
@@ -0,0 +1,89 @@
<!-- 公益红娘服务页 U33 -->
<view class="mm-page">
<ui-nav-bar
title="公益红娘"
status-bar-height="{{statusBarHeight}}"
nav-bar-height="{{navBarHeight}}"
bind:back="onBack"
/>
<!-- 首次加载 -->
<view wx:if="{{loading && !firstLoaded}}" class="mm-loading">
<ui-loading mode="skeleton" rows="2" />
</view>
<view wx:else class="mm-body">
<!-- 进行中的服务 -->
<view wx:if="{{activeService}}" class="mm-section">
<ui-section-header title="我的服务" subtitle="当前进行中" />
<ui-matchmaker-card
service="{{activeService}}"
show-recommendations="{{showRecommendations}}"
bind:view="onViewService"
bind:recommendations="onViewRecommendations"
/>
</view>
<!-- 无活跃服务:空状态 + 申请入口 -->
<view wx:else class="mm-empty">
<ui-empty
title="还没有红娘服务"
description="公益红娘可以基于你的择偶条件,为你推荐合适的对象"
illustration="default"
actions="{{emptyActions}}"
bind:action="onEmptyAction"
/>
</view>
<!-- 申请红娘帮助 CTA(无活跃服务时主入口;有活跃服务时仍可重新申请) -->
<view class="mm-section">
<ui-button
variant="{{activeService ? 'secondary' : 'primary'}}"
size="lg"
block
bind:tap="onApplyService"
>{{activeService ? '提交新的红娘需求' : '申请红娘帮助'}}</ui-button>
</view>
<!-- 红娘能力说明(AGENTS 第 1 条:公益免费,无付费/会员差异化) -->
<view class="mm-section">
<view class="mm-cap card-base">
<ui-section-header title="红娘能帮您什么?" />
<view class="mm-cap__list">
<view wx:for="{{capabilities}}" wx:key="*this" class="mm-cap__item">
<view class="mm-cap__dot"></view>
<text class="mm-cap__text">{{item}}</text>
</view>
</view>
<view class="mm-cap__note">
<text>公益服务,全程免费。</text>
</view>
</view>
</view>
<!-- 历史服务列表 -->
<view wx:if="{{historyServices.length}}" class="mm-section">
<ui-section-header title="历史服务" subtitle="共 {{historyServices.length}} 条" />
<view class="mm-history">
<view
wx:for="{{historyServices}}"
wx:key="serviceId"
class="mm-history__item card-base"
data-service-id="{{item.serviceId}}"
bindtap="onHistoryTap"
>
<view class="mm-history__row">
<text class="mm-history__title">公益红娘服务</text>
<text class="mm-history__status mm-history__status--{{item.status}}">{{item.statusText || item.status}}</text>
</view>
<view wx:if="{{item.matchmakerName}}" class="mm-history__meta">
红娘:{{item.matchmakerName}}
</view>
<view wx:if="{{item.lastFollowUpAtText || item.lastFollowUpAt}}" class="mm-history__meta">
最近跟进:{{item.lastFollowUpAtText || item.lastFollowUpAt}}
</view>
</view>
</view>
</view>
</view>
</view>
+113
View File
@@ -0,0 +1,113 @@
/**
* 公益红娘服务页 U33
*/
.mm-page {
min-height: 100vh;
background: var(--color-bg-page);
padding-bottom: var(--spacing-section);
}
/* ============ 加载 ============ */
.mm-loading {
padding: var(--spacing-3) var(--spacing-page-x);
}
.mm-body {
padding-top: var(--spacing-2);
}
.mm-section {
padding: var(--spacing-2) var(--spacing-page-x);
}
/* ============ 空状态 ============ */
.mm-empty {
padding-top: 80rpx;
}
/* ============ 红娘能力说明 ============ */
.mm-cap {
margin-top: var(--spacing-2);
}
.mm-cap__list {
margin-top: var(--spacing-3);
}
.mm-cap__item {
display: flex;
align-items: flex-start;
gap: var(--spacing-2);
padding: var(--spacing-1) 0;
}
.mm-cap__dot {
width: 12rpx;
height: 12rpx;
margin-top: 14rpx;
border-radius: 50%;
background: var(--color-primary);
flex-shrink: 0;
}
.mm-cap__text {
flex: 1;
font-size: var(--font-size-sm);
color: var(--color-text-secondary);
line-height: var(--line-height-relaxed);
}
.mm-cap__note {
margin-top: var(--spacing-3);
padding-top: var(--spacing-3);
border-top: var(--border-width) solid var(--color-divider);
font-size: var(--font-size-xs);
color: var(--color-success);
}
/* ============ 历史服务 ============ */
.mm-history {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
margin-top: var(--spacing-2);
}
.mm-history__item {
padding: var(--spacing-3);
}
.mm-history__row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-1);
}
.mm-history__title {
font-size: var(--font-size-md);
font-weight: var(--font-weight-semibold);
color: var(--color-text-primary);
}
.mm-history__status {
font-size: var(--font-size-xs);
padding: var(--spacing-1) var(--spacing-2);
border-radius: var(--radius-sm);
background: var(--color-bg-disabled);
color: var(--color-text-tertiary);
}
.mm-history__status--completed,
.mm-history__status--cancelled {
background: var(--color-bg-disabled);
color: var(--color-text-disabled);
}
.mm-history__meta {
font-size: var(--font-size-xs);
color: var(--color-text-tertiary);
line-height: var(--line-height-normal);
margin-top: var(--spacing-1);
}