1050 lines
26 KiB
Vue
1050 lines
26 KiB
Vue
<template>
|
||
<view class="search-page">
|
||
<!-- 自定义导航栏 -->
|
||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||
<view class="navbar-content">
|
||
<view class="navbar-back" @click="handleBack">
|
||
<text class="back-icon">‹</text>
|
||
</view>
|
||
<text class="navbar-title">搜索</text>
|
||
<view class="navbar-placeholder"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容区域 -->
|
||
<scroll-view
|
||
class="content-scroll"
|
||
scroll-y
|
||
:style="{ paddingTop: (statusBarHeight + 44) + 'px' }"
|
||
>
|
||
<!-- 顶部Banner -->
|
||
<view class="banner-section">
|
||
<view class="banner-bg"></view>
|
||
<view class="banner-text">
|
||
<text class="banner-title">大胆说出</text>
|
||
<text class="banner-title">你的爱</text>
|
||
</view>
|
||
<view class="banner-decoration">
|
||
<text class="deco-heart">💕</text>
|
||
<text class="deco-ring">💍</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 筛选表单 -->
|
||
<view class="filter-form">
|
||
<!-- 年龄要求 -->
|
||
<view class="filter-item" @click="showAgePicker">
|
||
<text class="filter-label">年龄要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ ageText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 身高要求 -->
|
||
<view class="filter-item" @click="showHeightPicker">
|
||
<text class="filter-label">身高要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ heightText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 学历要求(可多选) -->
|
||
<view class="filter-item-multi">
|
||
<text class="filter-label">学历要求(可多选)</text>
|
||
<view class="tag-group">
|
||
<view
|
||
v-for="edu in educationOptions"
|
||
:key="edu.value"
|
||
class="tag-item"
|
||
:class="{ active: filters.education.includes(edu.value) }"
|
||
@click="toggleEducation(edu.value)"
|
||
>
|
||
{{ edu.label }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 地区要求(可多选) -->
|
||
<view class="filter-item-multi">
|
||
<text class="filter-label">地区要求(可多选)</text>
|
||
<view class="tag-group">
|
||
<view
|
||
v-for="(city, index) in selectedCities"
|
||
:key="index"
|
||
class="tag-item active"
|
||
@click="removeCity(index)"
|
||
>
|
||
{{ city }}
|
||
<text class="tag-close">×</text>
|
||
</view>
|
||
<view class="tag-item add-tag" @click="showCityPicker">
|
||
+其他地区
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 月收入要求 -->
|
||
<view class="filter-item" @click="showIncomePicker">
|
||
<text class="filter-label">月收入要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ incomeText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 房产要求 -->
|
||
<view class="filter-item" @click="showHousePicker">
|
||
<text class="filter-label">房产要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ houseText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 车产要求 -->
|
||
<view class="filter-item" @click="showCarPicker">
|
||
<text class="filter-label">车产要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ carText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 婚姻要求 -->
|
||
<view class="filter-item" @click="showMarriagePicker">
|
||
<text class="filter-label">婚姻要求</text>
|
||
<view class="filter-value">
|
||
<text>{{ marriageText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 搜索按钮 -->
|
||
<view class="search-btn-section">
|
||
<button class="btn-search" @click="handleSearch">立即搜索</button>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 年龄选择弹窗 -->
|
||
<view class="picker-popup" v-if="showAgePopup" @click.self="showAgePopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showAgePopup = false">取消</text>
|
||
<text class="picker-title">年龄要求</text>
|
||
<text class="picker-confirm" @click="confirmAge">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="agePickerValue" @change="onAgeChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="age in ageMinOptions" :key="age" class="picker-item">{{ age }}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item">至</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view v-for="age in ageMaxOptions" :key="age" class="picker-item">{{ age }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 身高选择弹窗 -->
|
||
<view class="picker-popup" v-if="showHeightPopup" @click.self="showHeightPopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showHeightPopup = false">取消</text>
|
||
<text class="picker-title">身高要求</text>
|
||
<text class="picker-confirm" @click="confirmHeight">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="heightPickerValue" @change="onHeightChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="h in heightMinOptions" :key="h" class="picker-item">{{ h }}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item">至</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view v-for="h in heightMaxOptions" :key="h" class="picker-item">{{ h }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 收入选择弹窗 -->
|
||
<view class="picker-popup" v-if="showIncomePopup" @click.self="showIncomePopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showIncomePopup = false">取消</text>
|
||
<text class="picker-title">月收入要求</text>
|
||
<text class="picker-confirm" @click="confirmIncome">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="incomePickerValue" @change="onIncomeChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="item in incomeOptions" :key="item.value" class="picker-item">{{ item.label }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 房产选择弹窗 -->
|
||
<view class="picker-popup" v-if="showHousePopup" @click.self="showHousePopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showHousePopup = false">取消</text>
|
||
<text class="picker-title">房产要求</text>
|
||
<text class="picker-confirm" @click="confirmHouse">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="housePickerValue" @change="onHouseChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="item in houseOptions" :key="item.value" class="picker-item">{{ item.label }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 车产选择弹窗 -->
|
||
<view class="picker-popup" v-if="showCarPopup" @click.self="showCarPopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showCarPopup = false">取消</text>
|
||
<text class="picker-title">车产要求</text>
|
||
<text class="picker-confirm" @click="confirmCar">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="carPickerValue" @change="onCarChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="item in carOptions" :key="item.value" class="picker-item">{{ item.label }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 婚姻选择弹窗 -->
|
||
<view class="picker-popup" v-if="showMarriagePopup" @click.self="showMarriagePopup = false">
|
||
<view class="picker-content">
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showMarriagePopup = false">取消</text>
|
||
<text class="picker-title">婚姻要求</text>
|
||
<text class="picker-confirm" @click="confirmMarriage">确定</text>
|
||
</view>
|
||
<view class="picker-body">
|
||
<picker-view :value="marriagePickerValue" @change="onMarriageChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view v-for="item in marriageOptions" :key="item.value" class="picker-item">{{ item.label }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 城市选择弹窗 -->
|
||
<view class="picker-popup" v-if="showCityPopup" @click="closeCityPopup">
|
||
<view class="picker-content city-picker-content" @click.stop>
|
||
<view class="picker-header">
|
||
<text class="picker-cancel" @click="showCityPopup = false">取消</text>
|
||
<text class="picker-title">选择地区</text>
|
||
<text class="picker-confirm" @click="showCityPopup = false">完成</text>
|
||
</view>
|
||
|
||
<!-- 热门城市 -->
|
||
<view class="city-section">
|
||
<view class="section-title">热门城市</view>
|
||
<view class="city-grid">
|
||
<view
|
||
v-for="city in hotCities"
|
||
:key="city"
|
||
class="city-item"
|
||
:class="{ selected: selectedCities.includes(city) }"
|
||
@click.stop="toggleCity(city)"
|
||
>
|
||
{{ city }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 省份列表 -->
|
||
<view class="province-section">
|
||
<view class="section-title">按省份选择</view>
|
||
<scroll-view scroll-y class="province-scroll">
|
||
<view
|
||
v-for="province in provinceData"
|
||
:key="province.name"
|
||
class="province-item"
|
||
>
|
||
<view class="province-name" @click.stop="toggleProvince(province.name)">
|
||
<text>{{ province.name }}</text>
|
||
<text class="province-arrow" :class="{ expanded: expandedProvince === province.name }">›</text>
|
||
</view>
|
||
<view class="city-list" v-if="expandedProvince === province.name">
|
||
<view
|
||
v-for="city in province.cities"
|
||
:key="city"
|
||
class="city-tag"
|
||
:class="{ selected: selectedCities.includes(city) }"
|
||
@click.stop="toggleCity(city)"
|
||
>
|
||
{{ city }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, onMounted } from 'vue'
|
||
import { provinceData, hotCities } from '@/utils/cityData.js'
|
||
|
||
// 状态栏高度
|
||
const statusBarHeight = ref(20)
|
||
|
||
// 获取系统信息
|
||
const getSystemInfo = () => {
|
||
uni.getSystemInfo({
|
||
success: (res) => {
|
||
statusBarHeight.value = res.statusBarHeight || 20
|
||
}
|
||
})
|
||
}
|
||
|
||
// 返回
|
||
const handleBack = () => {
|
||
uni.navigateBack()
|
||
}
|
||
|
||
// 筛选条件
|
||
const filters = reactive({
|
||
ageMin: 0,
|
||
ageMax: 0,
|
||
heightMin: 0,
|
||
heightMax: 0,
|
||
education: [],
|
||
cities: [],
|
||
monthlyIncome: 0,
|
||
houseStatus: 0,
|
||
carStatus: 0,
|
||
marriageStatus: 0
|
||
})
|
||
|
||
// 已选城市
|
||
const selectedCities = ref([])
|
||
|
||
// 弹窗显示状态
|
||
const showAgePopup = ref(false)
|
||
const showHeightPopup = ref(false)
|
||
const showIncomePopup = ref(false)
|
||
const showHousePopup = ref(false)
|
||
const showCarPopup = ref(false)
|
||
const showMarriagePopup = ref(false)
|
||
|
||
// 选项配置
|
||
const educationOptions = [
|
||
{ value: 0, label: '不限' },
|
||
{ value: 2, label: '中专' },
|
||
{ value: 1, label: '高中' },
|
||
{ value: 3, label: '大专' },
|
||
{ value: 4, label: '本科' },
|
||
{ value: 5, label: '研究生/博士' }
|
||
]
|
||
|
||
const incomeOptions = [
|
||
{ value: 0, label: '请选择' },
|
||
{ value: 1, label: '5000以下' },
|
||
{ value: 2, label: '5000-10000' },
|
||
{ value: 3, label: '10000-20000' },
|
||
{ value: 4, label: '20000-50000' },
|
||
{ value: 5, label: '50000以上' }
|
||
]
|
||
|
||
const houseOptions = [
|
||
{ value: 0, label: '请选择' },
|
||
{ value: 1, label: '现居地已购房' },
|
||
{ value: 2, label: '家乡已购房' },
|
||
{ value: 3, label: '婚后购房' },
|
||
{ value: 4, label: '父母同住' },
|
||
{ value: 5, label: '租房' },
|
||
{ value: 6, label: '近期有购房计划' }
|
||
]
|
||
|
||
const carOptions = [
|
||
{ value: 0, label: '请选择' },
|
||
{ value: 1, label: '已购车' },
|
||
{ value: 2, label: '无车' },
|
||
{ value: 3, label: '近期购车' }
|
||
]
|
||
|
||
const marriageOptions = [
|
||
{ value: 0, label: '请选择' },
|
||
{ value: 1, label: '未婚' },
|
||
{ value: 2, label: '离异未育' },
|
||
{ value: 3, label: '离异已育' }
|
||
]
|
||
|
||
// 年龄选项
|
||
const ageMinOptions = computed(() => {
|
||
const options = ['不限']
|
||
for (let a = 18; a <= 60; a++) {
|
||
options.push(a + '岁')
|
||
}
|
||
return options
|
||
})
|
||
|
||
const ageMaxOptions = computed(() => {
|
||
const options = ['不限']
|
||
for (let a = 18; a <= 60; a++) {
|
||
options.push(a + '岁')
|
||
}
|
||
return options
|
||
})
|
||
|
||
// 身高选项
|
||
const heightMinOptions = computed(() => {
|
||
const options = ['不限']
|
||
for (let h = 140; h <= 200; h++) {
|
||
options.push(h + 'cm')
|
||
}
|
||
return options
|
||
})
|
||
|
||
const heightMaxOptions = computed(() => {
|
||
const options = ['不限']
|
||
for (let h = 140; h <= 200; h++) {
|
||
options.push(h + 'cm')
|
||
}
|
||
return options
|
||
})
|
||
|
||
// Picker值
|
||
const agePickerValue = ref([0, 0, 0])
|
||
const heightPickerValue = ref([0, 0, 0])
|
||
const incomePickerValue = ref([0])
|
||
const housePickerValue = ref([0])
|
||
const carPickerValue = ref([0])
|
||
const marriagePickerValue = ref([0])
|
||
|
||
// 显示文本
|
||
const ageText = computed(() => {
|
||
if (!filters.ageMin && !filters.ageMax) return '请选择'
|
||
if (filters.ageMin && filters.ageMax) return `${filters.ageMin}-${filters.ageMax}岁`
|
||
if (filters.ageMin) return `${filters.ageMin}岁以上`
|
||
if (filters.ageMax) return `${filters.ageMax}岁以下`
|
||
return '请选择'
|
||
})
|
||
|
||
const heightText = computed(() => {
|
||
if (!filters.heightMin && !filters.heightMax) return '请选择'
|
||
if (filters.heightMin && filters.heightMax) return `${filters.heightMin}-${filters.heightMax}cm`
|
||
if (filters.heightMin) return `${filters.heightMin}cm以上`
|
||
if (filters.heightMax) return `${filters.heightMax}cm以下`
|
||
return '请选择'
|
||
})
|
||
|
||
const incomeText = computed(() => {
|
||
const item = incomeOptions.find(o => o.value === filters.monthlyIncome)
|
||
return item ? item.label : '请选择'
|
||
})
|
||
|
||
const houseText = computed(() => {
|
||
const item = houseOptions.find(o => o.value === filters.houseStatus)
|
||
return item ? item.label : '请选择'
|
||
})
|
||
|
||
const carText = computed(() => {
|
||
const item = carOptions.find(o => o.value === filters.carStatus)
|
||
return item ? item.label : '请选择'
|
||
})
|
||
|
||
const marriageText = computed(() => {
|
||
const item = marriageOptions.find(o => o.value === filters.marriageStatus)
|
||
return item ? item.label : '请选择'
|
||
})
|
||
|
||
// 显示弹窗
|
||
const showAgePicker = () => {
|
||
showAgePopup.value = true
|
||
}
|
||
|
||
const showHeightPicker = () => {
|
||
showHeightPopup.value = true
|
||
}
|
||
|
||
const showIncomePicker = () => {
|
||
showIncomePopup.value = true
|
||
}
|
||
|
||
const showHousePicker = () => {
|
||
showHousePopup.value = true
|
||
}
|
||
|
||
const showCarPicker = () => {
|
||
showCarPopup.value = true
|
||
}
|
||
|
||
const showMarriagePicker = () => {
|
||
showMarriagePopup.value = true
|
||
}
|
||
|
||
// Picker变化
|
||
const onAgeChange = (e) => {
|
||
agePickerValue.value = e.detail.value
|
||
}
|
||
|
||
const onHeightChange = (e) => {
|
||
heightPickerValue.value = e.detail.value
|
||
}
|
||
|
||
const onIncomeChange = (e) => {
|
||
incomePickerValue.value = e.detail.value
|
||
}
|
||
|
||
const onHouseChange = (e) => {
|
||
housePickerValue.value = e.detail.value
|
||
}
|
||
|
||
const onCarChange = (e) => {
|
||
carPickerValue.value = e.detail.value
|
||
}
|
||
|
||
const onMarriageChange = (e) => {
|
||
marriagePickerValue.value = e.detail.value
|
||
}
|
||
|
||
// 确认选择
|
||
const confirmAge = () => {
|
||
const minIdx = agePickerValue.value[0]
|
||
const maxIdx = agePickerValue.value[2]
|
||
filters.ageMin = minIdx === 0 ? 0 : minIdx + 17
|
||
filters.ageMax = maxIdx === 0 ? 0 : maxIdx + 17
|
||
showAgePopup.value = false
|
||
}
|
||
|
||
const confirmHeight = () => {
|
||
const minIdx = heightPickerValue.value[0]
|
||
const maxIdx = heightPickerValue.value[2]
|
||
filters.heightMin = minIdx === 0 ? 0 : minIdx + 139
|
||
filters.heightMax = maxIdx === 0 ? 0 : maxIdx + 139
|
||
showHeightPopup.value = false
|
||
}
|
||
|
||
const confirmIncome = () => {
|
||
filters.monthlyIncome = incomeOptions[incomePickerValue.value[0]].value
|
||
showIncomePopup.value = false
|
||
}
|
||
|
||
const confirmHouse = () => {
|
||
filters.houseStatus = houseOptions[housePickerValue.value[0]].value
|
||
showHousePopup.value = false
|
||
}
|
||
|
||
const confirmCar = () => {
|
||
filters.carStatus = carOptions[carPickerValue.value[0]].value
|
||
showCarPopup.value = false
|
||
}
|
||
|
||
const confirmMarriage = () => {
|
||
filters.marriageStatus = marriageOptions[marriagePickerValue.value[0]].value
|
||
showMarriagePopup.value = false
|
||
}
|
||
|
||
// 学历多选
|
||
const toggleEducation = (value) => {
|
||
if (value === 0) {
|
||
// 选择不限时清空其他选择
|
||
filters.education = [0]
|
||
return
|
||
}
|
||
|
||
// 移除不限
|
||
const noLimitIdx = filters.education.indexOf(0)
|
||
if (noLimitIdx >= 0) {
|
||
filters.education.splice(noLimitIdx, 1)
|
||
}
|
||
|
||
const idx = filters.education.indexOf(value)
|
||
if (idx >= 0) {
|
||
filters.education.splice(idx, 1)
|
||
} else {
|
||
filters.education.push(value)
|
||
}
|
||
}
|
||
|
||
// 城市选择弹窗
|
||
const showCityPopup = ref(false)
|
||
|
||
// 展开的省份
|
||
const expandedProvince = ref('')
|
||
|
||
// 城市选择
|
||
const showCityPicker = () => {
|
||
showCityPopup.value = true
|
||
}
|
||
|
||
// 关闭城市弹窗(点击遮罩层)
|
||
const closeCityPopup = (e) => {
|
||
// 只有点击遮罩层才关闭
|
||
if (e.target === e.currentTarget) {
|
||
showCityPopup.value = false
|
||
}
|
||
}
|
||
|
||
// 切换省份展开
|
||
const toggleProvince = (provinceName) => {
|
||
if (expandedProvince.value === provinceName) {
|
||
expandedProvince.value = ''
|
||
} else {
|
||
expandedProvince.value = provinceName
|
||
}
|
||
}
|
||
|
||
// 切换城市选择
|
||
const toggleCity = (city) => {
|
||
const idx = selectedCities.value.indexOf(city)
|
||
if (idx >= 0) {
|
||
selectedCities.value.splice(idx, 1)
|
||
} else {
|
||
selectedCities.value.push(city)
|
||
}
|
||
}
|
||
|
||
const removeCity = (index) => {
|
||
selectedCities.value.splice(index, 1)
|
||
}
|
||
|
||
// 搜索
|
||
const handleSearch = () => {
|
||
// 构建搜索参数
|
||
const params = {
|
||
ageMin: filters.ageMin,
|
||
ageMax: filters.ageMax,
|
||
heightMin: filters.heightMin,
|
||
heightMax: filters.heightMax,
|
||
education: filters.education.filter(e => e !== 0),
|
||
cities: selectedCities.value,
|
||
monthlyIncome: filters.monthlyIncome,
|
||
houseStatus: filters.houseStatus,
|
||
carStatus: filters.carStatus,
|
||
marriageStatus: filters.marriageStatus
|
||
}
|
||
|
||
// 跳转到搜索结果页
|
||
uni.navigateTo({
|
||
url: `/pages/search/result?params=${encodeURIComponent(JSON.stringify(params))}`
|
||
})
|
||
}
|
||
|
||
onMounted(() => {
|
||
getSystemInfo()
|
||
})
|
||
</script>
|
||
|
||
|
||
<style lang="scss" scoped>
|
||
.search-page {
|
||
min-height: 100vh;
|
||
background-color: #f5f6fa;
|
||
}
|
||
|
||
// 自定义导航栏
|
||
.custom-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
background: linear-gradient(135deg, #ffb5b5 0%, #ff9a9a 100%);
|
||
|
||
.navbar-content {
|
||
height: 44px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 24rpx;
|
||
|
||
.navbar-back {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.back-icon {
|
||
font-size: 64rpx;
|
||
color: #fff;
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
|
||
.navbar-title {
|
||
font-size: 34rpx;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
}
|
||
|
||
.navbar-placeholder {
|
||
width: 80rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 内容滚动区域
|
||
.content-scroll {
|
||
min-height: 100vh;
|
||
padding-bottom: 60rpx;
|
||
}
|
||
|
||
// Banner区域
|
||
.banner-section {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 320rpx;
|
||
overflow: hidden;
|
||
|
||
.banner-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(135deg, #ffb5b5 0%, #ffd1d1 50%, #ffe4e4 100%);
|
||
}
|
||
|
||
.banner-text {
|
||
position: absolute;
|
||
left: 40rpx;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
z-index: 2;
|
||
|
||
.banner-title {
|
||
display: block;
|
||
font-size: 52rpx;
|
||
font-weight: bold;
|
||
color: #ff6b9d;
|
||
text-shadow: 2rpx 2rpx 4rpx rgba(255, 107, 157, 0.3);
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
|
||
.banner-decoration {
|
||
position: absolute;
|
||
right: 40rpx;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
z-index: 2;
|
||
|
||
.deco-heart {
|
||
font-size: 80rpx;
|
||
display: block;
|
||
animation: float 2s ease-in-out infinite;
|
||
}
|
||
|
||
.deco-ring {
|
||
font-size: 60rpx;
|
||
display: block;
|
||
margin-top: -20rpx;
|
||
margin-left: 40rpx;
|
||
animation: float 2s ease-in-out infinite 0.5s;
|
||
}
|
||
}
|
||
}
|
||
|
||
@keyframes float {
|
||
0%, 100% {
|
||
transform: translateY(0);
|
||
}
|
||
50% {
|
||
transform: translateY(-10rpx);
|
||
}
|
||
}
|
||
|
||
// 筛选表单
|
||
.filter-form {
|
||
background: #fff;
|
||
margin: 24rpx;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.filter-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 32rpx 28rpx;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.filter-value {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.arrow {
|
||
margin-left: 8rpx;
|
||
font-size: 28rpx;
|
||
color: #ccc;
|
||
}
|
||
}
|
||
}
|
||
|
||
.filter-item-multi {
|
||
padding: 28rpx;
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.filter-label {
|
||
display: block;
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
}
|
||
|
||
.tag-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
|
||
.tag-item {
|
||
padding: 16rpx 28rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
border: 2rpx solid transparent;
|
||
transition: all 0.2s;
|
||
|
||
&.active {
|
||
background: #fff5f5;
|
||
color: #ff6b6b;
|
||
border-color: #ff6b6b;
|
||
}
|
||
|
||
&.add-tag {
|
||
color: #999;
|
||
border: 2rpx dashed #ddd;
|
||
background: transparent;
|
||
}
|
||
|
||
.tag-close {
|
||
margin-left: 8rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 搜索按钮
|
||
.search-btn-section {
|
||
padding: 40rpx 24rpx;
|
||
|
||
.btn-search {
|
||
width: 100%;
|
||
height: 96rpx;
|
||
line-height: 96rpx;
|
||
background: linear-gradient(135deg, #ffb5b5 0%, #ff9a9a 100%);
|
||
border-radius: 48rpx;
|
||
font-size: 34rpx;
|
||
color: #fff;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Picker弹窗
|
||
.picker-popup {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
|
||
.picker-content {
|
||
width: 100%;
|
||
background: #fff;
|
||
border-radius: 24rpx 24rpx 0 0;
|
||
}
|
||
|
||
.picker-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 28rpx 32rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
|
||
.picker-cancel {
|
||
font-size: 30rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.picker-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.picker-confirm {
|
||
font-size: 30rpx;
|
||
color: #ff6b6b;
|
||
}
|
||
}
|
||
|
||
.picker-body {
|
||
height: 400rpx;
|
||
}
|
||
|
||
.picker-view {
|
||
height: 100%;
|
||
}
|
||
|
||
.picker-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
// 城市选择弹窗
|
||
.city-picker-content {
|
||
max-height: 80vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.picker-placeholder {
|
||
width: 60rpx;
|
||
}
|
||
}
|
||
|
||
.city-section {
|
||
padding: 20rpx 24rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.city-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 16rpx;
|
||
|
||
.city-item {
|
||
height: 64rpx;
|
||
line-height: 64rpx;
|
||
text-align: center;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
border: 2rpx solid transparent;
|
||
|
||
&.selected {
|
||
background: #fff5f5;
|
||
color: #ff6b6b;
|
||
border-color: #ff6b6b;
|
||
}
|
||
}
|
||
}
|
||
|
||
.province-section {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 20rpx 24rpx 0;
|
||
|
||
.section-title {
|
||
flex-shrink: 0;
|
||
}
|
||
}
|
||
|
||
.province-scroll {
|
||
flex: 1;
|
||
height: 500rpx;
|
||
}
|
||
|
||
.province-item {
|
||
border-bottom: 1rpx solid #f5f5f5;
|
||
|
||
.province-name {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx 0;
|
||
font-size: 30rpx;
|
||
color: #333;
|
||
|
||
.province-arrow {
|
||
font-size: 32rpx;
|
||
color: #ccc;
|
||
transition: transform 0.2s;
|
||
|
||
&.expanded {
|
||
transform: rotate(90deg);
|
||
}
|
||
}
|
||
}
|
||
|
||
.city-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
padding-bottom: 20rpx;
|
||
|
||
.city-tag {
|
||
padding: 12rpx 24rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
border: 2rpx solid transparent;
|
||
|
||
&.selected {
|
||
background: #fff5f5;
|
||
color: #ff6b6b;
|
||
border-color: #ff6b6b;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|