1013 lines
22 KiB
Vue
1013 lines
22 KiB
Vue
<template>
|
||
<view class="reminders-container page-container-with-bg">
|
||
<!-- 统计概览卡片 -->
|
||
<view class="stats-card">
|
||
<view class="stats-grid">
|
||
<view class="stat-item">
|
||
<view class="stat-number">{{ pendingCount }}</view>
|
||
<view class="stat-label">待处理</view>
|
||
<view class="stat-icon">⏰</view>
|
||
</view>
|
||
<view class="stat-item">
|
||
<view class="stat-number">{{ todayCount }}</view>
|
||
<view class="stat-label">今日</view>
|
||
<view class="stat-icon">📅</view>
|
||
</view>
|
||
<view class="stat-item">
|
||
<view class="stat-number">{{ completedCount }}</view>
|
||
<view class="stat-label">已完成</view>
|
||
<view class="stat-icon">✅</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 筛选标签 -->
|
||
<view class="filter-tabs">
|
||
<view
|
||
class="filter-tab"
|
||
:class="{ active: currentFilter === 'all' }"
|
||
@click="setFilter('all')"
|
||
>
|
||
<text class="tab-text">全部</text>
|
||
</view>
|
||
<view
|
||
class="filter-tab"
|
||
:class="{ active: currentFilter === 'pending' }"
|
||
@click="setFilter('pending')"
|
||
>
|
||
<text class="tab-text">待处理</text>
|
||
</view>
|
||
<view
|
||
class="filter-tab"
|
||
:class="{ active: currentFilter === 'today' }"
|
||
@click="setFilter('today')"
|
||
>
|
||
<text class="tab-text">今日</text>
|
||
</view>
|
||
<view
|
||
class="filter-tab"
|
||
:class="{ active: currentFilter === 'completed' }"
|
||
@click="setFilter('completed')"
|
||
>
|
||
<text class="tab-text">已完成</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提醒列表 -->
|
||
<view class="reminders-list" v-if="filteredReminders.length > 0">
|
||
<view
|
||
class="reminder-item"
|
||
v-for="reminder in filteredReminders"
|
||
:key="reminder.id"
|
||
:class="{ completed: reminder.completed, overdue: isOverdue(reminder) }"
|
||
@click="viewReminderDetail(reminder)"
|
||
>
|
||
<view class="reminder-checkbox" @click.stop="toggleReminder(reminder)">
|
||
<view class="checkbox" :class="{ checked: reminder.completed }">
|
||
<text class="check-icon" v-if="reminder.completed">✓</text>
|
||
</view>
|
||
</view>
|
||
<view class="reminder-content">
|
||
<view class="reminder-title">{{ reminder.title }}</view>
|
||
<view class="reminder-meta">
|
||
<view class="reminder-time">
|
||
<text class="time-icon">🕐</text>
|
||
<text class="time-text">{{ formatDateTime(reminder.datetime) }}</text>
|
||
</view>
|
||
<view class="reminder-pet" v-if="reminder.petName">
|
||
<text class="pet-icon">🐱</text>
|
||
<text class="pet-text">{{ reminder.petName }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="reminder-desc" v-if="reminder.description">
|
||
{{ reminder.description }}
|
||
</view>
|
||
</view>
|
||
<view class="reminder-actions">
|
||
<view class="reminder-priority" :class="reminder.priority">
|
||
<text class="priority-dot"></text>
|
||
</view>
|
||
<view class="action-more" @click.stop="showReminderActions(reminder)">
|
||
<text class="more-icon">⋯</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view class="empty-state" v-else>
|
||
<view class="empty-icon">📝</view>
|
||
<view class="empty-text">{{ getEmptyText() }}</view>
|
||
<view class="empty-action" @click="addReminder" v-if="currentFilter === 'all'">
|
||
<text class="action-text">添加第一个提醒</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 添加按钮 -->
|
||
<view class="add-button" @click="addReminder">
|
||
<text class="add-icon">+</text>
|
||
</view>
|
||
|
||
<!-- 添加提醒弹窗 -->
|
||
<u-modal
|
||
:show="showAddModal"
|
||
title="添加提醒"
|
||
@confirm="confirmAddReminder"
|
||
@cancel="cancelAddReminder"
|
||
:show-cancel-button="true"
|
||
confirm-text="保存"
|
||
>
|
||
<view class="add-reminder-form">
|
||
<view class="form-item">
|
||
<text class="form-label">提醒标题</text>
|
||
<u-input
|
||
v-model="newReminder.title"
|
||
placeholder="请输入提醒标题"
|
||
border="none"
|
||
:custom-style="inputStyle"
|
||
></u-input>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">提醒时间</text>
|
||
<view class="datetime-picker" @click="showDatetimePicker">
|
||
<text class="datetime-text">{{ formatDateTime(newReminder.datetime) || '请选择时间' }}</text>
|
||
<text class="picker-arrow">→</text>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">关联宠物</text>
|
||
<view class="pet-picker" @click="showPetPicker">
|
||
<text class="pet-text">{{ newReminder.petName || '请选择宠物' }}</text>
|
||
<text class="picker-arrow">→</text>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">优先级</text>
|
||
<view class="priority-options">
|
||
<view
|
||
class="priority-option"
|
||
:class="{ active: newReminder.priority === 'high' }"
|
||
@click="setPriority('high')"
|
||
>
|
||
<view class="priority-dot high"></view>
|
||
<text class="priority-text">高</text>
|
||
</view>
|
||
<view
|
||
class="priority-option"
|
||
:class="{ active: newReminder.priority === 'medium' }"
|
||
@click="setPriority('medium')"
|
||
>
|
||
<view class="priority-dot medium"></view>
|
||
<text class="priority-text">中</text>
|
||
</view>
|
||
<view
|
||
class="priority-option"
|
||
:class="{ active: newReminder.priority === 'low' }"
|
||
@click="setPriority('low')"
|
||
>
|
||
<view class="priority-dot low"></view>
|
||
<text class="priority-text">低</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">备注说明</text>
|
||
<u-textarea
|
||
v-model="newReminder.description"
|
||
placeholder="添加备注说明(可选)"
|
||
:maxlength="100"
|
||
:custom-style="textareaStyle"
|
||
></u-textarea>
|
||
</view>
|
||
</view>
|
||
</u-modal>
|
||
|
||
<!-- 日期时间选择器 -->
|
||
<u-datetime-picker
|
||
:show="showDatetime"
|
||
v-model="selectedDatetime"
|
||
mode="datetime"
|
||
@confirm="onDatetimeConfirm"
|
||
@cancel="showDatetime = false"
|
||
></u-datetime-picker>
|
||
|
||
<!-- 宠物选择器 -->
|
||
<u-picker
|
||
:show="showPet"
|
||
:columns="petColumns"
|
||
@confirm="onPetConfirm"
|
||
@cancel="showPet = false"
|
||
></u-picker>
|
||
|
||
<!-- 操作菜单 -->
|
||
<u-action-sheet
|
||
:show="showActions"
|
||
:actions="actionList"
|
||
@close="showActions = false"
|
||
@select="onActionSelect"
|
||
></u-action-sheet>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { reactive, ref, onMounted, computed } from 'vue'
|
||
|
||
export default {
|
||
name: 'RemindersPage',
|
||
setup() {
|
||
// 响应式数据
|
||
const reminders = ref([])
|
||
const currentFilter = ref('all')
|
||
const showAddModal = ref(false)
|
||
const showDatetime = ref(false)
|
||
const showPet = ref(false)
|
||
const showActions = ref(false)
|
||
const selectedDatetime = ref(Date.now())
|
||
const currentReminder = ref(null)
|
||
|
||
const newReminder = reactive({
|
||
title: '',
|
||
datetime: '',
|
||
petId: '',
|
||
petName: '',
|
||
priority: 'medium',
|
||
description: ''
|
||
})
|
||
|
||
const petColumns = ref([])
|
||
const actionList = ref([
|
||
{ name: '编辑', value: 'edit' },
|
||
{ name: '删除', value: 'delete', color: '#FF5722' }
|
||
])
|
||
|
||
// 样式配置
|
||
const inputStyle = {
|
||
fontSize: '28rpx',
|
||
color: '#333333'
|
||
}
|
||
|
||
const textareaStyle = {
|
||
fontSize: '26rpx',
|
||
color: '#333333'
|
||
}
|
||
|
||
// 计算属性
|
||
const pendingCount = computed(() => {
|
||
return reminders.value.filter(r => !r.completed).length
|
||
})
|
||
|
||
const todayCount = computed(() => {
|
||
const today = new Date().toDateString()
|
||
return reminders.value.filter(r =>
|
||
new Date(r.datetime).toDateString() === today
|
||
).length
|
||
})
|
||
|
||
const completedCount = computed(() => {
|
||
return reminders.value.filter(r => r.completed).length
|
||
})
|
||
|
||
const filteredReminders = computed(() => {
|
||
let filtered = reminders.value
|
||
|
||
switch (currentFilter.value) {
|
||
case 'pending':
|
||
filtered = reminders.value.filter(r => !r.completed)
|
||
break
|
||
case 'today':
|
||
const today = new Date().toDateString()
|
||
filtered = reminders.value.filter(r =>
|
||
new Date(r.datetime).toDateString() === today
|
||
)
|
||
break
|
||
case 'completed':
|
||
filtered = reminders.value.filter(r => r.completed)
|
||
break
|
||
default:
|
||
filtered = reminders.value
|
||
}
|
||
|
||
// 按时间排序,未完成的在前
|
||
return filtered.sort((a, b) => {
|
||
if (a.completed !== b.completed) {
|
||
return a.completed ? 1 : -1
|
||
}
|
||
return new Date(a.datetime) - new Date(b.datetime)
|
||
})
|
||
})
|
||
|
||
// 生命周期
|
||
onMounted(() => {
|
||
loadReminders()
|
||
loadPets()
|
||
})
|
||
|
||
// 方法定义
|
||
const loadReminders = () => {
|
||
try {
|
||
const savedReminders = uni.getStorageSync('reminders') || []
|
||
reminders.value = savedReminders
|
||
} catch (error) {
|
||
console.error('加载提醒数据失败:', error)
|
||
}
|
||
}
|
||
|
||
const loadPets = () => {
|
||
try {
|
||
const pets = uni.getStorageSync('pets') || []
|
||
petColumns.value = [pets.map(pet => pet.name)]
|
||
} catch (error) {
|
||
console.error('加载宠物数据失败:', error)
|
||
}
|
||
}
|
||
|
||
const saveReminders = () => {
|
||
uni.setStorageSync('reminders', reminders.value)
|
||
}
|
||
|
||
const setFilter = (filter) => {
|
||
currentFilter.value = filter
|
||
}
|
||
|
||
const isOverdue = (reminder) => {
|
||
if (reminder.completed) return false
|
||
return new Date(reminder.datetime) < new Date()
|
||
}
|
||
|
||
const formatDateTime = (datetime) => {
|
||
if (!datetime) return ''
|
||
const date = new Date(datetime)
|
||
const now = new Date()
|
||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
||
const reminderDate = new Date(date.getFullYear(), date.getMonth(), date.getDate())
|
||
|
||
let dateStr = ''
|
||
if (reminderDate.getTime() === today.getTime()) {
|
||
dateStr = '今天'
|
||
} else if (reminderDate.getTime() === today.getTime() + 24 * 60 * 60 * 1000) {
|
||
dateStr = '明天'
|
||
} else {
|
||
dateStr = `${date.getMonth() + 1}月${date.getDate()}日`
|
||
}
|
||
|
||
const timeStr = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
||
return `${dateStr} ${timeStr}`
|
||
}
|
||
|
||
const getEmptyText = () => {
|
||
switch (currentFilter.value) {
|
||
case 'pending':
|
||
return '暂无待处理的提醒'
|
||
case 'today':
|
||
return '今日暂无提醒事项'
|
||
case 'completed':
|
||
return '暂无已完成的提醒'
|
||
default:
|
||
return '暂无提醒事项'
|
||
}
|
||
}
|
||
|
||
const toggleReminder = (reminder) => {
|
||
reminder.completed = !reminder.completed
|
||
reminder.completedAt = reminder.completed ? new Date().toISOString() : null
|
||
saveReminders()
|
||
|
||
uni.showToast({
|
||
title: reminder.completed ? '已完成' : '已取消完成',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
const viewReminderDetail = (reminder) => {
|
||
const statusText = reminder.completed ? '已完成' : (isOverdue(reminder) ? '已过期' : '待处理')
|
||
const content = `时间:${formatDateTime(reminder.datetime)}\n状态:${statusText}${reminder.petName ? `\n宠物:${reminder.petName}` : ''}${reminder.description ? `\n备注:${reminder.description}` : ''}`
|
||
|
||
uni.showModal({
|
||
title: reminder.title,
|
||
content: content,
|
||
showCancel: false
|
||
})
|
||
}
|
||
|
||
const showReminderActions = (reminder) => {
|
||
currentReminder.value = reminder
|
||
showActions.value = true
|
||
}
|
||
|
||
const onActionSelect = (action) => {
|
||
if (action.value === 'edit') {
|
||
editReminder(currentReminder.value)
|
||
} else if (action.value === 'delete') {
|
||
deleteReminder(currentReminder.value)
|
||
}
|
||
showActions.value = false
|
||
}
|
||
|
||
const editReminder = (reminder) => {
|
||
Object.assign(newReminder, {
|
||
id: reminder.id,
|
||
title: reminder.title,
|
||
datetime: reminder.datetime,
|
||
petId: reminder.petId,
|
||
petName: reminder.petName,
|
||
priority: reminder.priority,
|
||
description: reminder.description
|
||
})
|
||
showAddModal.value = true
|
||
}
|
||
|
||
const deleteReminder = (reminder) => {
|
||
uni.showModal({
|
||
title: '确认删除',
|
||
content: '确定要删除这个提醒吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
const index = reminders.value.findIndex(r => r.id === reminder.id)
|
||
if (index > -1) {
|
||
reminders.value.splice(index, 1)
|
||
saveReminders()
|
||
uni.showToast({
|
||
title: '已删除',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const addReminder = () => {
|
||
// 重置表单
|
||
Object.assign(newReminder, {
|
||
id: '',
|
||
title: '',
|
||
datetime: '',
|
||
petId: '',
|
||
petName: '',
|
||
priority: 'medium',
|
||
description: ''
|
||
})
|
||
showAddModal.value = true
|
||
}
|
||
|
||
const confirmAddReminder = () => {
|
||
if (!newReminder.title.trim()) {
|
||
uni.showToast({
|
||
title: '请输入提醒标题',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
if (!newReminder.datetime) {
|
||
uni.showToast({
|
||
title: '请选择提醒时间',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
const reminder = {
|
||
id: newReminder.id || 'reminder_' + Date.now(),
|
||
title: newReminder.title.trim(),
|
||
datetime: newReminder.datetime,
|
||
petId: newReminder.petId,
|
||
petName: newReminder.petName,
|
||
priority: newReminder.priority,
|
||
description: newReminder.description.trim(),
|
||
completed: false,
|
||
createdAt: new Date().toISOString()
|
||
}
|
||
|
||
if (newReminder.id) {
|
||
// 编辑模式
|
||
const index = reminders.value.findIndex(r => r.id === newReminder.id)
|
||
if (index > -1) {
|
||
reminders.value[index] = reminder
|
||
}
|
||
} else {
|
||
// 新增模式
|
||
reminders.value.push(reminder)
|
||
}
|
||
|
||
saveReminders()
|
||
showAddModal.value = false
|
||
|
||
uni.showToast({
|
||
title: newReminder.id ? '修改成功' : '添加成功',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
const cancelAddReminder = () => {
|
||
showAddModal.value = false
|
||
}
|
||
|
||
const showDatetimePicker = () => {
|
||
selectedDatetime.value = newReminder.datetime ? new Date(newReminder.datetime).getTime() : Date.now()
|
||
showDatetime.value = true
|
||
}
|
||
|
||
const onDatetimeConfirm = (e) => {
|
||
newReminder.datetime = new Date(e.value).toISOString()
|
||
showDatetime.value = false
|
||
}
|
||
|
||
const showPetPicker = () => {
|
||
showPet.value = true
|
||
}
|
||
|
||
const onPetConfirm = (e) => {
|
||
const pets = uni.getStorageSync('pets') || []
|
||
const selectedPet = pets.find(pet => pet.name === e.value[0])
|
||
if (selectedPet) {
|
||
newReminder.petId = selectedPet.id
|
||
newReminder.petName = selectedPet.name
|
||
}
|
||
showPet.value = false
|
||
}
|
||
|
||
const setPriority = (priority) => {
|
||
newReminder.priority = priority
|
||
}
|
||
|
||
return {
|
||
reminders,
|
||
currentFilter,
|
||
showAddModal,
|
||
showDatetime,
|
||
showPet,
|
||
showActions,
|
||
selectedDatetime,
|
||
newReminder,
|
||
petColumns,
|
||
actionList,
|
||
inputStyle,
|
||
textareaStyle,
|
||
pendingCount,
|
||
todayCount,
|
||
completedCount,
|
||
filteredReminders,
|
||
setFilter,
|
||
isOverdue,
|
||
formatDateTime,
|
||
getEmptyText,
|
||
toggleReminder,
|
||
viewReminderDetail,
|
||
showReminderActions,
|
||
onActionSelect,
|
||
addReminder,
|
||
confirmAddReminder,
|
||
cancelAddReminder,
|
||
showDatetimePicker,
|
||
onDatetimeConfirm,
|
||
showPetPicker,
|
||
onPetConfirm,
|
||
setPriority
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.reminders-container {
|
||
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
|
||
min-height: 100vh;
|
||
padding-bottom: 120rpx;
|
||
}
|
||
|
||
/* 统计概览卡片 */
|
||
.stats-card {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
margin: 0 30rpx 24rpx 30rpx;
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
gap: 24rpx;
|
||
|
||
.stat-item {
|
||
text-align: center;
|
||
padding: 24rpx 16rpx;
|
||
border-radius: 16rpx;
|
||
background: rgba(255, 138, 128, 0.05);
|
||
|
||
.stat-number {
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
color: #FF8A80;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 22rpx;
|
||
color: #666666;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stat-icon {
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 筛选标签 */
|
||
.filter-tabs {
|
||
display: flex;
|
||
margin: 0 30rpx 24rpx 30rpx;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 24rpx;
|
||
padding: 8rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.filter-tab {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 16rpx 12rpx;
|
||
border-radius: 16rpx;
|
||
transition: all 0.3s ease;
|
||
|
||
&.active {
|
||
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
|
||
|
||
.tab-text {
|
||
color: white;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 提醒列表 */
|
||
.reminders-list {
|
||
margin: 0 30rpx;
|
||
|
||
.reminder-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
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);
|
||
}
|
||
|
||
&.completed {
|
||
opacity: 0.6;
|
||
|
||
.reminder-title {
|
||
text-decoration: line-through;
|
||
color: #999999;
|
||
}
|
||
}
|
||
|
||
&.overdue:not(.completed) {
|
||
border-left: 6rpx solid #FF5722;
|
||
|
||
.reminder-title {
|
||
color: #FF5722;
|
||
}
|
||
}
|
||
|
||
.reminder-checkbox {
|
||
margin-right: 16rpx;
|
||
margin-top: 4rpx;
|
||
|
||
.checkbox {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border: 3rpx solid #CCCCCC;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s ease;
|
||
|
||
&.checked {
|
||
background: #FF8A80;
|
||
border-color: #FF8A80;
|
||
|
||
.check-icon {
|
||
color: white;
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.reminder-content {
|
||
flex: 1;
|
||
|
||
.reminder-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
margin-bottom: 12rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.reminder-meta {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
margin-bottom: 8rpx;
|
||
|
||
.reminder-time,
|
||
.reminder-pet {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.time-icon,
|
||
.pet-icon {
|
||
font-size: 20rpx;
|
||
margin-right: 6rpx;
|
||
}
|
||
|
||
.time-text,
|
||
.pet-text {
|
||
font-size: 22rpx;
|
||
color: #666666;
|
||
}
|
||
}
|
||
}
|
||
|
||
.reminder-desc {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
|
||
.reminder-actions {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.reminder-priority {
|
||
.priority-dot {
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
border-radius: 50%;
|
||
|
||
&.high {
|
||
background: #FF5722;
|
||
}
|
||
|
||
&.medium {
|
||
background: #FF8A80;
|
||
}
|
||
|
||
&.low {
|
||
background: #CCCCCC;
|
||
}
|
||
}
|
||
}
|
||
|
||
.action-more {
|
||
padding: 8rpx;
|
||
|
||
.more-icon {
|
||
font-size: 24rpx;
|
||
color: #CCCCCC;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 80rpx 40rpx;
|
||
margin: 0 30rpx;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(20rpx);
|
||
border-radius: 24rpx;
|
||
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||
|
||
.empty-icon {
|
||
font-size: 80rpx;
|
||
margin-bottom: 24rpx;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
margin-bottom: 32rpx;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.empty-action {
|
||
display: inline-block;
|
||
padding: 16rpx 32rpx;
|
||
background: linear-gradient(135deg, #FF8A80, #FFB6C1);
|
||
border-radius: 20rpx;
|
||
|
||
.action-text {
|
||
font-size: 26rpx;
|
||
color: white;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 添加按钮 */
|
||
.add-button {
|
||
position: fixed;
|
||
bottom: 120rpx;
|
||
right: 40rpx;
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
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.4);
|
||
z-index: 100;
|
||
transition: all 0.3s ease;
|
||
|
||
&:active {
|
||
transform: scale(0.9);
|
||
}
|
||
|
||
.add-icon {
|
||
font-size: 48rpx;
|
||
color: white;
|
||
font-weight: 300;
|
||
}
|
||
}
|
||
|
||
/* 添加提醒表单 */
|
||
.add-reminder-form {
|
||
padding: 20rpx 0;
|
||
|
||
.form-item {
|
||
margin-bottom: 32rpx;
|
||
|
||
.form-label {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.datetime-picker,
|
||
.pet-picker {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 20rpx;
|
||
background: rgba(255, 138, 128, 0.05);
|
||
border-radius: 16rpx;
|
||
border: 1rpx solid rgba(255, 138, 128, 0.2);
|
||
|
||
.datetime-text,
|
||
.pet-text {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.picker-arrow {
|
||
font-size: 24rpx;
|
||
color: #FF8A80;
|
||
}
|
||
}
|
||
|
||
.priority-options {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.priority-option {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20rpx 16rpx;
|
||
border-radius: 16rpx;
|
||
background: rgba(255, 138, 128, 0.05);
|
||
border: 2rpx solid transparent;
|
||
transition: all 0.3s ease;
|
||
|
||
&.active {
|
||
border-color: #FF8A80;
|
||
background: rgba(255, 138, 128, 0.1);
|
||
}
|
||
|
||
.priority-dot {
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
border-radius: 50%;
|
||
margin-right: 8rpx;
|
||
|
||
&.high {
|
||
background: #FF5722;
|
||
}
|
||
|
||
&.medium {
|
||
background: #FF8A80;
|
||
}
|
||
|
||
&.low {
|
||
background: #CCCCCC;
|
||
}
|
||
}
|
||
|
||
.priority-text {
|
||
font-size: 26rpx;
|
||
color: #333333;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 375px) {
|
||
.reminders-container {
|
||
.stats-card,
|
||
.filter-tabs,
|
||
.reminders-list,
|
||
.empty-state {
|
||
margin-left: 20rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.stats-card,
|
||
.empty-state {
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.stats-grid {
|
||
gap: 16rpx;
|
||
|
||
.stat-item {
|
||
padding: 20rpx 12rpx;
|
||
|
||
.stat-number {
|
||
font-size: 36rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-button {
|
||
right: 30rpx;
|
||
bottom: 100rpx;
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
|
||
.add-icon {
|
||
font-size: 40rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 动画效果 */
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(20rpx);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.reminders-container > view {
|
||
animation: fadeIn 0.5s ease-out;
|
||
}
|
||
|
||
.reminder-item {
|
||
animation: fadeIn 0.3s ease-out;
|
||
}
|
||
|
||
.add-button {
|
||
animation: fadeIn 0.6s ease-out;
|
||
}
|
||
</style>
|