895 lines
23 KiB
Vue
895 lines
23 KiB
Vue
<template>
|
||
<view class="add-event-page">
|
||
<!-- 自定义导航栏 -->
|
||
<view class="custom-navbar">
|
||
<view class="navbar-content">
|
||
<text class="nav-btn" @click="handleCancel">取消</text>
|
||
<text class="nav-title">新建日程</text>
|
||
<text class="nav-btn nav-btn-primary" @click="handleSave">完成</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容区域 -->
|
||
<scroll-view class="content-scroll" scroll-y>
|
||
<!-- 标题输入 -->
|
||
<view class="form-item">
|
||
<input
|
||
v-model="formData.title"
|
||
class="title-input"
|
||
placeholder="添加标题"
|
||
placeholder-style="color: #999;"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 时间日期选择 -->
|
||
<view class="form-item time-section">
|
||
<view class="time-item" @click="openStartPicker">
|
||
<view class="time-icon">🕐</view>
|
||
<view class="time-content">
|
||
<text class="time-value">{{ startTime }}</text>
|
||
<text class="time-date">{{ startDateText }}</text>
|
||
</view>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
<text class="time-separator">→</text>
|
||
<view class="time-item" @click="openEndPicker">
|
||
<view class="time-icon">🕐</view>
|
||
<view class="time-content">
|
||
<text class="time-value">{{ endTime }}</text>
|
||
<text class="time-date">{{ endDateText }}</text>
|
||
</view>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 全天开关 -->
|
||
<view class="form-item switch-item">
|
||
<text class="label">全天</text>
|
||
<switch :checked="formData.allDay" @change="toggleAllDay" color="#2885ff" />
|
||
</view>
|
||
|
||
<!-- 重复选项 -->
|
||
<view class="form-item clickable-item" @click="openRepeatPicker">
|
||
<text class="label">{{ repeatText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
|
||
<!-- 描述输入 -->
|
||
<view class="form-item clickable-item" @click="showDescInput = true">
|
||
<view class="desc-icon">📄</view>
|
||
<view class="desc-content">
|
||
<text v-if="formData.description" class="desc-text">{{ formData.description }}</text>
|
||
<text v-else class="desc-placeholder">添加描述</text>
|
||
</view>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
|
||
<!-- 日程颜色 -->
|
||
<view class="form-item clickable-item" @click="showColorPicker = true">
|
||
<view class="color-dot" :style="{ backgroundColor: formData.color }"></view>
|
||
<text class="label">日程颜色</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
|
||
<!-- 提醒设置 -->
|
||
<view class="form-item clickable-item" @click="showReminderPicker = true">
|
||
<view class="reminder-icon">🔔</view>
|
||
<text class="reminder-text">{{ reminderText }}</text>
|
||
<text class="arrow">›</text>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 开始日期时间选择弹窗 -->
|
||
<view v-if="showStartDatePicker || showStartTimePicker" class="modal-mask" @click="closeStartPicker">
|
||
<view class="modal-content datetime-modal" @click.stop>
|
||
<view class="modal-title">选择开始时间</view>
|
||
<view class="datetime-content">
|
||
<!-- 日期选择 -->
|
||
<view class="date-section">
|
||
<text class="section-label">日期</text>
|
||
<uv-calendar
|
||
ref="startDateCalendar"
|
||
mode="single"
|
||
@confirm="handleStartDateConfirm"
|
||
/>
|
||
</view>
|
||
<!-- 时间选择 -->
|
||
<view class="time-section-picker">
|
||
<text class="section-label">时间</text>
|
||
<picker
|
||
mode="multiSelector"
|
||
:value="startPickerIndex"
|
||
:range="startPickerRange"
|
||
@change="handleStartTimeChange"
|
||
>
|
||
<view class="picker-display">
|
||
{{ formatTime(formData.startHour, formData.startMin) }}
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="closeStartPicker">取消</button>
|
||
<button class="modal-btn primary" @click="closeStartPicker">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 结束日期时间选择弹窗 -->
|
||
<view v-if="showEndDatePicker || showEndTimePicker" class="modal-mask" @click="closeEndPicker">
|
||
<view class="modal-content datetime-modal" @click.stop>
|
||
<view class="modal-title">选择结束时间</view>
|
||
<view class="datetime-content">
|
||
<!-- 日期选择 -->
|
||
<view class="date-section">
|
||
<text class="section-label">日期</text>
|
||
<uv-calendar
|
||
ref="endDateCalendar"
|
||
mode="single"
|
||
@confirm="handleEndDateConfirm"
|
||
/>
|
||
</view>
|
||
<!-- 时间选择 -->
|
||
<view class="time-section-picker">
|
||
<text class="section-label">时间</text>
|
||
<picker
|
||
mode="multiSelector"
|
||
:value="endPickerIndex"
|
||
:range="endPickerRange"
|
||
@change="handleEndTimeChange"
|
||
>
|
||
<view class="picker-display">
|
||
{{ formatTime(formData.endHour, formData.endMin) }}
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="closeEndPicker">取消</button>
|
||
<button class="modal-btn primary" @click="closeEndPicker">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 描述输入弹窗 -->
|
||
<view v-if="showDescInput" class="modal-mask" @click="showDescInput = false">
|
||
<view class="modal-content" @click.stop>
|
||
<view class="modal-title">添加描述</view>
|
||
<textarea
|
||
v-model="formData.description"
|
||
class="desc-textarea"
|
||
placeholder="请输入描述"
|
||
auto-height
|
||
/>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="showDescInput = false">取消</button>
|
||
<button class="modal-btn primary" @click="showDescInput = false">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 颜色选择弹窗 -->
|
||
<view v-if="showColorPicker" class="modal-mask" @click="showColorPicker = false">
|
||
<view class="modal-content" @click.stop>
|
||
<view class="modal-title">选择颜色</view>
|
||
<view class="color-options">
|
||
<view
|
||
v-for="color in colorOptions"
|
||
:key="color"
|
||
class="color-option"
|
||
:class="{ active: formData.color === color }"
|
||
:style="{ backgroundColor: color }"
|
||
@click="selectColor(color)"
|
||
></view>
|
||
</view>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="showColorPicker = false">取消</button>
|
||
<button class="modal-btn primary" @click="showColorPicker = false">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 重复选择弹窗 -->
|
||
<view v-if="showRepeatPicker" class="modal-mask" @click="handleCancelRepeat">
|
||
<view class="modal-content" @click.stop>
|
||
<view class="modal-title">重复设置</view>
|
||
<view class="repeat-options">
|
||
<view
|
||
v-for="item in repeatOptions"
|
||
:key="item.value"
|
||
class="repeat-option"
|
||
:class="{ active: tempRepeat === item.value }"
|
||
@click="tempRepeat = item.value"
|
||
>
|
||
<text>{{ item.label }}</text>
|
||
<text v-if="tempRepeat === item.value" class="check">✓</text>
|
||
</view>
|
||
</view>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="handleCancelRepeat">取消</button>
|
||
<button class="modal-btn primary" @click="handleConfirmRepeat">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提醒选择弹窗 -->
|
||
<view v-if="showReminderPicker" class="modal-mask" @click="showReminderPicker = false">
|
||
<view class="modal-content" @click.stop>
|
||
<view class="modal-title">提醒设置</view>
|
||
<view class="reminder-options">
|
||
<view
|
||
v-for="item in reminderOptions"
|
||
:key="item.value"
|
||
class="reminder-option"
|
||
:class="{ active: formData.reminder === item.value }"
|
||
@click="selectReminder(item.value)"
|
||
>
|
||
<text>{{ item.label }}</text>
|
||
<text v-if="formData.reminder === item.value" class="check">✓</text>
|
||
</view>
|
||
</view>
|
||
<view class="modal-buttons">
|
||
<button class="modal-btn" @click="showReminderPicker = false">取消</button>
|
||
<button class="modal-btn primary" @click="showReminderPicker = false">确定</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed } from 'vue';
|
||
import { onLoad } from '@dcloudio/uni-app';
|
||
|
||
// 表单数据
|
||
const formData = ref({
|
||
title: '',
|
||
startDate: '',
|
||
startHour: 16,
|
||
startMin: 0,
|
||
endDate: '',
|
||
endHour: 17,
|
||
endMin: 0,
|
||
allDay: false,
|
||
repeat: 'none',
|
||
description: '',
|
||
color: '#0079FE',
|
||
reminder: 15 // 提前多少分钟提醒
|
||
});
|
||
|
||
// 显示状态
|
||
const showStartTimePicker = ref(false);
|
||
const showStartDatePicker = ref(false);
|
||
const showEndTimePicker = ref(false);
|
||
const showEndDatePicker = ref(false);
|
||
const showDescInput = ref(false);
|
||
const showColorPicker = ref(false);
|
||
const showRepeatPicker = ref(false);
|
||
const showReminderPicker = ref(false);
|
||
|
||
// 临时数据(用于弹窗暂存)
|
||
const tempRepeat = ref('none');
|
||
|
||
// 时间选择器相关
|
||
const hourOptions = Array.from({ length: 24 }, (_, i) => String(i).padStart(2, '0') + '时');
|
||
const minOptions = Array.from({ length: 60 }, (_, i) => String(i).padStart(2, '0') + '分');
|
||
|
||
const startPickerRange = ref([hourOptions, minOptions]);
|
||
const startPickerIndex = ref([16, 0]);
|
||
const endPickerRange = ref([hourOptions, minOptions]);
|
||
const endPickerIndex = ref([17, 0]);
|
||
|
||
const startDateCalendar = ref(null);
|
||
const endDateCalendar = ref(null);
|
||
|
||
// 颜色选项
|
||
const colorOptions = [
|
||
'#0079FE', '#FC902A', '#FF505D', '#18B48A',
|
||
'#FCBF28', '#8883F0',
|
||
];
|
||
|
||
// 重复选项
|
||
const repeatOptions = [
|
||
{ label: '不重复', value: 'none' },
|
||
{ label: '每天', value: 'daily' },
|
||
{ label: '每周', value: 'weekly' },
|
||
{ label: '每月', value: 'monthly' },
|
||
{ label: '每年', value: 'yearly' }
|
||
];
|
||
|
||
// 提醒选项
|
||
const reminderOptions = [
|
||
{ label: '不提醒', value: 0 },
|
||
{ label: '开始时', value: 0 },
|
||
{ label: '开始前5分钟', value: 5 },
|
||
{ label: '开始前15分钟', value: 15 },
|
||
{ label: '开始前30分钟', value: 30 },
|
||
{ label: '开始前1小时', value: 60 },
|
||
{ label: '开始前1天', value: 1440 }
|
||
];
|
||
|
||
// 格式化时间
|
||
const formatTime = (hour, min) => {
|
||
const h = String(hour).padStart(2, '0');
|
||
const m = String(min).padStart(2, '0');
|
||
return `${h}:${m}`;
|
||
};
|
||
|
||
// 格式化日期文本
|
||
const formatDateText = (dateStr) => {
|
||
if (!dateStr) return '';
|
||
const date = new Date(dateStr);
|
||
const month = date.getMonth() + 1;
|
||
const day = date.getDate();
|
||
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||
const weekday = weekdays[date.getDay()];
|
||
return `${month}月${day}日 ${weekday}`;
|
||
};
|
||
|
||
// 计算属性
|
||
const startTime = computed(() => {
|
||
return formData.value.allDay ? '全天' : formatTime(formData.value.startHour, formData.value.startMin);
|
||
});
|
||
|
||
const endTime = computed(() => {
|
||
return formData.value.allDay ? '' : formatTime(formData.value.endHour, formData.value.endMin);
|
||
});
|
||
|
||
const startDateText = computed(() => {
|
||
return formatDateText(formData.value.startDate);
|
||
});
|
||
|
||
const endDateText = computed(() => {
|
||
return formatDateText(formData.value.endDate || formData.value.startDate);
|
||
});
|
||
|
||
// 打开开始时间选择器
|
||
const openStartPicker = () => {
|
||
if (formData.value.allDay) {
|
||
showStartDatePicker.value = true;
|
||
} else {
|
||
showStartDatePicker.value = true;
|
||
showStartTimePicker.value = true;
|
||
}
|
||
// 更新选择器索引
|
||
startPickerIndex.value = [formData.value.startHour, formData.value.startMin];
|
||
};
|
||
|
||
// 打开结束时间选择器
|
||
const openEndPicker = () => {
|
||
if (formData.value.allDay) {
|
||
showEndDatePicker.value = true;
|
||
} else {
|
||
showEndDatePicker.value = true;
|
||
showEndTimePicker.value = true;
|
||
}
|
||
// 更新选择器索引
|
||
endPickerIndex.value = [formData.value.endHour, formData.value.endMin];
|
||
};
|
||
|
||
// 关闭开始选择器
|
||
const closeStartPicker = () => {
|
||
showStartDatePicker.value = false;
|
||
showStartTimePicker.value = false;
|
||
};
|
||
|
||
// 关闭结束选择器
|
||
const closeEndPicker = () => {
|
||
showEndDatePicker.value = false;
|
||
showEndTimePicker.value = false;
|
||
};
|
||
|
||
const reminderText = computed(() => {
|
||
if (formData.value.reminder === 0) {
|
||
return '不提醒';
|
||
}
|
||
if (formData.value.reminder === 1440) {
|
||
return '开始前1天,应用弹窗提醒我';
|
||
}
|
||
if (formData.value.reminder === 60) {
|
||
return `开始前1小时,应用弹窗提醒我`;
|
||
}
|
||
return `开始前${formData.value.reminder}分钟,应用弹窗提醒我`;
|
||
});
|
||
|
||
const repeatText = computed(() => {
|
||
const option = repeatOptions.find(opt => opt.value === formData.value.repeat);
|
||
return option ? option.label : '不重复';
|
||
});
|
||
|
||
// 初始化日期
|
||
const initDates = (dateStr = '') => {
|
||
// 如果没有传入日期参数,使用今天
|
||
if (!dateStr) {
|
||
const today = new Date();
|
||
dateStr = today.toISOString().slice(0, 10);
|
||
}
|
||
|
||
formData.value.startDate = dateStr;
|
||
formData.value.endDate = dateStr;
|
||
|
||
// 设置默认时间为当前时间到一小时后(如果不是全天)
|
||
if (!formData.value.allDay) {
|
||
const today = new Date();
|
||
formData.value.startHour = today.getHours();
|
||
formData.value.startMin = Math.ceil(today.getMinutes() / 5) * 5; // 向上取整到5的倍数
|
||
const endTime = new Date(today);
|
||
endTime.setHours(today.getHours() + 1);
|
||
formData.value.endHour = endTime.getHours();
|
||
formData.value.endMin = endTime.getMinutes();
|
||
startPickerIndex.value = [formData.value.startHour, formData.value.startMin];
|
||
endPickerIndex.value = [formData.value.endHour, formData.value.endMin];
|
||
}
|
||
};
|
||
|
||
// 处理开始日期确认
|
||
const handleStartDateConfirm = (e) => {
|
||
const formattedDate = formatDateToYYYYMMDD(e);
|
||
if (formattedDate) {
|
||
formData.value.startDate = formattedDate;
|
||
// 如果结束日期未设置或早于开始日期,更新结束日期
|
||
if (!formData.value.endDate || formData.value.endDate < formData.value.startDate) {
|
||
formData.value.endDate = formData.value.startDate;
|
||
}
|
||
}
|
||
};
|
||
|
||
// 处理开始时间变化
|
||
const handleStartTimeChange = (e) => {
|
||
const [hourIndex, minIndex] = e.detail.value;
|
||
formData.value.startHour = hourIndex;
|
||
formData.value.startMin = minIndex;
|
||
startPickerIndex.value = [hourIndex, minIndex];
|
||
|
||
// 如果结束时间早于开始时间,自动调整结束时间
|
||
if (formData.value.endDate === formData.value.startDate) {
|
||
const startTotalMin = formData.value.startHour * 60 + formData.value.startMin;
|
||
const endTotalMin = formData.value.endHour * 60 + formData.value.endMin;
|
||
if (endTotalMin <= startTotalMin) {
|
||
const newEndTotalMin = startTotalMin + 60; // 默认延长1小时
|
||
formData.value.endHour = Math.floor(newEndTotalMin / 60) % 24;
|
||
formData.value.endMin = newEndTotalMin % 60;
|
||
endPickerIndex.value = [formData.value.endHour, formData.value.endMin];
|
||
}
|
||
}
|
||
};
|
||
|
||
// 处理结束日期确认
|
||
const handleEndDateConfirm = (e) => {
|
||
const formattedDate = formatDateToYYYYMMDD(e);
|
||
if (formattedDate) {
|
||
formData.value.endDate = formattedDate;
|
||
}
|
||
};
|
||
|
||
// 处理结束时间变化
|
||
const handleEndTimeChange = (e) => {
|
||
const [hourIndex, minIndex] = e.detail.value;
|
||
formData.value.endHour = hourIndex;
|
||
formData.value.endMin = minIndex;
|
||
endPickerIndex.value = [hourIndex, minIndex];
|
||
};
|
||
|
||
// 格式化日期为 YYYY-MM-DD(复用首页的逻辑)
|
||
function formatDateToYYYYMMDD(dateInput) {
|
||
if (!dateInput) return '';
|
||
let dateStr = '';
|
||
if (typeof dateInput === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(dateInput)) {
|
||
return dateInput;
|
||
}
|
||
if (typeof dateInput === 'string') {
|
||
dateStr = dateInput;
|
||
} else if (dateInput?.date) {
|
||
dateStr = dateInput.date;
|
||
} else if (dateInput?.value) {
|
||
dateStr = dateInput.value;
|
||
} else if (Array.isArray(dateInput) && dateInput.length > 0) {
|
||
dateStr = typeof dateInput[0] === 'string' ? dateInput[0] : (dateInput[0]?.date || dateInput[0]?.value || '');
|
||
}
|
||
if (!dateStr) return '';
|
||
const date = new Date(dateStr);
|
||
if (!isNaN(date.getTime())) {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
}
|
||
if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
|
||
return dateStr.slice(0, 10);
|
||
}
|
||
return '';
|
||
}
|
||
|
||
// 切换全天
|
||
const toggleAllDay = () => {
|
||
formData.value.allDay = !formData.value.allDay;
|
||
if (formData.value.allDay) {
|
||
formData.value.startHour = 0;
|
||
formData.value.startMin = 0;
|
||
formData.value.endHour = 23;
|
||
formData.value.endMin = 59;
|
||
startPickerIndex.value = [0, 0];
|
||
endPickerIndex.value = [23, 59];
|
||
}
|
||
};
|
||
|
||
// 选择颜色
|
||
const selectColor = (color) => {
|
||
formData.value.color = color;
|
||
};
|
||
|
||
// 打开重复选择弹窗
|
||
const openRepeatPicker = () => {
|
||
// 打开弹窗时,将当前值复制到临时变量
|
||
tempRepeat.value = formData.value.repeat;
|
||
showRepeatPicker.value = true;
|
||
};
|
||
|
||
// 取消重复选择
|
||
const handleCancelRepeat = () => {
|
||
// 恢复原始值
|
||
tempRepeat.value = formData.value.repeat;
|
||
showRepeatPicker.value = false;
|
||
};
|
||
|
||
// 确认重复选择
|
||
const handleConfirmRepeat = () => {
|
||
// 将临时变量的值更新到表单数据
|
||
formData.value.repeat = tempRepeat.value;
|
||
showRepeatPicker.value = false;
|
||
};
|
||
|
||
// 选择提醒
|
||
const selectReminder = (value) => {
|
||
formData.value.reminder = value;
|
||
};
|
||
|
||
// 取消
|
||
const handleCancel = () => {
|
||
uni.navigateBack();
|
||
};
|
||
|
||
// 保存
|
||
const handleSave = () => {
|
||
if (!formData.value.title.trim()) {
|
||
uni.showToast({
|
||
title: '请输入标题',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 准备返回的数据
|
||
const eventData = {
|
||
title: formData.value.title,
|
||
date: formData.value.startDate,
|
||
startHour: formData.value.startHour,
|
||
startMin: formData.value.startMin,
|
||
endHour: formData.value.endHour,
|
||
endMin: formData.value.endMin,
|
||
color: formData.value.color,
|
||
allDay: formData.value.allDay,
|
||
repeat: formData.value.repeat,
|
||
description: formData.value.description,
|
||
reminder: formData.value.reminder
|
||
};
|
||
|
||
// 使用全局存储传递数据,在首页的 onShow 中读取
|
||
uni.setStorageSync('newEventData', eventData);
|
||
|
||
// 返回上一页
|
||
uni.navigateBack();
|
||
};
|
||
|
||
// 页面加载时接收参数
|
||
onLoad((options) => {
|
||
const dateStr = options?.date || '';
|
||
initDates(dateStr);
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.add-event-page {
|
||
min-height: 100vh;
|
||
background: #fff;
|
||
}
|
||
|
||
.custom-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 1000;
|
||
background: #fff;
|
||
border-bottom: 1px solid #e5e5e5;
|
||
padding-top: var(--status-bar-height, 0);
|
||
}
|
||
|
||
.navbar-content {
|
||
height: 44px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 16px;
|
||
}
|
||
|
||
.nav-btn {
|
||
font-size: 16px;
|
||
color: #333;
|
||
padding: 8px;
|
||
}
|
||
|
||
.nav-btn-primary {
|
||
color: #2885ff;
|
||
}
|
||
|
||
.nav-title {
|
||
font-size: 17px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.content-scroll {
|
||
margin-top: calc(var(--status-bar-height, 0) + 45px);
|
||
height: calc(100vh - var(--status-bar-height, 0) - 45px);
|
||
}
|
||
|
||
.form-item {
|
||
padding: 16px;
|
||
border-bottom: 1px solid #f5f5f5;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.title-input {
|
||
width: 100%;
|
||
font-size: 18px;
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.time-section {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20px 16px;
|
||
}
|
||
|
||
.time-item {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
.time-icon {
|
||
font-size: 20px;
|
||
}
|
||
|
||
.time-content {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.time-value {
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.time-date {
|
||
font-size: 12px;
|
||
color: #999;
|
||
}
|
||
|
||
.time-separator {
|
||
margin: 0 16px;
|
||
font-size: 20px;
|
||
color: #ccc;
|
||
}
|
||
|
||
.arrow {
|
||
font-size: 20px;
|
||
color: #ccc;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.switch-item {
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.label {
|
||
font-size: 16px;
|
||
color: #333;
|
||
}
|
||
|
||
.clickable-item {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.desc-icon {
|
||
font-size: 20px;
|
||
margin-right: 12px;
|
||
}
|
||
|
||
.desc-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.desc-text {
|
||
font-size: 16px;
|
||
color: #333;
|
||
}
|
||
|
||
.desc-placeholder {
|
||
font-size: 16px;
|
||
color: #999;
|
||
}
|
||
|
||
.color-dot {
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
margin-right: 12px;
|
||
}
|
||
|
||
.reminder-icon {
|
||
font-size: 20px;
|
||
margin-right: 12px;
|
||
}
|
||
|
||
.reminder-text {
|
||
flex: 1;
|
||
font-size: 16px;
|
||
color: #333;
|
||
}
|
||
|
||
/* 弹窗样式 */
|
||
.modal-mask {
|
||
position: fixed;
|
||
left: 0;
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 2000;
|
||
}
|
||
|
||
.modal-content {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
padding: 24px;
|
||
width: 80%;
|
||
max-width: 500px;
|
||
max-height: 80vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin-bottom: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.desc-textarea {
|
||
width: 100%;
|
||
min-height: 120px;
|
||
padding: 12px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.color-options {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16px;
|
||
justify-content: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.color-option {
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 50%;
|
||
border: 3px solid transparent;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.color-option.active {
|
||
border-color: #2885ff;
|
||
transform: scale(1.1);
|
||
}
|
||
|
||
.repeat-options,
|
||
.reminder-options {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.repeat-option,
|
||
.reminder-option {
|
||
padding: 16px;
|
||
border-bottom: 1px solid #f5f5f5;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.repeat-option:last-child,
|
||
.reminder-option:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.repeat-option.active,
|
||
.reminder-option.active {
|
||
color: #2885ff;
|
||
}
|
||
|
||
.check {
|
||
color: #2885ff;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.modal-buttons {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 16px;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.modal-btn {
|
||
padding: 10px 24px;
|
||
border: none;
|
||
background: #f5f5f5;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
color: #333;
|
||
}
|
||
|
||
.modal-btn.primary {
|
||
background: #2885ff;
|
||
color: #fff;
|
||
}
|
||
|
||
.datetime-modal {
|
||
max-width: 90%;
|
||
}
|
||
|
||
.datetime-content {
|
||
max-height: 60vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.date-section {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.section-label {
|
||
display: block;
|
||
font-size: 14px;
|
||
color: #666;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.time-section-picker {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.picker-display {
|
||
padding: 12px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
font-size: 16px;
|
||
color: #333;
|
||
}
|
||
</style>
|
||
|