feat(discover): rewrite filter UI to align with backend DiscoverController 5 params
- Top chips: 推荐(重置) / 丹阳本地(regionCode=321181) / 年龄 / 学历 / 婚姻 - Each chip has real active state bound to applied filter value - Panel expanded to 4 sections: age slider + region + education + maritalStatus - Param names fixed: minAge/maxAge/regionCode/educationCode/maritalStatus - Data flow: panel temp -> onApplyFilter -> applied -> _buildParams -> API - Panel opens with current applied values, closes with openFilterPanel/closeFilterPanel
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* 找对象页 U19-U20(TypeScript)
|
* 找对象页 — 筛选对齐后端 DiscoverController 5 个筛选参数:
|
||||||
|
* minAge, maxAge, regionCode, maritalStatus, educationCode
|
||||||
*
|
*
|
||||||
* 不变量(AGENTS.md):
|
* 不变量(AGENTS.md):
|
||||||
* - 第 2 条:Required 不可自动放宽——Discover 搜索仅透传筛选条件到后端
|
* - Required 不可自动放宽——Discover 仅透传筛选条件到后端
|
||||||
* - 第 4 条:Block 即时禁止互动
|
* - Block 即时禁止互动
|
||||||
* - 第 6 条:单向意向不泄露
|
* - 单向意向不泄露
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
import { matchStore, appStore, authStore } from '../../stores';
|
import { matchStore, appStore, authStore } from '../../stores';
|
||||||
@@ -14,6 +15,15 @@ import { recommendationService } from '../../services';
|
|||||||
import { to } from '../../constants';
|
import { to } from '../../constants';
|
||||||
import type { RecommendationCandidate } from '../../types';
|
import type { RecommendationCandidate } from '../../types';
|
||||||
|
|
||||||
|
interface AppliedFilter {
|
||||||
|
keyword: string;
|
||||||
|
regionCode: string; // 后端参数名
|
||||||
|
minAge: number;
|
||||||
|
maxAge: number;
|
||||||
|
educationCode: string; // 后端参数名
|
||||||
|
maritalStatus: string; // 后端参数名
|
||||||
|
}
|
||||||
|
|
||||||
interface DiscoverData {
|
interface DiscoverData {
|
||||||
users: RecommendationCandidate[];
|
users: RecommendationCandidate[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@@ -22,18 +32,22 @@ interface DiscoverData {
|
|||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
keywordInput: string;
|
keywordInput: string;
|
||||||
showFilter: boolean;
|
showFilter: boolean;
|
||||||
tempRegion: string;
|
// 面板临时态
|
||||||
tempAgeMin: number;
|
tempRegionCode: string;
|
||||||
tempAgeMax: number;
|
tempMinAge: number;
|
||||||
applied: { keyword: string; region: string; ageMin: number; ageMax: number };
|
tempMaxAge: number;
|
||||||
|
tempEducationCode: string;
|
||||||
|
tempMaritalStatus: string;
|
||||||
|
applied: AppliedFilter;
|
||||||
hasActiveFilter: boolean;
|
hasActiveFilter: boolean;
|
||||||
regions: string[];
|
regions: Array<{ code: string; label: string }>;
|
||||||
|
educations: Array<{ code: string; label: string }>;
|
||||||
|
maritalStatuses: Array<{ code: string; label: string }>;
|
||||||
actionLoadingUserId: string;
|
actionLoadingUserId: string;
|
||||||
emptyActions: Array<{ text: string; event: string; variant: string }>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_AGE_MIN = 18;
|
const DEFAULT_MIN_AGE = 18;
|
||||||
const DEFAULT_AGE_MAX = 60;
|
const DEFAULT_MAX_AGE = 60;
|
||||||
const PAGE_SIZE = 20;
|
const PAGE_SIZE = 20;
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
@@ -45,18 +59,37 @@ Page({
|
|||||||
hasMore: true,
|
hasMore: true,
|
||||||
keywordInput: '',
|
keywordInput: '',
|
||||||
showFilter: false,
|
showFilter: false,
|
||||||
tempRegion: '',
|
tempRegionCode: '',
|
||||||
tempAgeMin: DEFAULT_AGE_MIN,
|
tempMinAge: DEFAULT_MIN_AGE,
|
||||||
tempAgeMax: DEFAULT_AGE_MAX,
|
tempMaxAge: DEFAULT_MAX_AGE,
|
||||||
applied: { keyword: '', region: '', ageMin: DEFAULT_AGE_MIN, ageMax: DEFAULT_AGE_MAX },
|
tempEducationCode: '',
|
||||||
hasActiveFilter: false,
|
tempMaritalStatus: '',
|
||||||
regions: ['丹阳', '镇江', '南京'],
|
applied: {
|
||||||
actionLoadingUserId: '',
|
keyword: '',
|
||||||
emptyActions: [
|
regionCode: '',
|
||||||
{ text: '清空筛选', event: 'reset', variant: 'primary' },
|
minAge: DEFAULT_MIN_AGE,
|
||||||
{ text: '去今日推荐', event: 'home', variant: 'secondary' },
|
maxAge: DEFAULT_MAX_AGE,
|
||||||
],
|
educationCode: '',
|
||||||
|
maritalStatus: '',
|
||||||
},
|
},
|
||||||
|
hasActiveFilter: false,
|
||||||
|
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() {
|
onLoad() {
|
||||||
if (!authStore.state.isLoggedIn) return;
|
if (!authStore.state.isLoggedIn) return;
|
||||||
@@ -67,7 +100,7 @@ Page({
|
|||||||
if (this.data.loading) return;
|
if (this.data.loading) return;
|
||||||
this.setData({ loading: true });
|
this.setData({ loading: true });
|
||||||
try {
|
try {
|
||||||
// @ts-ignore - recommendationService 接口待 TypeScript 化
|
// @ts-ignore - recommendationService 接口待 TS 化
|
||||||
const result = await recommendationService.discover(this._buildParams());
|
const result = await recommendationService.discover(this._buildParams());
|
||||||
const items: RecommendationCandidate[] = (result?.items as RecommendationCandidate[]) || [];
|
const items: RecommendationCandidate[] = (result?.items as RecommendationCandidate[]) || [];
|
||||||
this.setData({
|
this.setData({
|
||||||
@@ -104,16 +137,29 @@ Page({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 对齐后端 DiscoverController 5 个筛选参数 */
|
||||||
_buildParams() {
|
_buildParams() {
|
||||||
const { applied } = this.data;
|
const a = this.data.applied;
|
||||||
const params: Record<string, unknown> = { pageSize: PAGE_SIZE };
|
const params: Record<string, unknown> = { pageSize: PAGE_SIZE };
|
||||||
if (applied.keyword) params.keyword = applied.keyword;
|
if (a.keyword) params.keyword = a.keyword;
|
||||||
if (applied.region) params.region = applied.region;
|
if (a.regionCode) params.regionCode = a.regionCode;
|
||||||
if (applied.ageMin !== DEFAULT_AGE_MIN) params.ageMin = applied.ageMin;
|
if (a.minAge !== DEFAULT_MIN_AGE) params.minAge = a.minAge;
|
||||||
if (applied.ageMax !== DEFAULT_AGE_MAX) params.ageMax = applied.ageMax;
|
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;
|
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) {
|
onKeywordInput(e: any) {
|
||||||
this.setData({ keywordInput: e.detail.value });
|
this.setData({ keywordInput: e.detail.value });
|
||||||
},
|
},
|
||||||
@@ -125,68 +171,109 @@ Page({
|
|||||||
this.fetchDiscover(true);
|
this.fetchDiscover(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleFilter() {
|
// ========== 顶部 chip 点击(即时应用) ==========
|
||||||
this.setData({ showFilter: !this.data.showFilter });
|
|
||||||
},
|
|
||||||
|
|
||||||
onRegionTap(e: WechatMiniprogram.TouchEvent) {
|
onTopRegionTap() {
|
||||||
const val = (e.currentTarget.dataset as any).val as string;
|
// 丹阳本地 chip:regionCode=321181
|
||||||
this.setData({ tempRegion: this.data.tempRegion === val ? '' : val });
|
const target = '321181';
|
||||||
},
|
const nextCode = this.data.applied.regionCode === target ? '' : target;
|
||||||
|
const applied = { ...this.data.applied, regionCode: nextCode };
|
||||||
/** 顶部"丹阳本地" 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 };
|
|
||||||
this.setData({
|
this.setData({
|
||||||
tempRegion: nextRegion,
|
tempRegionCode: nextCode,
|
||||||
applied,
|
applied,
|
||||||
hasActiveFilter: this._hasActiveFilter(applied),
|
hasActiveFilter: this._hasActiveFilter(applied),
|
||||||
});
|
});
|
||||||
this.fetchDiscover(true);
|
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) {
|
onMinAgeChange(e: any) {
|
||||||
let min = Number((e as any).detail.value);
|
let min = Number(e.detail.value);
|
||||||
if (min > this.data.tempAgeMax) min = this.data.tempAgeMax;
|
if (min > this.data.tempMaxAge) min = this.data.tempMaxAge;
|
||||||
this.setData({ tempAgeMin: min });
|
this.setData({ tempMinAge: min });
|
||||||
},
|
},
|
||||||
|
|
||||||
onMaxAgeChange(e: any) {
|
onMaxAgeChange(e: any) {
|
||||||
let max = Number((e as any).detail.value);
|
let max = Number(e.detail.value);
|
||||||
if (max < this.data.tempAgeMin) max = this.data.tempAgeMin;
|
if (max < this.data.tempMinAge) max = this.data.tempMinAge;
|
||||||
this.setData({ tempAgeMax: max });
|
this.setData({ tempMaxAge: max });
|
||||||
},
|
},
|
||||||
|
|
||||||
onApplyFilter() {
|
onApplyFilter() {
|
||||||
const { tempRegion, tempAgeMin, tempAgeMax, keywordInput } = this.data;
|
const a = this.data.applied;
|
||||||
const applied = { keyword: (keywordInput || '').trim(), region: tempRegion, ageMin: tempAgeMin, ageMax: tempAgeMax };
|
const applied: AppliedFilter = {
|
||||||
this.setData({ applied, hasActiveFilter: this._hasActiveFilter(applied), showFilter: false });
|
keyword: a.keyword,
|
||||||
this.fetchDiscover(true);
|
regionCode: this.data.tempRegionCode,
|
||||||
},
|
minAge: this.data.tempMinAge,
|
||||||
|
maxAge: this.data.tempMaxAge,
|
||||||
onResetFilter() {
|
educationCode: this.data.tempEducationCode,
|
||||||
const applied = { keyword: '', region: '', ageMin: DEFAULT_AGE_MIN, ageMax: DEFAULT_AGE_MAX };
|
maritalStatus: this.data.tempMaritalStatus,
|
||||||
|
};
|
||||||
this.setData({
|
this.setData({
|
||||||
keywordInput: '', tempRegion: '', tempAgeMin: DEFAULT_AGE_MIN, tempAgeMax: DEFAULT_AGE_MAX,
|
applied,
|
||||||
applied, hasActiveFilter: false, showFilter: false,
|
hasActiveFilter: this._hasActiveFilter(applied),
|
||||||
|
showFilter: false,
|
||||||
});
|
});
|
||||||
this.fetchDiscover(true);
|
this.fetchDiscover(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
_hasActiveFilter(applied: { keyword: string; region: string; ageMin: number; ageMax: number }) {
|
onResetFilter() {
|
||||||
return !!(
|
const applied: AppliedFilter = {
|
||||||
applied.keyword || applied.region ||
|
keyword: '',
|
||||||
applied.ageMin !== DEFAULT_AGE_MIN || applied.ageMax !== DEFAULT_AGE_MAX
|
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) {
|
onViewDetail(e: WechatMiniprogram.TouchEvent) {
|
||||||
const { userId } = (e.detail as any) || {};
|
const { userId } = (e.detail as any) || {};
|
||||||
|
|||||||
@@ -1,24 +1,108 @@
|
|||||||
<view class="page app-page reference-page">
|
<view class="page app-page reference-page">
|
||||||
<view class="discover-hero">
|
<view class="discover-hero">
|
||||||
<view class="discover-nav"><text class="nav-title">找对象</text><view class="nav-search" bindtap="toggleFilter"><image src="/assets/icons/ui/search.png" mode="aspectFit" /></view></view>
|
<view class="discover-nav">
|
||||||
|
<text class="nav-title">找对象</text>
|
||||||
|
<view class="nav-search" bindtap="{{showFilter ? 'closeFilterPanel' : 'openFilterPanel'}}">
|
||||||
|
<image src="/assets/icons/ui/search.png" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view class="search-bar">
|
<view class="search-bar">
|
||||||
<view class="search-input"><text class="search-label">搜索</text><input class="search-field" placeholder="姓名、职业或地区" placeholder-class="search-placeholder" value="{{keywordInput}}" bindinput="onKeywordInput" confirm-type="search" bindconfirm="onSearch" /></view>
|
<view class="search-input">
|
||||||
|
<text class="search-label">搜索</text>
|
||||||
|
<input class="search-field" placeholder="姓名、职业或地区" placeholder-class="search-placeholder"
|
||||||
|
value="{{keywordInput}}" bindinput="onKeywordInput" confirm-type="search" bindconfirm="onSearch" />
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-x class="filter-scroll discover-filter-chips"><view class="filter-chips"><view class="filter-chip {{!hasActiveFilter ? 'active' : ''}}" bindtap="onResetFilter">推荐</view><view class="filter-chip {{applied.region === '丹阳' ? 'active' : ''}}" bindtap="onTopRegionTap" data-val="丹阳">丹阳本地</view><view class="filter-chip" bindtap="toggleFilter">附近</view><view class="filter-chip {{applied.ageMin !== 18 || applied.ageMax !== 60 ? 'active' : ''}}" bindtap="toggleFilter">年龄</view><view class="filter-chip" bindtap="toggleFilter">学历</view><view class="filter-chip {{hasActiveFilter ? 'active' : ''}}" bindtap="toggleFilter">更多筛选</view></view></scroll-view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 顶部 chip — 每个都有真实 active 状态,对应后端 5 个筛选参数 -->
|
||||||
|
<scroll-view scroll-x class="filter-scroll">
|
||||||
|
<view class="filter-chips">
|
||||||
|
<view class="filter-chip {{!hasActiveFilter ? 'active' : ''}}" bindtap="onResetFilter">推荐</view>
|
||||||
|
<view class="filter-chip {{applied.regionCode === '321181' ? 'active' : ''}}" bindtap="onTopRegionTap">丹阳本地</view>
|
||||||
|
<view class="filter-chip {{applied.minAge !== 18 || applied.maxAge !== 60 ? 'active' : ''}}" bindtap="openFilterPanel">年龄</view>
|
||||||
|
<view class="filter-chip {{!!applied.educationCode ? 'active' : ''}}" bindtap="openFilterPanel">学历</view>
|
||||||
|
<view class="filter-chip {{!!applied.maritalStatus ? 'active' : ''}}" bindtap="openFilterPanel">婚姻</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 筛选面板:年龄 + 地区 + 学历 + 婚姻状态(与后端 DiscoverController 参数完全对齐) -->
|
||||||
<view wx:if="{{showFilter}}" class="filter-panel">
|
<view wx:if="{{showFilter}}" class="filter-panel">
|
||||||
<view class="filter-section"><view class="filter-heading"><text class="filter-label">年龄范围</text><text class="filter-value">{{tempAgeMin}}–{{tempAgeMax}} 岁</text></view><slider class="range-slider" min="18" max="60" value="{{tempAgeMin}}" activeColor="#FF4F91" backgroundColor="#E9EAF2" block-size="18" bindchange="onMinAgeChange" /><slider class="range-slider" min="18" max="60" value="{{tempAgeMax}}" activeColor="#7B63D9" backgroundColor="#E9EAF2" block-size="18" bindchange="onMaxAgeChange" /></view>
|
<!-- 年龄范围 -->
|
||||||
<view class="filter-section"><text class="filter-label">地区</text><view class="tag-group"><view wx:for="{{regions}}" wx:key="*this" class="tag {{tempRegion === item ? 'selected' : ''}}" bindtap="onRegionTap" data-val="{{item}}">{{item}}</view></view></view>
|
<view class="filter-section">
|
||||||
<view class="filter-actions"><ui-button variant="ghost" size="md" block bind:tap="onResetFilter">重置</ui-button><ui-button variant="primary" size="md" block bind:tap="onApplyFilter">应用筛选</ui-button></view>
|
<view class="filter-heading">
|
||||||
|
<text class="filter-label">年龄范围</text>
|
||||||
|
<text class="filter-value">{{tempMinAge}}–{{tempMaxAge}} 岁</text>
|
||||||
|
</view>
|
||||||
|
<slider class="range-slider" min="18" max="60" value="{{tempMinAge}}" activeColor="#FF4F91"
|
||||||
|
backgroundColor="#E9EAF2" block-size="18" bindchange="onMinAgeChange" />
|
||||||
|
<slider class="range-slider" min="18" max="60" value="{{tempMaxAge}}" activeColor="#7B63D9"
|
||||||
|
backgroundColor="#E9EAF2" block-size="18" bindchange="onMaxAgeChange" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 地区 -->
|
||||||
|
<view class="filter-section">
|
||||||
|
<text class="filter-label">地区</text>
|
||||||
|
<view class="tag-group">
|
||||||
|
<view wx:for="{{regions}}" wx:key="code"
|
||||||
|
class="tag {{tempRegionCode === item.code ? 'selected' : ''}}"
|
||||||
|
bindtap="onPanelRegionTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 学历 -->
|
||||||
|
<view class="filter-section">
|
||||||
|
<text class="filter-label">学历</text>
|
||||||
|
<view class="tag-group">
|
||||||
|
<view wx:for="{{educations}}" wx:key="code"
|
||||||
|
class="tag {{tempEducationCode === item.code ? 'selected' : ''}}"
|
||||||
|
bindtap="onPanelEducationTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 婚姻状态 -->
|
||||||
|
<view class="filter-section">
|
||||||
|
<text class="filter-label">婚姻状态</text>
|
||||||
|
<view class="tag-group">
|
||||||
|
<view wx:for="{{maritalStatuses}}" wx:key="code"
|
||||||
|
class="tag {{tempMaritalStatus === item.code ? 'selected' : ''}}"
|
||||||
|
bindtap="onPanelMaritalTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="filter-actions">
|
||||||
|
<ui-button variant="ghost" size="md" block bind:tap="onResetFilter">重置</ui-button>
|
||||||
|
<ui-button variant="primary" size="md" block bind:tap="onApplyFilter">应用筛选</ui-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 结果区 -->
|
||||||
|
<view class="result-head" wx:if="{{users.length > 0 || loading}}">
|
||||||
|
<view>
|
||||||
|
<text class="result-title">为你推荐</text>
|
||||||
|
<text class="result-subtitle">{{hasActiveFilter ? '已按当前条件筛选' : '认真认识,再做选择'}}</text>
|
||||||
|
</view>
|
||||||
|
<text class="result-count">{{users.length}} 位</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="result-head" wx:if="{{users.length > 0 || loading}}"><view><text class="result-title">为你推荐</text><text class="result-subtitle">{{hasActiveFilter ? '已按当前条件筛选' : '认真认识,再做选择'}}</text></view><text class="result-count">{{users.length}} 位</text></view>
|
|
||||||
<ui-loading wx:if="{{loading && users.length === 0}}" mode="skeleton" rows="5" />
|
<ui-loading wx:if="{{loading && users.length === 0}}" mode="skeleton" rows="5" />
|
||||||
|
|
||||||
<view wx:elif="{{users.length > 0}}" class="user-list candidate-list">
|
<view wx:elif="{{users.length > 0}}" class="user-list candidate-list">
|
||||||
<ui-user-card wx:for="{{users}}" wx:key="userId" user="{{item}}" bind:tap="onViewDetail"><view slot="actions" class="card-action" catchtap="onLike" data-user-id="{{item.userId}}"><view class="like-button {{actionLoadingUserId === item.userId ? 'loading' : ''}}"><image src="/assets/brand/logo-mark.png" mode="aspectFit" /></view></view></ui-user-card>
|
<ui-user-card wx:for="{{users}}" wx:key="userId" user="{{item}}" bind:tap="onViewDetail">
|
||||||
|
<view slot="actions" class="card-action" catchtap="onLike" data-user-id="{{item.userId}}">
|
||||||
|
<view class="like-button {{actionLoadingUserId === item.userId ? 'loading' : ''}}">
|
||||||
|
<image src="/assets/brand/logo-mark.png" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</ui-user-card>
|
||||||
<ui-loading wx:if="{{loadingMore}}" mode="spinner" inline text="加载更多…" />
|
<ui-loading wx:if="{{loadingMore}}" mode="spinner" inline text="加载更多…" />
|
||||||
<view wx:if="{{!hasMore && users.length > 0}}" class="list-end-hint">真诚相遇,认真选择</view>
|
<view wx:if="{{!hasMore && users.length > 0}}" class="list-end-hint">真诚相遇,认真选择</view>
|
||||||
</view>
|
</view>
|
||||||
<view wx:elif="{{!loading}}" class="discover-empty"><image src="/assets/brand/logo-mark.png" mode="aspectFit" /><text class="empty-title">暂无符合条件的人选</text><text class="empty-desc">Required 条件不会自动放宽,可以调整筛选后再看看</text><view class="empty-action" bindtap="onResetFilter">清空筛选</view></view>
|
|
||||||
|
<view wx:elif="{{!loading}}" class="discover-empty">
|
||||||
|
<image src="/assets/brand/logo-mark.png" mode="aspectFit" />
|
||||||
|
<text class="empty-title">暂无符合条件的人选</text>
|
||||||
|
<text class="empty-desc">Required 条件不会自动放宽,可以调整筛选后再看看</text>
|
||||||
|
<view class="empty-action" bindtap="onResetFilter">清空筛选</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
Reference in New Issue
Block a user