diff --git a/miniapp/pages/discover/discover.ts b/miniapp/pages/discover/discover.ts index 0046061..1f06187 100644 --- a/miniapp/pages/discover/discover.ts +++ b/miniapp/pages/discover/discover.ts @@ -1,10 +1,11 @@ /** - * 找对象页 U19-U20(TypeScript) + * 找对象页 — 筛选对齐后端 DiscoverController 5 个筛选参数: + * minAge, maxAge, regionCode, maritalStatus, educationCode * * 不变量(AGENTS.md): - * - 第 2 条:Required 不可自动放宽——Discover 搜索仅透传筛选条件到后端 - * - 第 4 条:Block 即时禁止互动 - * - 第 6 条:单向意向不泄露 + * - Required 不可自动放宽——Discover 仅透传筛选条件到后端 + * - Block 即时禁止互动 + * - 单向意向不泄露 */ // eslint-disable-next-line @typescript-eslint/no-unused-vars import { matchStore, appStore, authStore } from '../../stores'; @@ -14,6 +15,15 @@ import { recommendationService } from '../../services'; import { to } from '../../constants'; import type { RecommendationCandidate } from '../../types'; +interface AppliedFilter { + keyword: string; + regionCode: string; // 后端参数名 + minAge: number; + maxAge: number; + educationCode: string; // 后端参数名 + maritalStatus: string; // 后端参数名 +} + interface DiscoverData { users: RecommendationCandidate[]; loading: boolean; @@ -22,18 +32,22 @@ interface DiscoverData { hasMore: boolean; keywordInput: string; showFilter: boolean; - tempRegion: string; - tempAgeMin: number; - tempAgeMax: number; - applied: { keyword: string; region: string; ageMin: number; ageMax: number }; + // 面板临时态 + tempRegionCode: string; + tempMinAge: number; + tempMaxAge: number; + tempEducationCode: string; + tempMaritalStatus: string; + applied: AppliedFilter; hasActiveFilter: boolean; - regions: string[]; + regions: Array<{ code: string; label: string }>; + educations: Array<{ code: string; label: string }>; + maritalStatuses: Array<{ code: string; label: string }>; actionLoadingUserId: string; - emptyActions: Array<{ text: string; event: string; variant: string }>; } -const DEFAULT_AGE_MIN = 18; -const DEFAULT_AGE_MAX = 60; +const DEFAULT_MIN_AGE = 18; +const DEFAULT_MAX_AGE = 60; const PAGE_SIZE = 20; Page({ @@ -45,18 +59,37 @@ Page({ hasMore: true, keywordInput: '', showFilter: false, - tempRegion: '', - tempAgeMin: DEFAULT_AGE_MIN, - tempAgeMax: DEFAULT_AGE_MAX, - applied: { keyword: '', region: '', ageMin: DEFAULT_AGE_MIN, ageMax: DEFAULT_AGE_MAX }, + tempRegionCode: '', + tempMinAge: DEFAULT_MIN_AGE, + tempMaxAge: DEFAULT_MAX_AGE, + tempEducationCode: '', + tempMaritalStatus: '', + applied: { + keyword: '', + regionCode: '', + minAge: DEFAULT_MIN_AGE, + maxAge: DEFAULT_MAX_AGE, + educationCode: '', + maritalStatus: '', + }, hasActiveFilter: false, - regions: ['丹阳', '镇江', '南京'], - actionLoadingUserId: '', - emptyActions: [ - { text: '清空筛选', event: 'reset', variant: 'primary' }, - { text: '去今日推荐', event: 'home', variant: 'secondary' }, + regions: [ + { code: '321181', label: '丹阳' }, + { code: '321100', label: '镇江' }, + { code: '320100', label: '南京' }, ], - }, + educations: [ + { code: 'high_school', label: '高中及以下' }, + { code: 'college', label: '大专' }, + { code: 'bachelor', label: '本科' }, + { code: 'master', label: '硕士及以上' }, + ], + maritalStatuses: [ + { code: 'never_married', label: '未婚' }, + { code: 'divorced', label: '离异' }, + ], + actionLoadingUserId: '', + } as DiscoverData, onLoad() { if (!authStore.state.isLoggedIn) return; @@ -67,7 +100,7 @@ Page({ if (this.data.loading) return; this.setData({ loading: true }); try { - // @ts-ignore - recommendationService 接口待 TypeScript 化 + // @ts-ignore - recommendationService 接口待 TS 化 const result = await recommendationService.discover(this._buildParams()); const items: RecommendationCandidate[] = (result?.items as RecommendationCandidate[]) || []; this.setData({ @@ -104,16 +137,29 @@ Page({ } }, + /** 对齐后端 DiscoverController 5 个筛选参数 */ _buildParams() { - const { applied } = this.data; + const a = this.data.applied; const params: Record = { pageSize: PAGE_SIZE }; - if (applied.keyword) params.keyword = applied.keyword; - if (applied.region) params.region = applied.region; - if (applied.ageMin !== DEFAULT_AGE_MIN) params.ageMin = applied.ageMin; - if (applied.ageMax !== DEFAULT_AGE_MAX) params.ageMax = applied.ageMax; + if (a.keyword) params.keyword = a.keyword; + if (a.regionCode) params.regionCode = a.regionCode; + if (a.minAge !== DEFAULT_MIN_AGE) params.minAge = a.minAge; + if (a.maxAge !== DEFAULT_MAX_AGE) params.maxAge = a.maxAge; + if (a.educationCode) params.educationCode = a.educationCode; + if (a.maritalStatus) params.maritalStatus = a.maritalStatus; return params; }, + _hasActiveFilter(applied: AppliedFilter) { + return !!( + applied.keyword || applied.regionCode || + applied.minAge !== DEFAULT_MIN_AGE || applied.maxAge !== DEFAULT_MAX_AGE || + applied.educationCode || applied.maritalStatus + ); + }, + + // ========== 搜索框 ========== + onKeywordInput(e: any) { this.setData({ keywordInput: e.detail.value }); }, @@ -125,68 +171,109 @@ Page({ this.fetchDiscover(true); }, - toggleFilter() { - this.setData({ showFilter: !this.data.showFilter }); - }, + // ========== 顶部 chip 点击(即时应用) ========== - onRegionTap(e: WechatMiniprogram.TouchEvent) { - const val = (e.currentTarget.dataset as any).val as string; - this.setData({ tempRegion: this.data.tempRegion === val ? '' : val }); - }, - - /** 顶部"丹阳本地" chip 专用:立即应用 region 筛选并刷新结果 */ - onTopRegionTap(e: WechatMiniprogram.TouchEvent) { - const val = (e.currentTarget.dataset as any).val as string; - const nextRegion = this.data.applied.region === val ? '' : val; - const applied = { ...this.data.applied, region: nextRegion }; + onTopRegionTap() { + // 丹阳本地 chip:regionCode=321181 + const target = '321181'; + const nextCode = this.data.applied.regionCode === target ? '' : target; + const applied = { ...this.data.applied, regionCode: nextCode }; this.setData({ - tempRegion: nextRegion, + tempRegionCode: nextCode, applied, hasActiveFilter: this._hasActiveFilter(applied), }); this.fetchDiscover(true); }, + /** 打开筛选面板,并同步当前 applied 状态到 temp */ + openFilterPanel() { + const a = this.data.applied; + this.setData({ + showFilter: true, + tempRegionCode: a.regionCode, + tempMinAge: a.minAge, + tempMaxAge: a.maxAge, + tempEducationCode: a.educationCode, + tempMaritalStatus: a.maritalStatus, + }); + }, + + closeFilterPanel() { + this.setData({ showFilter: false }); + }, + + // ========== 筛选面板内交互 ========== + + onPanelRegionTap(e: WechatMiniprogram.TouchEvent) { + const code = (e.currentTarget.dataset as any).code as string; + this.setData({ tempRegionCode: this.data.tempRegionCode === code ? '' : code }); + }, + + onPanelEducationTap(e: WechatMiniprogram.TouchEvent) { + const code = (e.currentTarget.dataset as any).code as string; + this.setData({ tempEducationCode: this.data.tempEducationCode === code ? '' : code }); + }, + + onPanelMaritalTap(e: WechatMiniprogram.TouchEvent) { + const code = (e.currentTarget.dataset as any).code as string; + this.setData({ tempMaritalStatus: this.data.tempMaritalStatus === code ? '' : code }); + }, + onMinAgeChange(e: any) { - let min = Number((e as any).detail.value); - if (min > this.data.tempAgeMax) min = this.data.tempAgeMax; - this.setData({ tempAgeMin: min }); + let min = Number(e.detail.value); + if (min > this.data.tempMaxAge) min = this.data.tempMaxAge; + this.setData({ tempMinAge: min }); }, onMaxAgeChange(e: any) { - let max = Number((e as any).detail.value); - if (max < this.data.tempAgeMin) max = this.data.tempAgeMin; - this.setData({ tempAgeMax: max }); + let max = Number(e.detail.value); + if (max < this.data.tempMinAge) max = this.data.tempMinAge; + this.setData({ tempMaxAge: max }); }, onApplyFilter() { - const { tempRegion, tempAgeMin, tempAgeMax, keywordInput } = this.data; - const applied = { keyword: (keywordInput || '').trim(), region: tempRegion, ageMin: tempAgeMin, ageMax: tempAgeMax }; - this.setData({ applied, hasActiveFilter: this._hasActiveFilter(applied), showFilter: false }); - this.fetchDiscover(true); - }, - - onResetFilter() { - const applied = { keyword: '', region: '', ageMin: DEFAULT_AGE_MIN, ageMax: DEFAULT_AGE_MAX }; + const a = this.data.applied; + const applied: AppliedFilter = { + keyword: a.keyword, + regionCode: this.data.tempRegionCode, + minAge: this.data.tempMinAge, + maxAge: this.data.tempMaxAge, + educationCode: this.data.tempEducationCode, + maritalStatus: this.data.tempMaritalStatus, + }; this.setData({ - keywordInput: '', tempRegion: '', tempAgeMin: DEFAULT_AGE_MIN, tempAgeMax: DEFAULT_AGE_MAX, - applied, hasActiveFilter: false, showFilter: false, + applied, + hasActiveFilter: this._hasActiveFilter(applied), + showFilter: false, }); this.fetchDiscover(true); }, - _hasActiveFilter(applied: { keyword: string; region: string; ageMin: number; ageMax: number }) { - return !!( - applied.keyword || applied.region || - applied.ageMin !== DEFAULT_AGE_MIN || applied.ageMax !== DEFAULT_AGE_MAX - ); + onResetFilter() { + const applied: AppliedFilter = { + keyword: '', + regionCode: '', + minAge: DEFAULT_MIN_AGE, + maxAge: DEFAULT_MAX_AGE, + educationCode: '', + maritalStatus: '', + }; + this.setData({ + keywordInput: '', + tempRegionCode: '', + tempMinAge: DEFAULT_MIN_AGE, + tempMaxAge: DEFAULT_MAX_AGE, + tempEducationCode: '', + tempMaritalStatus: '', + applied, + hasActiveFilter: false, + showFilter: false, + }); + this.fetchDiscover(true); }, - onEmptyAction(e: WechatMiniprogram.TouchEvent) { - const { event } = (e.detail as any) || {}; - if (event === 'reset') this.onResetFilter(); - else if (event === 'home') wx.switchTab({ url: '/pages/index/index' }); - }, + // ========== 卡片交互 ========== onViewDetail(e: WechatMiniprogram.TouchEvent) { const { userId } = (e.detail as any) || {}; diff --git a/miniapp/pages/discover/discover.wxml b/miniapp/pages/discover/discover.wxml index 713f759..8097d27 100644 --- a/miniapp/pages/discover/discover.wxml +++ b/miniapp/pages/discover/discover.wxml @@ -1,24 +1,108 @@ - 找对象 - - 搜索 + + 找对象 + + + - 推荐丹阳本地附近年龄学历更多筛选 + + + 搜索 + + + + + + + + 推荐 + 丹阳本地 + 年龄 + 学历 + 婚姻 + + + - 年龄范围{{tempAgeMin}}–{{tempAgeMax}} 岁 - 地区{{item}} - 重置应用筛选 + + + + 年龄范围 + {{tempMinAge}}–{{tempMaxAge}} 岁 + + + + + + + + 地区 + + {{item.label}} + + + + + + 学历 + + {{item.label}} + + + + + + 婚姻状态 + + {{item.label}} + + + + + 重置 + 应用筛选 + + + + + + + 为你推荐 + {{hasActiveFilter ? '已按当前条件筛选' : '认真认识,再做选择'}} + + {{users.length}} 位 - 为你推荐{{hasActiveFilter ? '已按当前条件筛选' : '认真认识,再做选择'}}{{users.length}} 位 + - + + + + + 真诚相遇,认真选择 - 暂无符合条件的人选Required 条件不会自动放宽,可以调整筛选后再看看清空筛选 + + + + 暂无符合条件的人选 + Required 条件不会自动放宽,可以调整筛选后再看看 + 清空筛选 +