1121 lines
24 KiB
Vue
1121 lines
24 KiB
Vue
<template>
|
|
<view class="pet-records-container page-container-with-bg">
|
|
<!-- 头部操作栏 -->
|
|
<view class="header-section">
|
|
<view class="header-info">
|
|
<text class="pet-name">{{ petName }}的记录</text>
|
|
<text class="record-count">共{{ totalRecords }}条记录</text>
|
|
</view>
|
|
<view class="header-actions">
|
|
<view class="search-btn" @click="toggleSearch">
|
|
<text class="search-icon">🔍</text>
|
|
</view>
|
|
<view class="add-btn" @click="addRecord">
|
|
<text class="add-text">+ 添加</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 搜索栏 -->
|
|
<view class="search-section" v-if="showSearch">
|
|
<view class="search-input-wrapper">
|
|
<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>
|
|
|
|
<!-- 分类筛选栏 -->
|
|
<view class="filter-section">
|
|
<view class="primary-filters">
|
|
<view
|
|
class="filter-tab"
|
|
:class="{ active: activeCategory === 'all' }"
|
|
@click="switchCategory('all')"
|
|
>
|
|
<text class="tab-text">全部</text>
|
|
</view>
|
|
<view
|
|
class="filter-tab"
|
|
:class="{ active: activeCategory === category.key }"
|
|
v-for="category in primaryCategories"
|
|
:key="category.key"
|
|
@click="switchCategory(category.key)"
|
|
>
|
|
<text class="tab-icon">{{ category.icon }}</text>
|
|
<text class="tab-text">{{ category.name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 二级分类筛选 -->
|
|
<view class="secondary-filters" v-if="activeCategory !== 'all' && subCategories.length > 0">
|
|
<view
|
|
class="sub-filter-tab"
|
|
:class="{ active: activeSubCategory === 'all' }"
|
|
@click="switchSubCategory('all')"
|
|
>
|
|
<text class="sub-tab-text">全部</text>
|
|
</view>
|
|
<view
|
|
class="sub-filter-tab"
|
|
:class="{ active: activeSubCategory === subCategory.key }"
|
|
v-for="subCategory in subCategories"
|
|
:key="subCategory.key"
|
|
@click="switchSubCategory(subCategory.key)"
|
|
>
|
|
<text class="sub-tab-icon">{{ subCategory.icon }}</text>
|
|
<text class="sub-tab-text">{{ subCategory.name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 排序选择 -->
|
|
<view class="sort-section">
|
|
<view class="sort-options">
|
|
<view
|
|
class="sort-option"
|
|
:class="{ active: sortBy === 'time' }"
|
|
@click="changeSortBy('time')"
|
|
>
|
|
<text class="sort-text">按时间</text>
|
|
</view>
|
|
<view
|
|
class="sort-option"
|
|
:class="{ active: sortBy === 'category' }"
|
|
@click="changeSortBy('category')"
|
|
>
|
|
<text class="sort-text">按分类</text>
|
|
</view>
|
|
<view
|
|
class="sort-option"
|
|
:class="{ active: sortBy === 'popularity' }"
|
|
@click="changeSortBy('popularity')"
|
|
>
|
|
<text class="sort-text">按热度</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 记录列表 -->
|
|
<scroll-view
|
|
class="records-scroll"
|
|
scroll-y
|
|
@scrolltolower="loadMoreRecords"
|
|
@refresherrefresh="onRefresh"
|
|
:refresher-enabled="true"
|
|
:refresher-triggered="refreshing"
|
|
>
|
|
<view class="records-list">
|
|
<!-- 记录项 -->
|
|
<view
|
|
class="record-item"
|
|
v-for="record in displayRecords"
|
|
:key="record.id"
|
|
@click="viewRecordDetail(record)"
|
|
>
|
|
<view class="record-header">
|
|
<view class="record-category">
|
|
<text class="category-icon">{{ getCategoryIcon(record.category, record.subCategory) }}</text>
|
|
<text class="category-name">{{ getCategoryName(record.category, record.subCategory) }}</text>
|
|
</view>
|
|
<view class="record-time">
|
|
<text class="time-text">{{ formatTime(record.recordTime) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="record-content">
|
|
<text class="record-title">{{ record.title }}</text>
|
|
<text class="record-text">{{ record.content }}</text>
|
|
</view>
|
|
|
|
<!-- 标签 -->
|
|
<view class="record-tags" v-if="record.tags && record.tags.length > 0">
|
|
<view
|
|
class="tag-item"
|
|
v-for="tag in record.tags.slice(0, 3)"
|
|
:key="tag"
|
|
>
|
|
<text class="tag-text"># {{ tag }}</text>
|
|
</view>
|
|
<view class="more-tags" v-if="record.tags.length > 3">
|
|
<text class="more-text">+{{ record.tags.length - 3 }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 图片预览 -->
|
|
<view class="record-photos" v-if="record.photos && record.photos.length > 0">
|
|
<view
|
|
class="photo-item"
|
|
v-for="(photo, index) in record.photos.slice(0, 3)"
|
|
:key="index"
|
|
>
|
|
<image class="photo-image" :src="photo" mode="aspectFill" />
|
|
</view>
|
|
<view class="more-photos" v-if="record.photos.length > 3">
|
|
<text class="more-photos-text">+{{ record.photos.length - 3 }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 社交数据 -->
|
|
<view class="record-social">
|
|
<view class="social-item">
|
|
<text class="social-icon">👁️</text>
|
|
<text class="social-count">{{ getSocialData(record.id).views }}</text>
|
|
</view>
|
|
<view class="social-item">
|
|
<text class="social-icon">❤️</text>
|
|
<text class="social-count">{{ getSocialData(record.id).likes }}</text>
|
|
</view>
|
|
<view class="social-item">
|
|
<text class="social-icon">💬</text>
|
|
<text class="social-count">{{ getSocialData(record.id).comments.length }}</text>
|
|
</view>
|
|
<view class="share-level">
|
|
<text class="share-icon">{{ getShareIcon(record.shareLevel) }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 加载更多 -->
|
|
<view class="load-more" v-if="hasMoreRecords && !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="displayRecords.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="addRecord">
|
|
<text class="action-text">添加第一条记录</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<!-- 浮动添加按钮 -->
|
|
<view class="fab-button" @click="addRecord">
|
|
<text class="fab-icon">+</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
// 记录管理器 - 从 utils/recordManager.js 移入
|
|
const recordManager = {
|
|
storageKey: 'pet_records',
|
|
|
|
getRecords(petId) {
|
|
try {
|
|
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
|
let records = allRecords[petId] || []
|
|
|
|
if (records.length === 0) {
|
|
records = this.initializeTestData(petId)
|
|
allRecords[petId] = records
|
|
uni.setStorageSync(this.storageKey, allRecords)
|
|
}
|
|
|
|
return records.sort((a, b) => new Date(b.date) - new Date(a.date))
|
|
} catch (error) {
|
|
console.error('获取记录失败:', error)
|
|
return []
|
|
}
|
|
},
|
|
|
|
initializeTestData(petId) {
|
|
const now = new Date()
|
|
return [
|
|
{
|
|
id: Date.now() + 1,
|
|
petId: petId,
|
|
type: 'health',
|
|
title: '健康检查',
|
|
content: '定期健康检查,一切正常',
|
|
date: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
|
images: [],
|
|
createTime: new Date().toISOString()
|
|
},
|
|
{
|
|
id: Date.now() + 2,
|
|
petId: petId,
|
|
type: 'feeding',
|
|
title: '喂食记录',
|
|
content: '今天食欲很好,吃完了所有的猫粮',
|
|
date: new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
|
images: [],
|
|
createTime: new Date().toISOString()
|
|
}
|
|
]
|
|
},
|
|
|
|
addRecord(petId, recordData) {
|
|
try {
|
|
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
|
if (!allRecords[petId]) {
|
|
allRecords[petId] = []
|
|
}
|
|
|
|
const newRecord = {
|
|
id: Date.now(),
|
|
petId: petId,
|
|
...recordData,
|
|
createTime: new Date().toISOString()
|
|
}
|
|
|
|
allRecords[petId].push(newRecord)
|
|
uni.setStorageSync(this.storageKey, allRecords)
|
|
return true
|
|
} catch (error) {
|
|
console.error('添加记录失败:', error)
|
|
return false
|
|
}
|
|
},
|
|
|
|
deleteRecord(petId, recordId) {
|
|
try {
|
|
const allRecords = uni.getStorageSync(this.storageKey) || {}
|
|
if (allRecords[petId]) {
|
|
allRecords[petId] = allRecords[petId].filter(record => record.id !== recordId)
|
|
uni.setStorageSync(this.storageKey, allRecords)
|
|
}
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除记录失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
petId: '',
|
|
petName: '',
|
|
|
|
// 记录数据
|
|
allRecords: [],
|
|
displayRecords: [],
|
|
totalRecords: 0,
|
|
|
|
// 搜索功能
|
|
showSearch: false,
|
|
searchKeyword: '',
|
|
searchResults: [],
|
|
|
|
// 分类筛选
|
|
activeCategory: 'all',
|
|
activeSubCategory: 'all',
|
|
primaryCategories: [
|
|
{ key: 'health', name: '健康', icon: '🏥' },
|
|
{ key: 'care', name: '护理', icon: '🛁' },
|
|
{ key: 'behavior', name: '行为', icon: '🎾' },
|
|
{ key: 'daily', name: '日常', icon: '📝' },
|
|
{ key: 'expense', name: '消费', icon: '💰' }
|
|
],
|
|
subCategories: [],
|
|
|
|
// 排序
|
|
sortBy: 'time', // time, category, popularity
|
|
|
|
// 分页和加载
|
|
page: 1,
|
|
pageSize: 10,
|
|
hasMoreRecords: true,
|
|
loadingMore: false,
|
|
refreshing: false,
|
|
|
|
// 社交数据缓存
|
|
socialDataCache: {}
|
|
}
|
|
},
|
|
|
|
onLoad(options) {
|
|
this.petId = options.petId || ''
|
|
this.petName = options.petName || '宠物'
|
|
this.loadRecords()
|
|
},
|
|
|
|
methods: {
|
|
loadRecords() {
|
|
// 获取所有记录
|
|
this.allRecords = recordManager.getRecords(this.petId)
|
|
this.totalRecords = this.allRecords.length
|
|
|
|
// 初始化社交数据缓存
|
|
this.initSocialDataCache()
|
|
|
|
// 应用筛选和排序
|
|
this.applyFiltersAndSort()
|
|
},
|
|
|
|
initSocialDataCache() {
|
|
this.socialDataCache = {}
|
|
this.allRecords.forEach(record => {
|
|
this.socialDataCache[record.id] = recordManager.getSocialData(record.id)
|
|
})
|
|
},
|
|
|
|
applyFiltersAndSort() {
|
|
let filteredRecords = [...this.allRecords]
|
|
|
|
// 应用搜索筛选
|
|
if (this.searchKeyword) {
|
|
filteredRecords = recordManager.searchRecords(this.petId, this.searchKeyword)
|
|
}
|
|
|
|
// 应用分类筛选
|
|
if (this.activeCategory !== 'all') {
|
|
const subCategory = this.activeSubCategory !== 'all' ? this.activeSubCategory : null
|
|
filteredRecords = filteredRecords.filter(record => {
|
|
if (subCategory) {
|
|
return record.category === this.activeCategory && record.subCategory === subCategory
|
|
} else {
|
|
return record.category === this.activeCategory
|
|
}
|
|
})
|
|
}
|
|
|
|
// 应用排序
|
|
this.sortRecords(filteredRecords)
|
|
|
|
// 分页显示
|
|
this.displayRecords = filteredRecords.slice(0, this.page * this.pageSize)
|
|
this.hasMoreRecords = filteredRecords.length > this.displayRecords.length
|
|
},
|
|
|
|
sortRecords(records) {
|
|
switch (this.sortBy) {
|
|
case 'time':
|
|
records.sort((a, b) => new Date(b.recordTime) - new Date(a.recordTime))
|
|
break
|
|
case 'category':
|
|
records.sort((a, b) => {
|
|
if (a.category !== b.category) {
|
|
return a.category.localeCompare(b.category)
|
|
}
|
|
return new Date(b.recordTime) - new Date(a.recordTime)
|
|
})
|
|
break
|
|
case 'popularity':
|
|
records.sort((a, b) => {
|
|
const aPopularity = this.getSocialData(a.id).likes + this.getSocialData(a.id).views
|
|
const bPopularity = this.getSocialData(b.id).likes + this.getSocialData(b.id).views
|
|
return bPopularity - aPopularity
|
|
})
|
|
break
|
|
}
|
|
},
|
|
|
|
// 搜索功能
|
|
toggleSearch() {
|
|
this.showSearch = !this.showSearch
|
|
if (!this.showSearch) {
|
|
this.clearSearch()
|
|
}
|
|
},
|
|
|
|
onSearchInput() {
|
|
// 实时搜索
|
|
this.performSearch()
|
|
},
|
|
|
|
performSearch() {
|
|
this.page = 1
|
|
this.applyFiltersAndSort()
|
|
},
|
|
|
|
clearSearch() {
|
|
this.searchKeyword = ''
|
|
this.performSearch()
|
|
},
|
|
|
|
// 分类筛选
|
|
switchCategory(category) {
|
|
this.activeCategory = category
|
|
this.activeSubCategory = 'all'
|
|
this.page = 1
|
|
|
|
// 更新二级分类选项
|
|
this.updateSubCategories()
|
|
|
|
this.applyFiltersAndSort()
|
|
},
|
|
|
|
switchSubCategory(subCategory) {
|
|
this.activeSubCategory = subCategory
|
|
this.page = 1
|
|
this.applyFiltersAndSort()
|
|
},
|
|
|
|
updateSubCategories() {
|
|
if (this.activeCategory === 'all') {
|
|
this.subCategories = []
|
|
return
|
|
}
|
|
|
|
const categoryConfig = recordManager.categories[this.activeCategory]
|
|
if (categoryConfig && categoryConfig.subCategories) {
|
|
this.subCategories = Object.keys(categoryConfig.subCategories).map(key => ({
|
|
key: key,
|
|
name: categoryConfig.subCategories[key].name,
|
|
icon: categoryConfig.subCategories[key].icon
|
|
}))
|
|
} else {
|
|
this.subCategories = []
|
|
}
|
|
},
|
|
|
|
// 排序
|
|
changeSortBy(sortType) {
|
|
this.sortBy = sortType
|
|
this.page = 1
|
|
this.applyFiltersAndSort()
|
|
},
|
|
|
|
// 加载更多
|
|
loadMoreRecords() {
|
|
if (this.hasMoreRecords && !this.loadingMore) {
|
|
this.loadingMore = true
|
|
|
|
setTimeout(() => {
|
|
this.page += 1
|
|
this.applyFiltersAndSort()
|
|
this.loadingMore = false
|
|
}, 500)
|
|
}
|
|
},
|
|
|
|
// 下拉刷新
|
|
onRefresh() {
|
|
this.refreshing = true
|
|
|
|
setTimeout(() => {
|
|
this.loadRecords()
|
|
this.refreshing = false
|
|
}, 1000)
|
|
},
|
|
|
|
// 获取分类信息
|
|
getCategoryIcon(category, subCategory = null) {
|
|
const categoryInfo = recordManager.getCategoryInfo(category, subCategory)
|
|
return categoryInfo.icon
|
|
},
|
|
|
|
getCategoryName(category, subCategory = null) {
|
|
const categoryInfo = recordManager.getCategoryInfo(category, subCategory)
|
|
return categoryInfo.name
|
|
},
|
|
|
|
getCategoryColor(category) {
|
|
const categoryInfo = recordManager.getCategoryInfo(category)
|
|
return categoryInfo.color
|
|
},
|
|
|
|
// 获取社交数据
|
|
getSocialData(recordId) {
|
|
return this.socialDataCache[recordId] || {
|
|
likes: 0,
|
|
views: 0,
|
|
comments: []
|
|
}
|
|
},
|
|
|
|
// 分享级别图标
|
|
getShareIcon(shareLevel) {
|
|
const icons = {
|
|
'public': '🌍',
|
|
'family': '👨👩👧👦',
|
|
'private': '🔒'
|
|
}
|
|
return icons[shareLevel] || '👨👩👧👦'
|
|
},
|
|
|
|
// 时间格式化
|
|
formatTime(timeStr) {
|
|
if (!timeStr) return ''
|
|
|
|
const time = new Date(timeStr)
|
|
const now = new Date()
|
|
const diff = now - time
|
|
|
|
const minutes = Math.floor(diff / (1000 * 60))
|
|
const hours = Math.floor(diff / (1000 * 60 * 60))
|
|
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
|
|
|
|
if (minutes < 60) {
|
|
return minutes <= 0 ? '刚刚' : `${minutes}分钟前`
|
|
} else if (hours < 24) {
|
|
return `${hours}小时前`
|
|
} else if (days < 7) {
|
|
return `${days}天前`
|
|
} else {
|
|
return `${time.getMonth() + 1}-${time.getDate()}`
|
|
}
|
|
},
|
|
|
|
// 空状态文案
|
|
getEmptyTitle() {
|
|
if (this.searchKeyword) {
|
|
return '没有找到相关记录'
|
|
} else if (this.activeCategory !== 'all') {
|
|
const categoryName = this.getCategoryName(this.activeCategory)
|
|
return `暂无${categoryName}记录`
|
|
} else {
|
|
return '还没有记录哦'
|
|
}
|
|
},
|
|
|
|
getEmptySubtitle() {
|
|
if (this.searchKeyword) {
|
|
return '试试其他关键词或清空搜索条件'
|
|
} else {
|
|
return '记录宠物的美好时光,从第一条开始'
|
|
}
|
|
},
|
|
|
|
// 页面跳转
|
|
viewRecordDetail(record) {
|
|
// 增加浏览量
|
|
recordManager.incrementViews(record.id)
|
|
this.socialDataCache[record.id].views += 1
|
|
|
|
uni.navigateTo({
|
|
url: `/pages/pets/record-detail?recordId=${record.id}&petId=${this.petId}&petName=${this.petName}`
|
|
})
|
|
},
|
|
|
|
addRecord() {
|
|
uni.navigateTo({
|
|
url: `/pages/pets/select-record-type?petId=${this.petId}&petName=${this.petName}`
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.pet-records-container {
|
|
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
|
|
/* 头部区域 */
|
|
.header-section {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
padding: 32rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
.header-info {
|
|
.pet-name {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
display: block;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.record-count {
|
|
font-size: 22rpx;
|
|
color: #999999;
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
|
|
.search-btn {
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
background: rgba(255, 138, 128, 0.1);
|
|
border-radius: 16rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.3s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
background: rgba(255, 138, 128, 0.2);
|
|
}
|
|
|
|
.search-icon {
|
|
font-size: 24rpx;
|
|
}
|
|
}
|
|
|
|
.add-btn {
|
|
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
|
|
border-radius: 16rpx;
|
|
padding: 16rpx 24rpx;
|
|
transition: all 0.3s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.add-text {
|
|
font-size: 24rpx;
|
|
color: white;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 搜索区域 */
|
|
.search-section {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
padding: 0 32rpx 24rpx 32rpx;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
.search-input-wrapper {
|
|
position: relative;
|
|
background: rgba(255, 138, 128, 0.05);
|
|
border-radius: 20rpx;
|
|
padding: 0 20rpx;
|
|
|
|
.search-input {
|
|
width: 100%;
|
|
height: 72rpx;
|
|
font-size: 24rpx;
|
|
color: #333333;
|
|
background: transparent;
|
|
border: none;
|
|
outline: none;
|
|
}
|
|
|
|
.search-clear {
|
|
position: absolute;
|
|
right: 20rpx;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
background: #CCCCCC;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.clear-icon {
|
|
font-size: 16rpx;
|
|
color: white;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 筛选区域 */
|
|
.filter-section {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
padding: 24rpx 32rpx;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
.primary-filters {
|
|
display: flex;
|
|
gap: 12rpx;
|
|
margin-bottom: 20rpx;
|
|
overflow-x: auto;
|
|
|
|
.filter-tab {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
padding: 12rpx 20rpx;
|
|
border-radius: 20rpx;
|
|
background: rgba(255, 138, 128, 0.1);
|
|
transition: all 0.3s ease;
|
|
|
|
&.active {
|
|
background: #FF8A80;
|
|
|
|
.tab-text {
|
|
color: white;
|
|
}
|
|
|
|
.tab-icon {
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.tab-icon {
|
|
font-size: 20rpx;
|
|
}
|
|
|
|
.tab-text {
|
|
font-size: 22rpx;
|
|
font-weight: 500;
|
|
color: #666666;
|
|
}
|
|
}
|
|
}
|
|
|
|
.secondary-filters {
|
|
display: flex;
|
|
gap: 8rpx;
|
|
overflow-x: auto;
|
|
|
|
.sub-filter-tab {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6rpx;
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 16rpx;
|
|
background: rgba(255, 138, 128, 0.05);
|
|
transition: all 0.3s ease;
|
|
|
|
&.active {
|
|
background: rgba(255, 138, 128, 0.2);
|
|
|
|
.sub-tab-text {
|
|
color: #FF8A80;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.sub-tab-icon {
|
|
font-size: 16rpx;
|
|
}
|
|
|
|
.sub-tab-text {
|
|
font-size: 20rpx;
|
|
color: #666666;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 排序区域 */
|
|
.sort-section {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
padding: 16rpx 32rpx;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
.sort-options {
|
|
display: flex;
|
|
gap: 24rpx;
|
|
|
|
.sort-option {
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 12rpx;
|
|
background: rgba(255, 138, 128, 0.05);
|
|
transition: all 0.3s ease;
|
|
|
|
&.active {
|
|
background: rgba(255, 138, 128, 0.2);
|
|
|
|
.sort-text {
|
|
color: #FF8A80;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.sort-text {
|
|
font-size: 20rpx;
|
|
color: #666666;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 记录列表区域 */
|
|
.records-scroll {
|
|
height: calc(100vh - 400rpx);
|
|
padding: 0 20rpx;
|
|
}
|
|
|
|
.records-list {
|
|
padding-bottom: 120rpx;
|
|
}
|
|
|
|
.record-item {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
border-radius: 20rpx;
|
|
padding: 24rpx;
|
|
margin-bottom: 16rpx;
|
|
box-shadow: 0 4rpx 16rpx rgba(255, 138, 128, 0.1);
|
|
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
transition: all 0.3s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.98);
|
|
box-shadow: 0 2rpx 8rpx rgba(255, 138, 128, 0.2);
|
|
}
|
|
|
|
.record-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 16rpx;
|
|
|
|
.record-category {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
|
|
.category-icon {
|
|
font-size: 20rpx;
|
|
}
|
|
|
|
.category-name {
|
|
font-size: 22rpx;
|
|
font-weight: 500;
|
|
color: #666666;
|
|
}
|
|
}
|
|
|
|
.record-time {
|
|
.time-text {
|
|
font-size: 20rpx;
|
|
color: #999999;
|
|
}
|
|
}
|
|
}
|
|
|
|
.record-content {
|
|
margin-bottom: 16rpx;
|
|
|
|
.record-title {
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
color: #333333;
|
|
margin-bottom: 8rpx;
|
|
display: block;
|
|
}
|
|
|
|
.record-text {
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
line-height: 1.6;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 3;
|
|
overflow: hidden;
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.record-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8rpx;
|
|
margin-bottom: 16rpx;
|
|
|
|
.tag-item {
|
|
background: rgba(255, 138, 128, 0.1);
|
|
border-radius: 12rpx;
|
|
padding: 4rpx 12rpx;
|
|
|
|
.tag-text {
|
|
font-size: 18rpx;
|
|
color: #FF8A80;
|
|
}
|
|
}
|
|
|
|
.more-tags {
|
|
background: rgba(153, 153, 153, 0.1);
|
|
border-radius: 12rpx;
|
|
padding: 4rpx 12rpx;
|
|
|
|
.more-text {
|
|
font-size: 18rpx;
|
|
color: #999999;
|
|
}
|
|
}
|
|
}
|
|
|
|
.record-photos {
|
|
display: flex;
|
|
gap: 8rpx;
|
|
margin-bottom: 16rpx;
|
|
|
|
.photo-item {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
border-radius: 12rpx;
|
|
overflow: hidden;
|
|
|
|
.photo-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.more-photos {
|
|
width: 120rpx;
|
|
height: 120rpx;
|
|
background: rgba(0, 0, 0, 0.1);
|
|
border-radius: 12rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.more-photos-text {
|
|
font-size: 20rpx;
|
|
color: #666666;
|
|
}
|
|
}
|
|
}
|
|
|
|
.record-social {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.social-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6rpx;
|
|
|
|
.social-icon {
|
|
font-size: 16rpx;
|
|
}
|
|
|
|
.social-count {
|
|
font-size: 18rpx;
|
|
color: #999999;
|
|
}
|
|
}
|
|
|
|
.share-level {
|
|
.share-icon {
|
|
font-size: 16rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 加载更多和空状态 */
|
|
.load-more {
|
|
text-align: center;
|
|
padding: 40rpx 0;
|
|
|
|
.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;
|
|
|
|
.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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 浮动添加按钮 */
|
|
.fab-button {
|
|
position: fixed;
|
|
bottom: 120rpx;
|
|
right: 40rpx;
|
|
width: 112rpx;
|
|
height: 112rpx;
|
|
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 8rpx 24rpx rgba(255, 138, 128, 0.3);
|
|
z-index: 999;
|
|
transition: all 0.3s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.9);
|
|
}
|
|
|
|
.fab-icon {
|
|
font-size: 40rpx;
|
|
color: white;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
|