Files
akmon/pages/sport/student/reminder-settings.uvue
2026-01-20 08:04:15 +08:00

1187 lines
31 KiB
Plaintext

<template>
<scroll-view direction="vertical" class="reminder-settings-page">
<!-- Header -->
<view class="header">
<view class="header-left">
<button @click="goBack" class="back-btn">
<simple-icon type="arrow-left" :size="16" color="#FFFFFF" />
<text>返回</text>
</button>
<text class="title">训练提醒</text>
</view>
<view class="header-actions">
<button @click="addReminder" class="add-btn">
<simple-icon type="plus" :size="16" color="#FFFFFF" />
<text>添加</text>
</button>
</view>
</view>
<!-- Loading State -->
<view v-if="loading" class="loading-container">
<text class="loading-text">加载中...</text>
</view>
<!-- Content -->
<scroll-view v-else class="content" scroll-y="true" :style="{ height: contentHeight + 'px' }">
<!-- Quick Settings -->
<view class="quick-settings-section">
<view class="section-title">快速设置</view>
<view class="quick-options">
<view class="quick-option" @click="createQuickReminder('daily')">
<view class="option-icon">
<text class="option-emoji"></text>
</view>
<view class="option-content">
<text class="option-title">每日训练</text>
<text class="option-desc">每天固定时间提醒</text>
</view>
</view>
<view class="quick-option" @click="createQuickReminder('weekly')">
<view class="option-icon">
<text class="option-emoji"></text>
</view>
<view class="option-content">
<text class="option-title">每周训练</text>
<text class="option-desc">选择特定日期提醒</text>
</view>
</view>
<view class="quick-option" @click="createQuickReminder('custom')">
<view class="option-icon">
<text class="option-emoji">⚙️</text>
</view>
<view class="option-content">
<text class="option-title">自定义</text>
<text class="option-desc">完全自定义提醒设置</text>
</view>
</view>
</view>
</view>
<!-- Current Reminders -->
<view class="reminders-section">
<view class="section-title">当前提醒</view>
<view v-if="reminders.length === 0" class="empty-state">
<simple-icon type="bell-off" :size="48" color="#BDC3C7" />
<text class="empty-text">还没有设置提醒</text>
<text class="empty-desc">设置提醒让训练更规律</text>
</view>
<view v-else class="reminders-list">
<view v-for="reminder in reminders" :key="reminder.id" class="reminder-item">
<view class="reminder-header">
<view class="reminder-info">
<text class="reminder-title">{{ reminder.title }}</text>
<text class="reminder-message">{{ reminder.message ?? '开始训练吧!' }}</text>
</view>
<switch :checked="reminder.is_enabled" @change="toggleReminder(reminder)" />
</view>
<view class="reminder-details">
<view class="detail-item">
<simple-icon type="clock" :size="16" color="#666" />
<text class="detail-text">{{ getTimeText(reminder) }}</text>
</view>
<view class="detail-item">
<simple-icon type="repeat" :size="16" color="#666" />
<text class="detail-text">{{ getRepeatText(reminder) }}</text>
</view>
<view v-if="reminder.advance_minutes as Number > 0" class="detail-item">
<simple-icon type="bell" :size="16" color="#666" />
<text class="detail-text">提前{{ reminder.advance_minutes }}分钟</text>
</view>
</view>
<view class="reminder-actions">
<button @click="editReminder(reminder)" class="edit-btn">编辑</button>
<button @click="deleteReminder(reminder)" class="delete-btn">删除</button>
</view>
</view>
</view>
</view>
<!-- Settings -->
<view class="settings-section">
<view class="section-title">提醒设置</view>
<view class="settings-list">
<view class="setting-item">
<view class="setting-info">
<text class="setting-title">声音提醒</text>
<text class="setting-desc">播放提示音</text>
</view>
<switch :checked="globalSettings.sound_enabled" @change="updateGlobalSetting('sound_enabled', $event as UniSwitchChangeEvent)" />
</view>
<view class="setting-item">
<view class="setting-info">
<text class="setting-title">震动提醒</text>
<text class="setting-desc">手机震动提示</text>
</view>
<switch :checked="globalSettings.vibrate_enabled" @change="updateGlobalSetting('vibrate_enabled', $event as UniSwitchChangeEvent)" />
</view>
<view class="setting-item">
<view class="setting-info">
<text class="setting-title">休息日提醒</text>
<text class="setting-desc">在休息日也发送提醒</text>
</view>
<switch :checked="globalSettings.rest_day_reminder" @change="updateGlobalSetting('rest_day_reminder', $event as UniSwitchChangeEvent)" />
</view>
</view>
</view>
</scroll-view>
<!-- Add/Edit Reminder Modal -->
<view v-if="showReminderModal" class="modal-overlay" @click="closeReminderModal">
<view class="modal-content" @click.stop>
<view class="modal-header">
<text class="modal-title">{{ editingReminder != null ? '编辑提醒' : '添加提醒' }}</text>
<button @click="closeReminderModal" class="modal-close">
<simple-icon type="x" :size="20" color="#666" />
</button>
</view>
<view class="modal-body">
<view class="form-group">
<text class="form-label">提醒类型</text>
<view class="picker-input" @click="showTypePicker = true">
<text>{{ reminderTypeOptions[reminderTypeIndex] ?? '请选择提醒类型' }}</text>
<simple-icon type="chevron-down" :size="16" color="#999" />
</view>
<view v-if="showTypePicker" class="picker-view-modal" @click="showTypePicker = false">
<picker-view :value="[reminderTypeIndex]" :indicator-style="'height: 40px;'" @change="onReminderTypePickerChange">
<picker-view-column>
<view v-for="(item, idx) in reminderTypeOptions" :key="idx" class="picker-view-item">{{ item }}</view>
</picker-view-column>
</picker-view>
<view class="picker-view-actions">
<button @click="showTypePicker = false">取消</button>
<button @click="confirmTypePicker">确定</button>
</view>
</view>
</view>
<view class="form-group">
<text class="form-label">提醒标题</text>
<input v-model="reminderForm.title" type="text"
class="form-input" placeholder="如: 晨练时间" />
</view>
<view class="form-group">
<text class="form-label">提醒内容</text>
<input v-model="reminderForm.message" type="text"
class="form-input" placeholder="如: 开始今天的训练吧!" />
</view>
<view class="form-group">
<text class="form-label">提醒时间</text>
<view class="picker-input" @click="showTimePicker = true">
<text>{{ reminderForm.trigger_time ?? '请选择时间' }}</text>
<simple-icon type="clock" :size="16" color="#999" />
</view>
<picker-time v-if="showTimePicker" :value="reminderForm.trigger_time" @change="onTimePickerChange" @cancel="showTimePicker = false" />
</view>
<view v-if="reminderForm.reminder_type === 'weekly'" class="form-group">
<text class="form-label">重复日期</text>
<view class="weekdays-selector">
<view v-for="(day, index) in weekdays" :key="index"
class="weekday-item"
:class="{ 'selected': isWeekdaySelected(index) }"
@click="toggleWeekday(index)">
<text class="weekday-text">{{ day }}</text>
</view>
</view>
</view>
<view v-if="reminderForm.reminder_type === 'custom'" class="form-group">
<text class="form-label">指定日期</text>
<view class="picker-input">
<input type="date"
v-model="reminderForm.trigger_date"
class="form-input"
placeholder="请选择日期" />
<simple-icon type="calendar" :size="16" color="#999" />
</view>
</view>
<view class="form-group">
<text class="form-label">提前提醒</text>
<view class="picker-input" @click="showAdvancePicker = true">
<text>{{ advanceOptions[advanceIndex] ?? '无提前提醒' }}</text>
<simple-icon type="chevron-down" :size="16" color="#999" />
</view>
<view v-if="showAdvancePicker" class="picker-view-modal" @click="showAdvancePicker = false">
<picker-view :value="[advanceIndex]" :indicator-style="'height: 40px;'" @change="onAdvancePickerChange">
<picker-view-column>
<view v-for="(item, idx) in advanceOptions" :key="idx" class="picker-view-item">{{ item }}</view>
</picker-view-column>
</picker-view>
<view class="picker-view-actions">
<button @click="showAdvancePicker = false">取消</button>
<button @click="confirmAdvancePicker">确定</button>
</view>
</view>
</view>
<view class="form-group">
<text class="form-label">重复次数</text>
<view class="picker-input" @click="showRepeatPicker = true">
<text>{{ repeatOptions[repeatIndex] ?? '1次' }}</text>
<simple-icon type="chevron-down" :size="16" color="#999" />
</view>
<view v-if="showRepeatPicker" class="picker-view-modal" @click="showRepeatPicker = false">
<picker-view :value="[repeatIndex]" :indicator-style="'height: 40px;'" @change="onRepeatPickerChange">
<picker-view-column>
<view v-for="(item, idx) in repeatOptions" :key="idx" class="picker-view-item">{{ item }}</view>
</picker-view-column>
</picker-view>
<view class="picker-view-actions">
<button @click="showRepeatPicker = false">取消</button>
<button @click="confirmRepeatPicker">确定</button>
</view>
</view>
</view>
</view>
<view class="modal-footer">
<button @click="closeReminderModal" class="cancel-btn">取消</button>
<button @click="saveReminder" class="save-btn" :disabled="!isReminderFormValid">保存</button>
</view>
</view>
</view>
</scroll-view>
</template>
<script setup lang="uts">
import { ref, onMounted, computed } from 'vue'
import { onResize, onLoad } from '@dcloudio/uni-app'
import { getCurrentUserId } from '@/utils/store'
import { state } from '@/utils/store.uts'
import supaClient from '@/components/supadb/aksupainstance.uts'
// Responsive state - using onResize for dynamic updates
const screenWidth = ref<number>(uni.getSystemInfoSync().windowWidth)
// Computed properties for responsive design
const isLargeScreen = computed(() : boolean => {
return screenWidth.value >= 768
})
// 响应式数据
const loading = ref(true)
const reminders = ref<UTSJSONObject[]>([])
const showReminderModal = ref(false)
const editingReminder = ref<UTSJSONObject | null>(null)
const contentHeight = ref(0)
const userId = ref('')
// 全局设置
const globalSettings = ref<UTSJSONObject>({
sound_enabled: true,
vibrate_enabled: true,
rest_day_reminder: false
})
// 表单数据
const reminderForm = ref<UTSJSONObject>({
reminder_type: 'daily',
title: '',
message: '',
trigger_time: '',
trigger_days: '',
trigger_date: '',
advance_minutes: 0,
repeat_count: 1,
repeat_interval_minutes: 5
})
// 选择器数据
const reminderTypeIndex = ref(0)
const advanceIndex = ref(0)
const repeatIndex = ref(0)
const reminderTypeOptions = ['每日', '每周', '自定义']
const reminderTypes = ['daily', 'weekly', 'custom']
const advanceOptions = ['无提前提醒', '5分钟前', '10分钟前', '15分钟前', '30分钟前', '1小时前']
const advanceValues = [0, 5, 10, 15, 30, 60]
const repeatOptions = ['1次', '2次', '3次', '5次', '直到确认']
const repeatValues = [1, 2, 3, 5, 10]
// 星期选择
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
const selectedWeekdays = ref<boolean[]>([false, false, false, false, false, false, false])
const showTypePicker = ref(false)
const showAdvancePicker = ref(false)
const showRepeatPicker = ref(false)
const showTimePicker = ref(false)
const tempTypeIndex = ref(reminderTypeIndex.value)
const tempAdvanceIndex = ref(advanceIndex.value)
const tempRepeatIndex = ref(repeatIndex.value)
// 计算内容高度
const calculateContentHeight = () => {
const systemInfo = uni.getSystemInfoSync()
const windowHeight = systemInfo.windowHeight
const headerHeight = 60
contentHeight.value = windowHeight - headerHeight
}
// 加载提醒数据
const loadReminders = async () => {
try {
loading.value = true
if (userId.value == null || userId.value == '') {
uni.showToast({
title: '请先登录',
icon: 'none'
})
return
}
const result = await supaClient
.from('ak_training_reminders')
.select('*', {})
.eq('user_id', userId.value)
.order('created_at', { ascending: false })
.execute()
if (result.data != null) {
reminders.value = result.data as UTSJSONObject[]
}
} catch (error) {
console.error('加载提醒失败:', error)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 加载全局设置
const loadGlobalSettings = () => {
try {
const settingsRaw = uni.getStorageSync('training_reminder_settings')
if (settingsRaw != null) {
const settings = new UTSJSONObject(settingsRaw)
if (settings.get('sound_enabled') != null) globalSettings.value.sound_enabled = settings.getBoolean('sound_enabled')
if (settings.get('vibrate_enabled') != null) globalSettings.value.vibrate_enabled = settings.getBoolean('vibrate_enabled')
if (settings.get('rest_day_reminder') != null) globalSettings.value.rest_day_reminder = settings.getBoolean('rest_day_reminder')
}
} catch (error) {
console.error('加载设置失败:', error)
}
}
// 保存全局设置
const saveGlobalSettings = () => {
try {
uni.setStorageSync('training_reminder_settings', globalSettings.value)
} catch (error) {
console.error('保存设置失败:', error)
}
}
// 重置表单
const resetReminderForm = () => {
reminderForm.value = new UTSJSONObject({
reminder_type: 'daily',
title: '',
message: '',
trigger_time: '',
trigger_days: '',
trigger_date: '',
advance_minutes: 0,
repeat_count: 1,
repeat_interval_minutes: 5
})
reminderTypeIndex.value = 0
advanceIndex.value = 0
repeatIndex.value = 0
selectedWeekdays.value = [false, false, false, false, false, false, false]
}
// 返回上一页
const goBack = () => {
uni.navigateBack()
}
// 添加提醒
const addReminder = () => {
editingReminder.value = null
resetReminderForm()
showReminderModal.value = true
}
// 快速创建提醒
const createQuickReminder = (type: string) => {
editingReminder.value = null
resetReminderForm()
reminderForm.value.reminder_type = type
reminderTypeIndex.value = reminderTypes.indexOf(type)
// 设置默认值
if (type === 'daily') {
reminderForm.value.title = '每日训练提醒'
reminderForm.value.message = '该开始今天的训练啦!'
reminderForm.value.trigger_time = '19:00'
} else if (type === 'weekly') {
reminderForm.value.title = '每周训练提醒'
reminderForm.value.message = '本周的训练时间到了!'
reminderForm.value.trigger_time = '09:00'
// 默认选择工作日
selectedWeekdays.value = [false, true, true, true, true, true, false]
} else {
reminderForm.value.title = '自定义提醒'
reminderForm.value.message = '开始训练吧!'
}
showReminderModal.value = true
}
// 填充表单
const populateReminderForm = (reminder: UTSJSONObject) => {
const reminderType = reminder.getString('reminder_type')
const title = reminder.getString('title')
const message = reminder.getString('message')
const triggerTime = reminder.getString('trigger_time')
const triggerDays = reminder.getString('trigger_days')
const triggerDate = reminder.getString('trigger_date')
const advanceMinutes = reminder.getNumber('advance_minutes')
const repeatCount = reminder.getNumber('repeat_count')
const repeatIntervalMinutes = reminder.getNumber('repeat_interval_minutes')
reminderForm.value = new UTSJSONObject({
reminder_type: reminderType != null ? reminderType : 'daily',
title: title != null ? title : '',
message: message != null ? message : '',
trigger_time: triggerTime != null ? triggerTime : '',
trigger_days: triggerDays != null ? triggerDays : '',
trigger_date: triggerDate != null ? triggerDate : '',
advance_minutes: advanceMinutes != null ? advanceMinutes : 0,
repeat_count: repeatCount != null ? repeatCount : 1,
repeat_interval_minutes: repeatIntervalMinutes != null ? repeatIntervalMinutes : 5
})
// 设置选择器索引
const typeIndex = reminderTypes.indexOf(reminderForm.value.getString('reminder_type'))
reminderTypeIndex.value = typeIndex >= 0 ? typeIndex : 0
const advIndex = advanceValues.indexOf(reminderForm.value.getNumber('advance_minutes'))
advanceIndex.value = advIndex >= 0 ? advIndex : 0
const repIndex = repeatValues.indexOf(reminderForm.value.getNumber('repeat_count'))
repeatIndex.value = repIndex >= 0 ? repIndex : 0
// 设置星期选择
const triggerDaysStr = reminderForm.value.getString('trigger_days')
if (triggerDaysStr != null && triggerDaysStr.length > 0) {
const days = triggerDaysStr.split('').map(d => parseInt(d))
selectedWeekdays.value = weekdays.map((_, index) => days.includes(index))
}
}
// 编辑提醒
const editReminder = (reminder: UTSJSONObject) => {
editingReminder.value = reminder
populateReminderForm(reminder)
showReminderModal.value = true
}
// 切换提醒开关
const toggleReminder = async (reminder: UTSJSONObject) => {
try {
const currentStatus = (reminder as UTSJSONObject).getBoolean('is_enabled') ?? true
const newStatus = !currentStatus
const result = await supaClient
.from('ak_training_reminders')
.update({ is_enabled: newStatus })
.eq('id', (reminder as UTSJSONObject).getString('id') ?? '')
.execute()
if (result.error != null) {
throw new Error(result.error?.message ?? '未知错误')
}
// 更新本地数据
const index = reminders.value.findIndex(r => (r as UTSJSONObject).getString('id') === (reminder as UTSJSONObject).getString('id'))
if (index >= 0) {
reminders.value[index] = { ...reminders.value[index], is_enabled: newStatus }
}
uni.showToast({
title: newStatus ? '提醒已开启' : '提醒已关闭',
icon: 'success'
})
} catch (error) {
console.error('更新提醒状态失败:', error)
uni.showToast({
title: '操作失败',
icon: 'none'
})
}
}
// 删除提醒异步逻辑
const handleDeleteReminder = async (reminder: UTSJSONObject) => {
try {
const result = await supaClient
.from('ak_training_reminders')
.delete()
.eq('id', (reminder as UTSJSONObject).getString('id') ?? '')
.execute()
if (result.error != null) {
throw new Error(result.error?.message ?? '未知错误')
}
uni.showToast({
title: '删除成功',
icon: 'success'
})
loadReminders()
} catch (error) {
console.error('删除提醒失败:', error)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
}
// 删除提醒
const deleteReminder = (reminder: UTSJSONObject) => {
uni.showModal({
title: '删除提醒',
content: '确定要删除这个提醒吗?',
success: (res) => {
if (res.confirm) {
handleDeleteReminder(reminder)
}
}
})
}
// 更新全局设置
const updateGlobalSetting = (key: string, event: UniSwitchChangeEvent) => {
globalSettings.value[key] = event.detail.value
saveGlobalSettings()
uni.showToast({
title: '设置已保存',
icon: 'success'
})
}
// 关闭模态框
const closeReminderModal = () => {
showReminderModal.value = false
editingReminder.value = null
}
// 保存提醒
const saveReminder = async () => {
try {
if (userId.value == null || userId.value == '') return
// 构建trigger_days
let triggerDays = ''
if (reminderForm.value.reminder_type === 'weekly') {
triggerDays = selectedWeekdays.value
.map((selected, index) => selected ? index.toString() : '')
.filter(day => day !== '')
.join('')
}
const triggerDate = reminderForm.value.trigger_date
const reminderData = {
user_id: userId.value,
reminder_type: reminderForm.value.reminder_type,
title: reminderForm.value.title,
message: reminderForm.value.message,
trigger_time: reminderForm.value.trigger_time,
trigger_days: triggerDays,
trigger_date: (triggerDate != null && triggerDate != '') ? triggerDate : null,
advance_minutes: reminderForm.value.advance_minutes,
repeat_count: reminderForm.value.repeat_count,
repeat_interval_minutes: reminderForm.value.repeat_interval_minutes,
is_enabled: true,
sound_enabled: globalSettings.value.sound_enabled,
vibrate_enabled: globalSettings.value.vibrate_enabled
}
let result: any
const upid = editingReminder.value?.getString('id')
if (upid != null) {
// 更新
result = await supaClient
.from('ak_training_reminders')
.update(reminderData)
.eq('id', upid)
.execute()
} else {
// 创建
result = await supaClient
.from('ak_training_reminders')
.insert(reminderData)
.execute()
}
if (result.error != null) {
throw new Error(result.error?.message ?? '未知错误')
}
uni.showToast({
title: editingReminder.value != null ? '更新成功' : '创建成功',
icon: 'success'
})
closeReminderModal()
loadReminders()
} catch (error) {
console.error('保存提醒失败:', error)
uni.showToast({
title: '保存失败',
icon: 'none'
})
}
}
const onTimePickerChange = (e: any) => {
reminderForm.value.trigger_time = e
showTimePicker.value = false
}
const onDateChange = (e: any) => {
reminderForm.value.trigger_date = e.value
}
const onAdvanceChange = (e: any) => {
advanceIndex.value = e.detail.value
reminderForm.value.advance_minutes = advanceValues[e.detail.value]
}
const onRepeatChange = (e: any) => {
repeatIndex.value = e.detail.value
reminderForm.value.repeat_count = repeatValues[e.detail.value]
}
// 星期选择相关
const toggleWeekday = (index: number) => {
selectedWeekdays.value[index] = !selectedWeekdays.value[index]
}
const isWeekdaySelected = (index: number): boolean => {
return selectedWeekdays.value[index]
}
const hasSelectedWeekdays = (): boolean => {
return selectedWeekdays.value.some(selected => selected)
}
const confirmAdvancePicker = () => {
advanceIndex.value = tempAdvanceIndex.value
reminderForm.value.advance_minutes = advanceValues[advanceIndex.value]
showAdvancePicker.value = false
}
const confirmTypePicker = () => {
reminderTypeIndex.value = tempTypeIndex.value
reminderForm.value.reminder_type = reminderTypes[reminderTypeIndex.value]
showTypePicker.value = false
}
const confirmRepeatPicker = () => {
repeatIndex.value = tempRepeatIndex.value
reminderForm.value.repeat_count = repeatValues[repeatIndex.value]
showRepeatPicker.value = false
}
// 选择器事件处理
const onReminderTypePickerChange = (e: UniPickerViewChangeEvent) => {
tempTypeIndex.value = e.detail.value[0]
}
const onAdvancePickerChange = (e: UniPickerViewChangeEvent) => {
tempAdvanceIndex.value = e.detail.value[0]
}
const onRepeatPickerChange = (e: UniPickerViewChangeEvent) => {
tempRepeatIndex.value = e.detail.value[0]
}
// 工具函数
const getTimeText = (reminder: UTSJSONObject): string => {
const time = reminder.getString('trigger_time')
return (time != null && time != '') ? time : '未设置'
}
const getRepeatText = (reminder: UTSJSONObject): string => {
const reminderType = reminder.getString('reminder_type') ?? ''
const days = reminder.getString('trigger_days') ?? ''
if (reminderType === 'daily') {
return '每天'
} else if (reminderType === 'weekly') {
if (days != null && days.length > 0) {
const selectedDays = days.split('').map(d => weekdays[parseInt(d)]).join('、')
return `每周${selectedDays}`
}
return '每周'
} else {
const date = reminder.getString('trigger_date') ?? ''
if (date != null && date.length > 0) {
return `${date}`
}
return '自定义'
}
}
// 生命周期
onMounted(() => {
screenWidth.value = uni.getSystemInfoSync().windowWidth
calculateContentHeight()
loadReminders()
loadGlobalSettings()
})
onResize((size) => {
screenWidth.value = size.size.windowWidth
})
onLoad((options: OnLoadOptions) => {
userId.value = options['id'] ?? getCurrentUserId();
})
const isReminderFormValid = computed(() => {
const form = reminderForm.value
if (form.title == null || form.title == "" || form.trigger_time == null || form.trigger_time == "") return false
if (form.reminder_type == "weekly" && !selectedWeekdays.value.some(v => v)) return false
if (form.reminder_type == "custom" && (form.trigger_date == null || form.trigger_date == "")) return false
return true
})
</script>
<style scoped>
.reminder-settings-page {
flex: 1;
background-color: #f5f5f5;
}
.header {
height: 60px;
background-image: linear-gradient(to top right, #4CAF50, #45a049);
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 16px;
}
.header-left {
flex-direction: row;
align-items: center;
flex: 1;
}
.back-btn, .add-btn {
background-color: rgba(255, 255, 255, 0.2);
border: none;
border-radius: 20px;
padding: 8px 12px;
flex-direction: row;
align-items: center;
gap: 4px;
}
.back-btn {
margin-right: 12px;
}
.back-btn text, .add-btn text {
color: #FFFFFF;
font-size: 14px;
}
.title {
font-size: 18px;
font-weight: bold;
color: #FFFFFF;
}
.content {
flex: 1;
padding: 16px;
}
.section-title {
font-size: 18px;
font-weight: bold;
color: #333;
margin-bottom: 12px;
}
.quick-settings-section {
margin-bottom: 24px;
}
.quick-options {
gap: 12px;
}
.quick-option {
background-color: #FFFFFF;
border-radius: 12px;
padding: 16px;
flex-direction: row;
align-items: center;
margin-bottom: 8px;
}
.option-icon {
width: 40px;
height: 40px;
background-color: #f0f0f0;
border-radius: 20px;
justify-content: center;
align-items: center;
margin-right: 12px;
}
.option-emoji {
font-size: 20px;
}
.option-content {
flex: 1;
}
.option-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.option-desc {
font-size: 12px;
color: #666;
}
.reminders-section {
margin-bottom: 24px;
}
.empty-state {
background-color: #FFFFFF;
border-radius: 12px;
padding: 40px 20px;
align-items: center;
text-align: center;
}
.empty-text {
font-size: 16px;
color: #666;
margin: 12px 0 4px;
}
.empty-desc {
font-size: 14px;
color: #999;
}
.reminders-list {
gap: 12px;
}
.reminder-item {
background-color: #FFFFFF;
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
}
.reminder-header {
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 12px;
}
.reminder-info {
flex: 1;
margin-right: 12px;
}
.reminder-title {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.reminder-message {
font-size: 14px;
color: #666;
}
.reminder-details {
margin-bottom: 12px;
gap: 8px;
}
.detail-item {
flex-direction: row;
align-items: center;
gap: 8px;
}
.detail-text {
font-size: 12px;
color: #666;
}
.reminder-actions {
flex-direction: row;
gap: 8px;
}
.edit-btn, .delete-btn {
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
border: none;
}
.edit-btn {
background-color: #4CAF50;
color: #FFFFFF;
}
.delete-btn {
background-color: #f5f5f5;
color: #666;
}
.settings-section {
margin-bottom: 24px;
}
.settings-list {
background-color: #FFFFFF;
border-radius: 12px;
overflow: hidden;
}
.setting-item {
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
}
.setting-info {
flex: 1;
}
.setting-title {
font-size: 16px;
color: #333;
margin-bottom: 4px;
}
.setting-desc {
font-size: 12px;
color: #666;
}
.weekdays-selector {
flex-direction: row;
gap: 8px;
flex-wrap: wrap;
}
.weekday-item {
width: 36px;
height: 36px;
border-radius: 18px;
background-color: #f0f0f0;
justify-content: center;
align-items: center;
border: 2px solid transparent;
}
.weekday-item.selected {
background-color: #4CAF50;
border-color: #45a049;
}
.weekday-text {
font-size: 14px;
color: #666;
}
.weekday-item.selected .weekday-text {
color: #FFFFFF;
font-weight: bold;
}
/* Modal Styles */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #FFFFFF;
border-radius: 12px;
width: 85%;
max-height: 80%;
}
.modal-header {
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 16px;
border-bottom: 1px solid #f0f0f0;
}
.modal-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.modal-close {
background: transparent;
border: none;
padding: 4px;
}
.modal-body {
padding: 16px;
max-height: 400px;
overflow-y: auto;
}
.form-group {
margin-bottom: 16px;
}
.form-label {
font-size: 14px;
color: #333;
margin-bottom: 8px;
display: block;
}
.form-input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
}
.picker-input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
color: #333;
position: relative;
}
.picker-input .chevron-down {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
}
.switch {
/* 自定义开关样式 */
}
.switch .uni-switch-label {
font-size: 14px;
color: #333;
}
.switch .uni-switch-button {
width: 40px;
height: 20px;
border-radius: 10px;
}
.switch .uni-switch-button:before {
width: 16px;
height: 16px;
border-radius: 8px;
}
.switch .uni-switch-button.checked {
background-color: #4CAF50;
}
.switch .uni-switch-button.checked:before {
transform: translateX(20px);
}
.switch .uni-switch-label {
margin-left: 8px;
}
/* iPhone X 及以上设备适配 */
@media only screen and (device-width: 375px) and (device-height: 812px) {
.header {
padding-top: 44px;
padding-bottom: 16px;
}
.header-left {
flex: 1;
}
.back-btn, .add-btn {
padding: 10px 16px;
}
.title {
font-size: 20px;
}
.content {
padding: 24px;
}
.section-title {
font-size: 20px;
}
.quick-option {
padding: 20px;
}
.reminder-item {
padding: 20px;
}
.setting-item {
padding: 20px;
}
.modal-content {
width: 90%;
}
}
</style>