pet/pages/adoption/adoption.vue

1769 lines
40 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="adoption-container page-container-with-bg">
<!-- 头部搜索栏 -->
<view class="header-section">
<view class="search-wrapper">
<view class="search-input-container">
<text class="search-icon">🔍</text>
<input
class="search-input"
v-model="searchKeyword"
placeholder="搜索宠物名称、品种..."
@input="onSearchInput"
@confirm="performSearch"
/>
<view class="search-clear" v-if="searchKeyword" @click="clearSearch">
<text class="clear-icon">✕</text>
</view>
</view>
<view class="filter-btn" @click="toggleFilter">
<text class="filter-icon">🔧</text>
<text class="filter-text">筛选</text>
</view>
</view>
</view>
<!-- 筛选面板 -->
<view class="filter-panel" v-if="showFilter">
<!-- 地区筛选 -->
<view class="filter-section">
<view class="filter-title">
<text class="title-text">📍 地区</text>
</view>
<view class="region-selectors">
<view class="region-selector">
<picker
:value="selectedProvinceIndex"
:range="provinceOptions"
range-key="name"
@change="onProvinceChange"
>
<view class="selector-display">
<text class="selector-text">{{ selectedProvince ? selectedProvince.name : '选择省份' }}</text>
<text class="selector-arrow">▼</text>
</view>
</picker>
</view>
<view class="region-selector" v-if="cityOptions.length > 0">
<picker
:value="selectedCityIndex"
:range="cityOptions"
range-key="name"
@change="onCityChange"
>
<view class="selector-display">
<text class="selector-text">{{ selectedCity ? selectedCity.name : '选择城市' }}</text>
<text class="selector-arrow">▼</text>
</view>
</picker>
</view>
<view class="region-selector" v-if="districtOptions.length > 0">
<picker
:value="selectedDistrictIndex"
:range="districtOptions"
range-key="name"
@change="onDistrictChange"
>
<view class="selector-display">
<text class="selector-text">{{ selectedDistrict ? selectedDistrict.name : '选择区县' }}</text>
<text class="selector-arrow">▼</text>
</view>
</picker>
</view>
</view>
</view>
<!-- 宠物类型筛选 -->
<view class="filter-section">
<view class="filter-title">
<text class="title-text">🐾 宠物类型</text>
</view>
<view class="type-filters">
<view
class="type-filter"
:class="{ active: selectedType === 'all' }"
@click="selectType('all')"
>
<text class="type-text">全部</text>
</view>
<view
class="type-filter"
:class="{ active: selectedType === type.key }"
v-for="type in petTypeOptions"
:key="type.key"
@click="selectType(type.key)"
>
<text class="type-icon">{{ type.icon }}</text>
<text class="type-text">{{ type.name }}</text>
</view>
</view>
</view>
<!-- 品种筛选 -->
<view class="filter-section" v-if="selectedType !== 'all' && breedOptions.length > 0">
<view class="filter-title">
<text class="title-text">🏷️ 品种</text>
</view>
<view class="breed-filters">
<view
class="breed-filter"
:class="{ active: selectedBreed === 'all' }"
@click="selectBreed('all')"
>
<text class="breed-text">全部</text>
</view>
<view
class="breed-filter"
:class="{ active: selectedBreed === breed.key }"
v-for="breed in breedOptions"
:key="breed.key"
@click="selectBreed(breed.key)"
>
<text class="breed-text">{{ breed.name }}</text>
</view>
</view>
</view>
<!-- 其他筛选 -->
<view class="filter-section">
<view class="filter-title">
<text class="title-text">⚙️ 其他条件</text>
</view>
<view class="other-filters">
<view class="filter-row">
<text class="filter-label">状态:</text>
<view class="status-filters">
<view
class="status-filter"
:class="{ active: selectedStatus === 'all' }"
@click="selectStatus('all')"
>
<text class="status-text">全部</text>
</view>
<view
class="status-filter"
:class="{ active: selectedStatus === 'available' }"
@click="selectStatus('available')"
>
<text class="status-text">可领养</text>
</view>
</view>
</view>
<view class="filter-row">
<text class="filter-label">性别:</text>
<view class="gender-filters">
<view
class="gender-filter"
:class="{ active: selectedGender === 'all' }"
@click="selectGender('all')"
>
<text class="gender-text">全部</text>
</view>
<view
class="gender-filter"
:class="{ active: selectedGender === 'male' }"
@click="selectGender('male')"
>
<text class="gender-text">公</text>
</view>
<view
class="gender-filter"
:class="{ active: selectedGender === 'female' }"
@click="selectGender('female')"
>
<text class="gender-text">母</text>
</view>
</view>
</view>
</view>
</view>
<!-- 筛选操作按钮 -->
<view class="filter-actions">
<view class="filter-reset" @click="resetFilters">
<text class="reset-text">重置</text>
</view>
<view class="filter-apply" @click="applyFilters">
<text class="apply-text">应用筛选</text>
</view>
</view>
</view>
<!-- 宠物列表 -->
<scroll-view
class="pets-scroll"
scroll-y
@scrolltolower="loadMorePets"
@refresherrefresh="onRefresh"
:refresher-enabled="true"
:refresher-triggered="refreshing"
>
<view class="pets-list">
<!-- 结果统计 - 已隐藏 -->
<!-- <view class="result-summary" v-if="displayPets.length > 0">
<text class="summary-text">找到 {{ totalPets }} 只可爱的小伙伴</text>
</view> -->
<!-- 宠物卡片 -->
<view
class="pet-card"
v-for="pet in displayPets"
:key="pet.id"
@click="viewPetDetail(pet)"
>
<view class="pet-image-container">
<image class="pet-image" :src="pet.photos[0]" mode="aspectFill" />
<view class="pet-status" :class="pet.status">
<text class="status-icon">{{ getStatusIcon(pet.status) }}</text>
<text class="status-text">{{ getStatusText(pet.status) }}</text>
</view>
</view>
<view class="pet-info">
<view class="pet-basic">
<text class="pet-name">{{ pet.name }}</text>
<view class="pet-tags">
<text class="pet-type">{{ getPetTypeName(pet.type) }}</text>
<text class="pet-breed">{{ getPetBreedName(pet.type, pet.breed) }}</text>
</view>
</view>
<view class="pet-details">
<view class="detail-item">
<text class="detail-icon">🎂</text>
<text class="detail-text">{{ pet.age }}岁</text>
</view>
<view class="detail-item">
<u-icon
:name="pet.gender === 'male' ? 'man' : 'woman'"
:color="pet.gender === 'male' ? '#4A90E2' : '#FF69B4'"
size="16"
></u-icon>
<text class="detail-text">{{ pet.gender === 'male' ? '公' : '母' }}</text>
</view>
<view class="detail-item">
<text class="detail-icon">📍</text>
<text class="detail-text">{{ getLocationText(pet.location) }}</text>
</view>
</view>
<view class="pet-personality">
<text
class="personality-trait"
v-for="trait in pet.personality.slice(0, 3)"
:key="trait"
>{{ trait }}</text>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" v-if="hasMorePets && !refreshing">
<view class="loading-indicator" v-if="loadingMore">
<text class="loading-text">加载中...</text>
</view>
<view class="load-more-tip" v-else>
<text class="tip-text">上拉加载更多</text>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="displayPets.length === 0 && !loadingMore && !refreshing">
<text class="empty-icon">🐾</text>
<text class="empty-title">{{ getEmptyTitle() }}</text>
<text class="empty-subtitle">{{ getEmptySubtitle() }}</text>
<view class="empty-action" @click="resetFilters">
<text class="action-text">重新搜索</text>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
// 宠物领养数据管理工具类 - 从 utils/adoptionManager.js 移入
class AdoptionManager {
constructor() {
this.storageKey = 'adoption_pets'
// 宠物类型配置
this.petTypes = {
cat: {
name: '猫咪',
icon: '🐱',
breeds: {
'british-shorthair': '英国短毛猫',
'american-shorthair': '美国短毛猫',
'persian': '波斯猫',
'ragdoll': '布偶猫',
'siamese': '暹罗猫',
'maine-coon': '缅因猫',
'scottish-fold': '苏格兰折耳猫',
'russian-blue': '俄罗斯蓝猫',
'bengal': '孟加拉猫',
'mixed': '混血猫',
'unknown': '品种不明'
}
},
dog: {
name: '狗狗',
icon: '🐶',
breeds: {
'golden-retriever': '金毛寻回犬',
'labrador': '拉布拉多',
'husky': '哈士奇',
'german-shepherd': '德国牧羊犬',
'poodle': '贵宾犬',
'chihuahua': '吉娃娃',
'bulldog': '斗牛犬',
'shiba-inu': '柴犬',
'corgi': '柯基',
'border-collie': '边境牧羊犬',
'mixed': '混血犬',
'unknown': '品种不明'
}
},
rabbit: {
name: '兔子',
icon: '🐰',
breeds: {
'holland-lop': '荷兰垂耳兔',
'mini-lop': '迷你垂耳兔',
'lionhead': '狮子头兔',
'dutch': '荷兰兔',
'angora': '安哥拉兔',
'mixed': '混血兔',
'unknown': '品种不明'
}
},
other: {
name: '其他',
icon: '🐾',
breeds: {
'hamster': '仓鼠',
'guinea-pig': '豚鼠',
'bird': '鸟类',
'turtle': '乌龟',
'fish': '鱼类',
'other': '其他'
}
}
}
// 地区数据(简化版三级联动)
this.regions = {
'beijing': {
name: '北京市',
cities: {
'beijing': {
name: '北京市',
districts: {
'chaoyang': '朝阳区',
'haidian': '海淀区',
'dongcheng': '东城区',
'xicheng': '西城区',
'fengtai': '丰台区',
'shijingshan': '石景山区'
}
}
}
},
'shanghai': {
name: '上海市',
cities: {
'shanghai': {
name: '上海市',
districts: {
'huangpu': '黄浦区',
'xuhui': '徐汇区',
'changning': '长宁区',
'jingan': '静安区',
'putuo': '普陀区',
'hongkou': '虹口区'
}
}
}
},
'guangdong': {
name: '广东省',
cities: {
'guangzhou': {
name: '广州市',
districts: {
'tianhe': '天河区',
'yuexiu': '越秀区',
'liwan': '荔湾区',
'haizhu': '海珠区',
'baiyun': '白云区',
'panyu': '番禺区'
}
},
'shenzhen': {
name: '深圳市',
districts: {
'futian': '福田区',
'luohu': '罗湖区',
'nanshan': '南山区',
'yantian': '盐田区',
'baoan': '宝安区',
'longgang': '龙岗区'
}
}
}
},
'jiangsu': {
name: '江苏省',
cities: {
'nanjing': {
name: '南京市',
districts: {
'xuanwu': '玄武区',
'qinhuai': '秦淮区',
'jianye': '建邺区',
'gulou': '鼓楼区',
'pukou': '浦口区',
'qixia': '栖霞区'
}
},
'suzhou': {
name: '苏州市',
districts: {
'gusu': '姑苏区',
'wuzhong': '吴中区',
'xiangcheng': '相城区',
'kunshan': '昆山市',
'changshu': '常熟市',
'zhangjiagang': '张家港市'
}
}
}
}
}
// 领养状态
this.adoptionStatus = {
available: { name: '可领养', color: '#4CAF50', icon: '✅' },
reserved: { name: '已预约', color: '#FF9800', icon: '⏰' },
adopted: { name: '已领养', color: '#9E9E9E', icon: '❤️' },
pending: { name: '审核中', color: '#2196F3', icon: '📋' }
}
}
// 获取所有领养宠物数据
getAdoptionPets() {
try {
let pets = uni.getStorageSync(this.storageKey) || []
// 如果没有数据,初始化一些测试数据
if (pets.length === 0) {
pets = this.initializeTestData()
uni.setStorageSync(this.storageKey, pets)
}
return pets
} catch (error) {
console.error('获取领养宠物数据失败:', error)
return this.initializeTestData()
}
}
// 初始化测试数据
initializeTestData() {
const testData = []
// 猫咪数据
testData.push({
id: Date.now() + 1,
name: '小橘',
type: 'cat',
breed: 'british-shorthair',
age: 2,
gender: 'male',
photos: ['https://images.unsplash.com/photo-1574158622682-e40e69881006?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1592194996308-7b43878e84a6?w=400&h=300&fit=crop'],
description: '小橘是一只非常温顺的英国短毛猫,性格亲人,喜欢和人互动。已经完成绝育手术和疫苗接种,身体健康。适合有爱心的家庭领养,希望能给它一个温暖的家。',
personality: ['温顺', '亲人', '安静', '乖巧'],
health: '健康良好,已绝育,疫苗齐全',
location: {
province: 'beijing',
city: 'beijing',
district: 'chaoyang',
address: '朝阳区宠物救助中心'
},
status: 'available',
requirements: [
'有稳定收入',
'有养猫经验',
'家中无其他宠物',
'同意定期回访'
],
contact: {
name: '北京爱心救助站',
phone: '138****1234',
wechat: 'rescue_station_bj',
type: 'organization'
},
publishTime: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString()
})
// 狗狗数据
testData.push({
id: Date.now() + 2,
name: '小金',
type: 'dog',
breed: 'golden-retriever',
age: 1,
gender: 'female',
photos: ['https://images.unsplash.com/photo-1552053831-71594a27632d?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1583337130417-3346a1be7dee?w=400&h=300&fit=crop'],
description: '小金是一只活泼可爱的金毛幼犬,性格温顺友善,非常聪明。喜欢和小朋友玩耍,是很好的家庭伴侣犬。已完成基础疫苗接种。',
personality: ['活泼', '友善', '聪明', '温顺'],
health: '健康良好,疫苗已接种',
location: {
province: 'shanghai',
city: 'shanghai',
district: 'huangpu',
address: '黄浦区宠物收容所'
},
status: 'available',
requirements: [
'有养狗经验',
'有足够活动空间',
'能定期遛狗',
'同意绝育手术'
],
contact: {
name: '上海宠物救助中心',
phone: '139****5678',
wechat: 'sh_pet_rescue',
type: 'organization'
},
publishTime: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString()
})
// 猫咪数据2
testData.push({
id: Date.now() + 3,
name: '小白',
type: 'cat',
breed: 'ragdoll',
age: 3,
gender: 'female',
photos: ['https://images.unsplash.com/photo-1596854407944-bf87f6fdd49e?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1548247416-ec66f4900b2e?w=400&h=300&fit=crop'],
description: '小白是一只美丽的布偶猫,性格非常温柔,喜欢被抱抱。毛发柔软,眼睛湛蓝,是典型的布偶猫特征。已绝育,疫苗齐全。',
personality: ['温柔', '安静', '粘人', '优雅'],
health: '健康良好,已绝育,疫苗齐全',
location: {
province: 'guangdong',
city: 'guangzhou',
district: 'tianhe',
address: '天河区动物保护协会'
},
status: 'available',
requirements: [
'有稳定收入',
'室内饲养',
'定期美容',
'同意回访'
],
contact: {
name: '广州动物保护协会',
phone: '137****9012',
wechat: 'gz_animal_care',
type: 'organization'
},
publishTime: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString()
})
// 狗狗数据2
testData.push({
id: Date.now() + 4,
name: '豆豆',
type: 'dog',
breed: 'corgi',
age: 2,
gender: 'male',
photos: ['https://images.unsplash.com/photo-1518717758536-85ae29035b6d?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1583337130417-3346a1be7dee?w=400&h=300&fit=crop'],
description: '豆豆是一只可爱的柯基犬,短腿大屁股,走路摇摆很萌。性格活泼开朗,喜欢和人互动,是很好的陪伴犬。已完成疫苗接种。',
personality: ['活泼', '开朗', '友好', '机灵'],
health: '健康良好,疫苗已接种',
location: {
province: 'jiangsu',
city: 'nanjing',
district: 'xuanwu',
address: '玄武区宠物救助站'
},
status: 'available',
requirements: [
'有养宠经验',
'能接受掉毛',
'定期运动',
'负责任的主人'
],
contact: {
name: '南京宠物救助站',
phone: '135****3456',
wechat: 'nj_pet_help',
type: 'organization'
},
publishTime: new Date(Date.now() - 4 * 24 * 60 * 60 * 1000).toISOString()
})
// 猫咪数据3
testData.push({
id: Date.now() + 5,
name: '小黑',
type: 'cat',
breed: 'mixed',
age: 1,
gender: 'male',
photos: ['https://images.unsplash.com/photo-1513245543132-31f507417b26?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1571566882372-1598d88abd90?w=400&h=300&fit=crop'],
description: '小黑是一只可爱的小黑猫虽然是混血但非常健康活泼。刚刚1岁正是最可爱的年纪。性格独立但也很亲人适合各种家庭。',
personality: ['独立', '亲人', '活泼', '好奇'],
health: '健康良好,疫苗已接种',
location: {
province: 'beijing',
city: 'beijing',
district: 'haidian',
address: '海淀区流浪动物救助中心'
},
status: 'reserved',
requirements: [
'爱心家庭',
'室内饲养',
'定期体检',
'不离不弃'
],
contact: {
name: '海淀救助中心',
phone: '136****7890',
wechat: 'hd_animal_rescue',
type: 'organization'
},
publishTime: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString()
})
// 兔子数据
testData.push({
id: Date.now() + 6,
name: '雪球',
type: 'rabbit',
breed: 'holland-lop',
age: 1,
gender: 'female',
photos: ['https://images.unsplash.com/photo-1585110396000-c9ffd4e4b308?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1583337130417-3346a1be7dee?w=400&h=300&fit=crop'],
description: '雪球是一只可爱的荷兰垂耳兔,全身雪白,耳朵垂下来很萌。性格温顺,喜欢吃胡萝卜和青菜。适合安静的家庭饲养。',
personality: ['温顺', '安静', '可爱', '乖巧'],
health: '健康良好,已体检',
location: {
province: 'shanghai',
city: 'shanghai',
district: 'xuhui',
address: '徐汇区小动物保护基地'
},
status: 'available',
requirements: [
'了解兔子习性',
'提供合适笼舍',
'定期清理',
'耐心照料'
],
contact: {
name: '小动物保护基地',
phone: '138****2468',
wechat: 'small_animal_care',
type: 'organization'
},
publishTime: new Date(Date.now() - 6 * 24 * 60 * 60 * 1000).toISOString()
})
// 狗狗数据3
testData.push({
id: Date.now() + 7,
name: '大黄',
type: 'dog',
breed: 'mixed',
age: 4,
gender: 'male',
photos: ['https://images.unsplash.com/photo-1587300003388-59208cc962cb?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1583337130417-3346a1be7dee?w=400&h=300&fit=crop'],
description: '大黄是一只忠诚的中华田园犬,虽然年龄稍大但身体健康。性格稳重,对主人非常忠诚,是很好的看家犬和陪伴犬。',
personality: ['忠诚', '稳重', '护主', '温和'],
health: '健康良好,已绝育',
location: {
province: 'guangdong',
city: 'shenzhen',
district: 'futian',
address: '福田区流浪动物救助站'
},
status: 'available',
requirements: [
'有院子更佳',
'能接受中大型犬',
'有责任心',
'不嫌弃年龄'
],
contact: {
name: '深圳流浪动物救助站',
phone: '134****1357',
wechat: 'sz_stray_help',
type: 'organization'
},
publishTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()
})
// 猫咪数据4
testData.push({
id: Date.now() + 8,
name: '咪咪',
type: 'cat',
breed: 'siamese',
age: 2,
gender: 'female',
photos: ['https://images.unsplash.com/photo-1606214174585-fe31582dc6ee?w=400&h=300&fit=crop', 'https://images.unsplash.com/photo-1583337130417-3346a1be7dee?w=400&h=300&fit=crop'],
description: '咪咪是一只优雅的暹罗猫,有着美丽的蓝眼睛和独特的重点色毛发。性格活泼聪明,喜欢和人交流,会发出各种声音表达情感。',
personality: ['聪明', '活泼', '优雅', '善交流'],
health: '健康良好,已绝育,疫苗齐全',
location: {
province: 'jiangsu',
city: 'suzhou',
district: 'gusu',
address: '姑苏区宠物救助中心'
},
status: 'adopted',
requirements: [
'有养猫经验',
'能理解暹罗猫特性',
'室内饲养',
'定期互动'
],
contact: {
name: '苏州宠物救助中心',
phone: '132****8024',
wechat: 'sz_pet_center',
type: 'organization'
},
publishTime: new Date(Date.now() - 8 * 24 * 60 * 60 * 1000).toISOString()
})
return testData
}
// 搜索宠物
searchPets(keyword, pets = null) {
if (!pets) {
pets = this.getAdoptionPets()
}
if (!keyword) return pets
const lowerKeyword = keyword.toLowerCase()
return pets.filter(pet => {
return pet.name.toLowerCase().includes(lowerKeyword) ||
pet.description.toLowerCase().includes(lowerKeyword) ||
this.getPetTypeName(pet.type).includes(keyword) ||
this.getPetBreedName(pet.type, pet.breed).includes(keyword) ||
pet.personality.some(trait => trait.includes(keyword))
})
}
// 筛选宠物
filterPets(filters, pets = null) {
if (!pets) {
pets = this.getAdoptionPets()
}
return pets.filter(pet => {
// 宠物类型筛选
if (filters.type && pet.type !== filters.type) {
return false
}
// 品种筛选
if (filters.breed && pet.breed !== filters.breed) {
return false
}
// 地区筛选
if (filters.province && pet.location.province !== filters.province) {
return false
}
if (filters.city && pet.location.city !== filters.city) {
return false
}
if (filters.district && pet.location.district !== filters.district) {
return false
}
// 状态筛选
if (filters.status && pet.status !== filters.status) {
return false
}
// 性别筛选
if (filters.gender && pet.gender !== filters.gender) {
return false
}
// 年龄筛选
if (filters.ageRange) {
const [minAge, maxAge] = filters.ageRange
if (pet.age < minAge || pet.age > maxAge) {
return false
}
}
return true
})
}
// 获取宠物类型名称
getPetTypeName(type) {
return this.petTypes[type]?.name || '未知类型'
}
// 获取宠物品种名称
getPetBreedName(type, breed) {
return this.petTypes[type]?.breeds[breed] || '未知品种'
}
// 获取地区名称
getLocationName(province, city = null, district = null) {
let locationName = this.regions[province]?.name || province
if (city) {
const cityName = this.regions[province]?.cities[city]?.name
if (cityName) {
locationName += ' ' + cityName
}
}
if (district) {
const districtName = this.regions[province]?.cities[city]?.districts[district]
if (districtName) {
locationName += ' ' + districtName
}
}
return locationName
}
// 获取状态信息
getStatusInfo(status) {
return this.adoptionStatus[status] || {
name: '未知状态',
color: '#999999',
icon: '❓'
}
}
}
const adoptionManager = new AdoptionManager()
export default {
data() {
return {
// 搜索
searchKeyword: '',
// 筛选面板
showFilter: false,
// 地区筛选
selectedProvince: null,
selectedCity: null,
selectedDistrict: null,
selectedProvinceIndex: 0,
selectedCityIndex: 0,
selectedDistrictIndex: 0,
// 宠物类型筛选
selectedType: 'all',
selectedBreed: 'all',
// 其他筛选
selectedStatus: 'all',
selectedGender: 'all',
// 数据
allPets: [],
displayPets: [],
totalPets: 0,
// 分页
page: 1,
pageSize: 20,
hasMorePets: true,
loadingMore: false,
refreshing: false
}
},
computed: {
// 省份选项
provinceOptions() {
return Object.keys(adoptionManager.regions).map(key => ({
key: key,
name: adoptionManager.regions[key].name
}))
},
// 城市选项
cityOptions() {
if (!this.selectedProvince) return []
const cities = adoptionManager.regions[this.selectedProvince.key]?.cities || {}
return Object.keys(cities).map(key => ({
key: key,
name: cities[key].name
}))
},
// 区县选项
districtOptions() {
if (!this.selectedProvince || !this.selectedCity) return []
const districts = adoptionManager.regions[this.selectedProvince.key]?.cities[this.selectedCity.key]?.districts || {}
return Object.keys(districts).map(key => ({
key: key,
name: districts[key]
}))
},
// 宠物类型选项
petTypeOptions() {
return Object.keys(adoptionManager.petTypes).map(key => ({
key: key,
name: adoptionManager.petTypes[key].name,
icon: adoptionManager.petTypes[key].icon
}))
},
// 品种选项
breedOptions() {
if (this.selectedType === 'all') return []
const breeds = adoptionManager.petTypes[this.selectedType]?.breeds || {}
return Object.keys(breeds).map(key => ({
key: key,
name: breeds[key]
}))
}
},
onLoad() {
this.loadPets()
},
methods: {
loadPets() {
console.log('loadPets called')
// 强制清除本地存储,重新初始化数据
uni.removeStorageSync('adoption_pets')
this.allPets = adoptionManager.getAdoptionPets()
console.log('allPets loaded:', this.allPets.length, this.allPets)
this.applyFiltersAndSearch()
},
applyFiltersAndSearch() {
console.log('applyFiltersAndSearch called, allPets:', this.allPets.length)
let filteredPets = [...this.allPets]
// 应用搜索
if (this.searchKeyword) {
console.log('applying search:', this.searchKeyword)
filteredPets = adoptionManager.searchPets(this.searchKeyword, filteredPets)
}
// 应用筛选
const filters = this.buildFilters()
console.log('applying filters:', filters)
filteredPets = adoptionManager.filterPets(filters, filteredPets)
console.log('filtered pets:', filteredPets.length)
// 排序(按发布时间倒序)
filteredPets.sort((a, b) => new Date(b.publishTime) - new Date(a.publishTime))
this.totalPets = filteredPets.length
this.displayPets = filteredPets.slice(0, this.page * this.pageSize)
this.hasMorePets = filteredPets.length > this.displayPets.length
console.log('final displayPets:', this.displayPets.length)
},
buildFilters() {
const filters = {}
if (this.selectedType !== 'all') {
filters.type = this.selectedType
}
if (this.selectedBreed !== 'all') {
filters.breed = this.selectedBreed
}
if (this.selectedProvince) {
filters.province = this.selectedProvince.key
}
if (this.selectedCity) {
filters.city = this.selectedCity.key
}
if (this.selectedDistrict) {
filters.district = this.selectedDistrict.key
}
if (this.selectedStatus !== 'all') {
filters.status = this.selectedStatus
}
if (this.selectedGender !== 'all') {
filters.gender = this.selectedGender
}
return filters
},
// 搜索功能
onSearchInput() {
// 实时搜索
this.page = 1
this.applyFiltersAndSearch()
},
performSearch() {
this.page = 1
this.applyFiltersAndSearch()
},
clearSearch() {
this.searchKeyword = ''
this.page = 1
this.applyFiltersAndSearch()
},
// 筛选面板
toggleFilter() {
console.log('toggleFilter clicked, current showFilter:', this.showFilter)
this.showFilter = !this.showFilter
console.log('toggleFilter after, new showFilter:', this.showFilter)
},
// 地区筛选
onProvinceChange(e) {
const index = e.detail.value
this.selectedProvinceIndex = index
this.selectedProvince = this.provinceOptions[index]
this.selectedCity = null
this.selectedDistrict = null
this.selectedCityIndex = 0
this.selectedDistrictIndex = 0
},
onCityChange(e) {
const index = e.detail.value
this.selectedCityIndex = index
this.selectedCity = this.cityOptions[index]
this.selectedDistrict = null
this.selectedDistrictIndex = 0
},
onDistrictChange(e) {
const index = e.detail.value
this.selectedDistrictIndex = index
this.selectedDistrict = this.districtOptions[index]
},
// 宠物类型筛选
selectType(type) {
this.selectedType = type
this.selectedBreed = 'all'
},
selectBreed(breed) {
this.selectedBreed = breed
},
// 其他筛选
selectStatus(status) {
this.selectedStatus = status
},
selectGender(gender) {
this.selectedGender = gender
},
// 筛选操作
resetFilters() {
this.selectedProvince = null
this.selectedCity = null
this.selectedDistrict = null
this.selectedProvinceIndex = 0
this.selectedCityIndex = 0
this.selectedDistrictIndex = 0
this.selectedType = 'all'
this.selectedBreed = 'all'
this.selectedStatus = 'all'
this.selectedGender = 'all'
this.searchKeyword = ''
this.page = 1
this.applyFiltersAndSearch()
},
applyFilters() {
this.showFilter = false
this.page = 1
this.applyFiltersAndSearch()
},
// 分页和刷新
loadMorePets() {
if (this.hasMorePets && !this.loadingMore) {
this.loadingMore = true
setTimeout(() => {
this.page += 1
this.applyFiltersAndSearch()
this.loadingMore = false
}, 500)
}
},
onRefresh() {
this.refreshing = true
setTimeout(() => {
this.loadPets()
this.refreshing = false
}, 1000)
},
// 工具方法
getPetTypeName(type) {
return adoptionManager.getPetTypeName(type)
},
getPetBreedName(type, breed) {
return adoptionManager.getPetBreedName(type, breed)
},
getLocationText(location) {
return adoptionManager.getLocationName(location.province, location.city, location.district)
},
getStatusIcon(status) {
return adoptionManager.getStatusInfo(status).icon
},
getStatusText(status) {
return adoptionManager.getStatusInfo(status).name
},
getEmptyTitle() {
if (this.searchKeyword) {
return '没有找到相关宠物'
} else {
return '暂无宠物信息'
}
},
getEmptySubtitle() {
if (this.searchKeyword) {
return '试试其他关键词或调整筛选条件'
} else {
return '请稍后再来看看,或者联系我们添加更多宠物信息'
}
},
// 页面跳转
viewPetDetail(pet) {
uni.navigateTo({
url: `/pages/adoption/adoption-detail?petId=${pet.id}`
})
}
}
}
</script>
<style lang="scss" scoped>
.adoption-container {
overflow-x: hidden;
width: 100vw;
}
/* 头部搜索栏 */
.header-section {
background: transparent;
padding: 24rpx 20rpx;
.search-wrapper {
display: flex;
align-items: center;
gap: 16rpx;
.search-input-container {
flex: 1;
position: relative;
background: rgba(255, 255, 255, 0.95);
border: 2rpx solid rgba(255, 255, 255, 0.8);
border-radius: 24rpx;
padding: 0 20rpx;
display: flex;
align-items: center;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
.search-icon {
font-size: 24rpx;
margin-right: 12rpx;
color: #666;
}
.search-input {
flex: 1;
height: 72rpx;
font-size: 24rpx;
color: #333;
background: transparent;
border: none;
outline: none;
&::placeholder {
color: #999;
}
}
.search-clear {
width: 32rpx;
height: 32rpx;
background: rgba(0, 0, 0, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-left: 12rpx;
transition: all 0.3s ease;
&:active {
background: rgba(0, 0, 0, 0.2);
}
.clear-icon {
font-size: 16rpx;
color: #666;
}
}
}
.filter-btn {
display: flex;
align-items: center;
gap: 8rpx;
background: rgba(255, 255, 255, 0.95);
border: 2rpx solid rgba(255, 255, 255, 0.8);
border-radius: 16rpx;
padding: 16rpx 20rpx;
transition: all 0.3s ease;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
&:active {
transform: scale(0.95);
background: rgba(255, 255, 255, 0.8);
border-color: rgba(255, 255, 255, 0.9);
}
.filter-icon {
font-size: 20rpx;
color: #666;
}
.filter-text {
font-size: 22rpx;
color: #666;
font-weight: 500;
}
}
}
}
/* 筛选面板 */
.filter-panel {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20rpx);
padding: 24rpx 20rpx;
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
position: relative;
z-index: 10;
width: 100%;
box-sizing: border-box;
.filter-section {
margin-bottom: 32rpx;
&:last-child {
margin-bottom: 0;
}
.filter-title {
margin-bottom: 16rpx;
.title-text {
font-size: 26rpx;
font-weight: bold;
color: #333333;
}
}
}
/* 地区选择器 */
.region-selectors {
display: flex;
gap: 12rpx;
.region-selector {
flex: 1;
.selector-display {
background: rgba(255, 138, 128, 0.05);
border-radius: 12rpx;
padding: 16rpx;
display: flex;
justify-content: space-between;
align-items: center;
.selector-text {
font-size: 22rpx;
color: #666666;
}
.selector-arrow {
font-size: 16rpx;
color: #999999;
}
}
}
}
/* 宠物类型筛选 */
.type-filters {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
.type-filter {
display: flex;
align-items: center;
gap: 8rpx;
background: rgba(255, 138, 128, 0.05);
border-radius: 16rpx;
padding: 12rpx 20rpx;
transition: all 0.3s ease;
&.active {
background: #FF8A80;
.type-text {
color: white;
}
.type-icon {
color: white;
}
}
&:active {
transform: scale(0.95);
}
.type-icon {
font-size: 20rpx;
}
.type-text {
font-size: 22rpx;
color: #666666;
font-weight: 500;
}
}
}
/* 品种筛选 */
.breed-filters {
display: flex;
flex-wrap: wrap;
gap: 8rpx;
.breed-filter {
background: rgba(255, 138, 128, 0.05);
border-radius: 12rpx;
padding: 8rpx 16rpx;
transition: all 0.3s ease;
&.active {
background: rgba(255, 138, 128, 0.2);
.breed-text {
color: #FF8A80;
font-weight: bold;
}
}
&:active {
transform: scale(0.95);
}
.breed-text {
font-size: 20rpx;
color: #666666;
}
}
}
/* 其他筛选 */
.other-filters {
.filter-row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
.filter-label {
font-size: 22rpx;
color: #666666;
min-width: 80rpx;
margin-right: 16rpx;
}
}
.status-filters,
.gender-filters {
display: flex;
gap: 8rpx;
.status-filter,
.gender-filter {
background: rgba(255, 138, 128, 0.05);
border-radius: 12rpx;
padding: 8rpx 16rpx;
transition: all 0.3s ease;
&.active {
background: rgba(255, 138, 128, 0.2);
.status-text,
.gender-text {
color: #FF8A80;
font-weight: bold;
}
}
&:active {
transform: scale(0.95);
}
.status-text,
.gender-text {
font-size: 20rpx;
color: #666666;
}
}
}
}
/* 筛选操作按钮 */
.filter-actions {
display: flex;
gap: 16rpx;
margin-top: 32rpx;
.filter-reset,
.filter-apply {
flex: 1;
text-align: center;
padding: 16rpx;
border-radius: 16rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
}
.filter-reset {
background: rgba(153, 153, 153, 0.1);
.reset-text {
font-size: 24rpx;
color: #666666;
font-weight: 500;
}
}
.filter-apply {
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
.apply-text {
font-size: 24rpx;
color: white;
font-weight: 500;
}
}
}
}
/* 宠物列表区域 */
.pets-scroll {
height: calc(100vh - 100rpx);
padding: 0 20rpx;
overflow-x: hidden;
width: 100%;
box-sizing: border-box;
}
.pets-list {
padding-bottom: 60rpx;
width: 100%;
box-sizing: border-box;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16rpx;
}
.result-summary {
text-align: center;
padding: 24rpx 0;
grid-column: 1 / -1;
.summary-text {
font-size: 24rpx;
color: #666666;
}
}
/* 宠物卡片 */
.pet-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20rpx);
border-radius: 12rpx;
padding: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(255, 138, 128, 0.08);
border: 1rpx solid rgba(255, 255, 255, 0.3);
transition: all 0.3s ease;
box-sizing: border-box;
&:active {
transform: scale(0.98);
box-shadow: 0 1rpx 6rpx rgba(255, 138, 128, 0.15);
}
.pet-image-container {
position: relative;
width: 100%;
height: 280rpx;
border-radius: 12rpx;
overflow: hidden;
margin-bottom: 12rpx;
.pet-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.pet-status {
position: absolute;
top: 16rpx;
left: 16rpx;
display: flex;
align-items: center;
gap: 6rpx;
background: rgba(0, 0, 0, 0.7);
border-radius: 12rpx;
padding: 8rpx 12rpx;
&.available {
background: rgba(76, 175, 80, 0.9);
}
&.reserved {
background: rgba(255, 152, 0, 0.9);
}
&.adopted {
background: rgba(158, 158, 158, 0.9);
}
.status-icon {
font-size: 16rpx;
}
.status-text {
font-size: 18rpx;
color: white;
font-weight: 500;
}
}
}
.pet-info {
.pet-basic {
margin-bottom: 8rpx;
.pet-name {
font-size: 30rpx;
font-weight: bold;
color: #333333;
margin-bottom: 6rpx;
display: block;
line-height: 1.2;
padding: 6rpx 0;
}
.pet-tags {
display: flex;
gap: 6rpx;
flex-wrap: wrap;
.pet-type,
.pet-breed {
background: rgba(255, 138, 128, 0.2);
border-radius: 8rpx;
padding: 2rpx 8rpx;
font-size: 18rpx;
color: #E57373;
font-weight: 500;
}
}
}
.pet-details {
display: flex;
gap: 16rpx;
margin-bottom: 8rpx;
flex-wrap: wrap;
.detail-item {
display: flex;
align-items: center;
gap: 4rpx;
.detail-icon {
font-size: 14rpx;
}
.detail-text {
font-size: 18rpx;
color: #666666;
}
}
}
.pet-personality {
display: flex;
gap: 6rpx;
flex-wrap: wrap;
margin-bottom: 8rpx;
.personality-trait {
background: rgba(100, 181, 246, 0.15);
border-radius: 8rpx;
padding: 2rpx 8rpx;
font-size: 18rpx;
color: #42A5F5;
font-weight: 500;
}
}
.pet-stats {
display: flex;
justify-content: flex-end;
align-items: center;
.contact-type {
display: flex;
align-items: center;
gap: 6rpx;
.contact-icon {
font-size: 16rpx;
}
.contact-text {
font-size: 18rpx;
color: #666666;
}
}
}
}
}
/* 加载更多和空状态 */
.load-more {
text-align: center;
padding: 40rpx 0;
grid-column: 1 / -1;
.loading-indicator {
.loading-text {
font-size: 24rpx;
color: #999999;
}
}
.load-more-tip {
.tip-text {
font-size: 24rpx;
color: #CCCCCC;
}
}
}
.empty-state {
text-align: center;
padding: 120rpx 40rpx;
grid-column: 1 / -1;
.empty-icon {
font-size: 120rpx;
margin-bottom: 32rpx;
display: block;
}
.empty-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
margin-bottom: 16rpx;
display: block;
}
.empty-subtitle {
font-size: 26rpx;
color: #999999;
margin-bottom: 40rpx;
display: block;
line-height: 1.5;
}
.empty-action {
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
border-radius: 20rpx;
padding: 16rpx 32rpx;
display: inline-block;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
.action-text {
font-size: 24rpx;
color: white;
font-weight: 500;
}
}
}
</style>