feat(discover): chip-targeted filter panel — scroll to + highlight target section
- Each filter chip (年龄/学历/婚姻) carries data-target pointing to its section - openFilterPanel receives TouchEvent, maps target to section id, sets panelScrollTo + panelHighlight - Panel uses scroll-view scroll-into-view with scroll-with-animation for smooth scroll - Targeted section gets pink outline highlight via .hl class - Non-targeted sections remain normally visible for context
This commit is contained in:
@@ -44,6 +44,9 @@ interface DiscoverData {
|
|||||||
educations: Array<{ code: string; label: string }>;
|
educations: Array<{ code: string; label: string }>;
|
||||||
maritalStatuses: Array<{ code: string; label: string }>;
|
maritalStatuses: Array<{ code: string; label: string }>;
|
||||||
actionLoadingUserId: string;
|
actionLoadingUserId: string;
|
||||||
|
// 抽屉滚动/高亮定位
|
||||||
|
panelScrollTo: string;
|
||||||
|
panelHighlight: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_MIN_AGE = 18;
|
const DEFAULT_MIN_AGE = 18;
|
||||||
@@ -89,6 +92,8 @@ Page({
|
|||||||
{ code: 'divorced', label: '离异' },
|
{ code: 'divorced', label: '离异' },
|
||||||
],
|
],
|
||||||
actionLoadingUserId: '',
|
actionLoadingUserId: '',
|
||||||
|
panelScrollTo: '',
|
||||||
|
panelHighlight: '',
|
||||||
} as DiscoverData,
|
} as DiscoverData,
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -186,9 +191,10 @@ Page({
|
|||||||
this.fetchDiscover(true);
|
this.fetchDiscover(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 打开筛选面板,并同步当前 applied 状态到 temp */
|
/** 打开筛选面板,并同步当前 applied 状态到 temp,可选定位到 target section */
|
||||||
openFilterPanel() {
|
openFilterPanel(e?: WechatMiniprogram.TouchEvent) {
|
||||||
console.log('[discover] openFilterPanel called');
|
const target = e ? (e.currentTarget.dataset as any).target as string | undefined : undefined;
|
||||||
|
const sectionMap: Record<string, string> = { age: 'sec-age', education: 'sec-education', marital: 'sec-marital', region: 'sec-region' };
|
||||||
const a = this.data.applied;
|
const a = this.data.applied;
|
||||||
this.setData({
|
this.setData({
|
||||||
showFilter: true,
|
showFilter: true,
|
||||||
@@ -197,8 +203,8 @@ Page({
|
|||||||
tempMaxAge: a.maxAge,
|
tempMaxAge: a.maxAge,
|
||||||
tempEducationCode: a.educationCode,
|
tempEducationCode: a.educationCode,
|
||||||
tempMaritalStatus: a.maritalStatus,
|
tempMaritalStatus: a.maritalStatus,
|
||||||
}, () => {
|
panelScrollTo: target ? (sectionMap[target] || '') : '',
|
||||||
console.log('[discover] showFilter set to true, current state:', JSON.stringify(this.data.applied));
|
panelHighlight: target || '',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
<view class="filter-chips">
|
<view class="filter-chips">
|
||||||
<view class="filter-chip {{!hasActiveFilter ? 'active' : ''}}" bindtap="onResetFilter">推荐</view>
|
<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.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.minAge !== 18 || applied.maxAge !== 60 ? 'active' : ''}}" bindtap="openFilterPanel" data-target="age">年龄</view>
|
||||||
<view class="filter-chip {{!!applied.educationCode ? 'active' : ''}}" bindtap="openFilterPanel">学历</view>
|
<view class="filter-chip {{!!applied.educationCode ? 'active' : ''}}" bindtap="openFilterPanel" data-target="education">学历</view>
|
||||||
<view class="filter-chip {{!!applied.maritalStatus ? 'active' : ''}}" bindtap="openFilterPanel">婚姻</view>
|
<view class="filter-chip {{!!applied.maritalStatus ? 'active' : ''}}" bindtap="openFilterPanel" data-target="marital">婚姻</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
@@ -30,47 +30,49 @@
|
|||||||
<block wx:if="{{showFilter}}">
|
<block wx:if="{{showFilter}}">
|
||||||
<view class="filter-mask" bindtap="closeFilterPanel"></view>
|
<view class="filter-mask" bindtap="closeFilterPanel"></view>
|
||||||
<view class="filter-panel-wrap">
|
<view class="filter-panel-wrap">
|
||||||
<!-- 年龄范围 -->
|
<scroll-view scroll-y class="filter-scroll-wrap" scroll-into-view="{{panelScrollTo}}" scroll-with-animation>
|
||||||
<view class="filter-section">
|
<!-- 年龄范围 -->
|
||||||
<view class="filter-heading">
|
<view id="sec-age" class="filter-section {{panelHighlight === 'age' ? 'hl' : ''}}">
|
||||||
<text class="filter-label">年龄范围</text>
|
<view class="filter-heading">
|
||||||
<text class="filter-value">{{tempMinAge}}–{{tempMaxAge}} 岁</text>
|
<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>
|
||||||
<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">
|
<view id="sec-region" class="filter-section {{panelHighlight === 'region' ? 'hl' : ''}}">
|
||||||
<text class="filter-label">地区</text>
|
<text class="filter-label">地区</text>
|
||||||
<view class="tag-group">
|
<view class="tag-group">
|
||||||
<view wx:for="{{regions}}" wx:key="code"
|
<view wx:for="{{regions}}" wx:key="code"
|
||||||
class="tag {{tempRegionCode === item.code ? 'selected' : ''}}"
|
class="tag {{tempRegionCode === item.code ? 'selected' : ''}}"
|
||||||
bindtap="onPanelRegionTap" data-code="{{item.code}}">{{item.label}}</view>
|
bindtap="onPanelRegionTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 学历 -->
|
<!-- 学历 -->
|
||||||
<view class="filter-section">
|
<view id="sec-education" class="filter-section {{panelHighlight === 'education' ? 'hl' : ''}}">
|
||||||
<text class="filter-label">学历</text>
|
<text class="filter-label">学历</text>
|
||||||
<view class="tag-group">
|
<view class="tag-group">
|
||||||
<view wx:for="{{educations}}" wx:key="code"
|
<view wx:for="{{educations}}" wx:key="code"
|
||||||
class="tag {{tempEducationCode === item.code ? 'selected' : ''}}"
|
class="tag {{tempEducationCode === item.code ? 'selected' : ''}}"
|
||||||
bindtap="onPanelEducationTap" data-code="{{item.code}}">{{item.label}}</view>
|
bindtap="onPanelEducationTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 婚姻状态 -->
|
<!-- 婚姻状态 -->
|
||||||
<view class="filter-section">
|
<view id="sec-marital" class="filter-section {{panelHighlight === 'marital' ? 'hl' : ''}}">
|
||||||
<text class="filter-label">婚姻状态</text>
|
<text class="filter-label">婚姻状态</text>
|
||||||
<view class="tag-group">
|
<view class="tag-group">
|
||||||
<view wx:for="{{maritalStatuses}}" wx:key="code"
|
<view wx:for="{{maritalStatuses}}" wx:key="code"
|
||||||
class="tag {{tempMaritalStatus === item.code ? 'selected' : ''}}"
|
class="tag {{tempMaritalStatus === item.code ? 'selected' : ''}}"
|
||||||
bindtap="onPanelMaritalTap" data-code="{{item.code}}">{{item.label}}</view>
|
bindtap="onPanelMaritalTap" data-code="{{item.code}}">{{item.label}}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</scroll-view>
|
||||||
|
|
||||||
<view class="filter-actions">
|
<view class="filter-actions">
|
||||||
<ui-button variant="ghost" size="md" block bind:tap="onResetFilter">重置</ui-button>
|
<ui-button variant="ghost" size="md" block bind:tap="onResetFilter">重置</ui-button>
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
/* 遮罩层 + 底部抽屉样式 */
|
/* 遮罩层 + 底部抽屉样式 */
|
||||||
.filter-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.35);z-index:10}
|
.filter-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.35);z-index:10}
|
||||||
.filter-panel-wrap{position:fixed;left:0;right:0;bottom:0;z-index:11;background:#fff;border-radius:28rpx 28rpx 0 0;max-height:78vh;padding:32rpx 28rpx calc(28rpx + env(safe-area-inset-bottom));box-shadow:0 -10rpx 40rpx rgba(31,32,89,.15);overflow-y:auto}
|
.filter-panel-wrap{position:fixed;left:0;right:0;bottom:0;z-index:11;background:#fff;border-radius:28rpx 28rpx 0 0;max-height:78vh;box-shadow:0 -10rpx 40rpx rgba(31,32,89,.15);display:flex;flex-direction:column;padding:24rpx 28rpx 28rpx}
|
||||||
.filter-section{margin-bottom:28rpx}
|
.filter-scroll-wrap{flex:1;max-height:calc(78vh - 140rpx);padding:8rpx 0 0}
|
||||||
|
.filter-section{margin-bottom:28rpx;padding:16rpx 20rpx;border-radius:16rpx;transition:background .2s,box-shadow .2s}
|
||||||
|
.filter-section.hl{background:#FFF5F8;box-shadow:inset 0 0 0 2rpx var(--mini-accent-pink)}
|
||||||
.filter-heading{display:flex;justify-content:space-between}
|
.filter-heading{display:flex;justify-content:space-between}
|
||||||
.filter-label{display:block;font-size:24rpx;font-weight:650;color:#282D4E}
|
.filter-label{display:block;font-size:24rpx;font-weight:650;color:#282D4E}
|
||||||
.filter-value{font-size:21rpx;color:#777E99}
|
.filter-value{font-size:21rpx;color:#777E99}
|
||||||
|
|||||||
Reference in New Issue
Block a user