新建日程
This commit is contained in:
parent
ef7c28c767
commit
a43d25b9f5
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<button class="fab-plus" >+</button>
|
||||
<button class="fab-plus" @click="$emit('click')">+</button>
|
||||
</template>
|
||||
<script setup>
|
||||
defineEmits(['click']);
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.fab-plus {
|
||||
position: fixed;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
"style": {
|
||||
"navigationBarTitleText": "办公管理"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/add-event/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新建日程",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
|
|
|||
891
pages/add-event/index.vue
Normal file
891
pages/add-event/index.vue
Normal file
|
|
@ -0,0 +1,891 @@
|
|||
<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" @click="toggleAllDay">
|
||||
<text class="label">全天</text>
|
||||
<switch :checked="formData.allDay" @change="toggleAllDay" color="#2885ff" />
|
||||
</view>
|
||||
|
||||
<!-- 重复选项 -->
|
||||
<view class="form-item clickable-item" @click="showRepeatPicker = true">
|
||||
<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="showRepeatPicker = false">
|
||||
<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: formData.repeat === item.value }"
|
||||
@click="selectRepeat(item.value)"
|
||||
>
|
||||
<text>{{ item.label }}</text>
|
||||
<text v-if="formData.repeat === item.value" class="check">✓</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="modal-buttons">
|
||||
<button class="modal-btn" @click="showRepeatPicker = false">取消</button>
|
||||
<button class="modal-btn primary" @click="showRepeatPicker = false">确定</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, onMounted } from 'vue';
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
title: '',
|
||||
startDate: '',
|
||||
startHour: 16,
|
||||
startMin: 0,
|
||||
endDate: '',
|
||||
endHour: 17,
|
||||
endMin: 0,
|
||||
allDay: false,
|
||||
repeat: 'none',
|
||||
description: '',
|
||||
color: '#e3fae6',
|
||||
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 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 = [
|
||||
'#e3fae6', '#fae1e1', '#e3f2fd', '#fff3e0',
|
||||
'#f3e5f5', '#e0f2f1', '#ffebee', '#f1f8e9'
|
||||
];
|
||||
|
||||
// 重复选项
|
||||
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 = () => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
const options = currentPage.options || currentPage.$route?.query || {};
|
||||
|
||||
let dateStr = '';
|
||||
if (options.date) {
|
||||
dateStr = options.date;
|
||||
} else {
|
||||
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 selectRepeat = (value) => {
|
||||
formData.value.repeat = value;
|
||||
};
|
||||
|
||||
// 选择提醒
|
||||
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
|
||||
};
|
||||
|
||||
// 通过 getCurrentPages 获取上一页实例并调用方法
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
const prevPage = pages[pages.length - 2];
|
||||
// 如果上一页有 addEvent 方法,直接调用
|
||||
if (prevPage && typeof prevPage.addEvent === 'function') {
|
||||
prevPage.addEvent(eventData);
|
||||
} else {
|
||||
// 否则使用全局存储,在首页的 onShow 中读取
|
||||
uni.setStorageSync('newEventData', eventData);
|
||||
}
|
||||
} else {
|
||||
// 使用全局存储作为备选方案
|
||||
uni.setStorageSync('newEventData', eventData);
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initDates();
|
||||
});
|
||||
</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>
|
||||
|
||||
|
|
@ -7,13 +7,13 @@
|
|||
<uv-calendar ref="calendar" mode="single" @confirm="handleConfirm" ></uv-calendar>
|
||||
<button @click="openCalendar">选择日期</button>
|
||||
<view style=" font-size: 12px; color: #666;">
|
||||
当前选择日期:{{ selectedDate }},事件数:{{ eventsInDay.length }}
|
||||
当前选择日期:{{ selectedDate }},事件数:{{ eventsInDay ? eventsInDay.length : 0 }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 滑动容器 -->
|
||||
<view
|
||||
class="swipe-container"
|
||||
@touchstart="handleTouchStart"
|
||||
@touchstart="handleTouchStart"
|
||||
@touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd"
|
||||
>
|
||||
|
|
@ -38,9 +38,9 @@
|
|||
</view>
|
||||
|
||||
<!-- 悬浮新建按钮 -->
|
||||
<FabPlus @click="showAdd = true" />
|
||||
<FabPlus @click="handleAddClick" />
|
||||
|
||||
<!-- 新建日程弹窗 -->
|
||||
<!-- 新建日程弹窗(保留以备后用) -->
|
||||
<AddEventModal :show="showAdd" @ok="addEvent" @cancel="showAdd = false" />
|
||||
|
||||
<!-- 底部导航 -->
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
|
||||
import TimeTable from '@/components/TimeTable.vue';
|
||||
import FabPlus from '@/components/FabPlus.vue';
|
||||
|
|
@ -197,14 +198,25 @@ const handleConfirm = (e) => {
|
|||
|
||||
// 悬浮按钮/弹窗控制
|
||||
const showAdd = ref(false);
|
||||
|
||||
// 处理添加按钮点击
|
||||
const handleAddClick = () => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/add-event/index?date=${selectedDate.value}`
|
||||
});
|
||||
};
|
||||
|
||||
// 添加日程
|
||||
function addEvent(e) {
|
||||
// e是{title, startHour, startMin, color},补充date
|
||||
// e是{title, startHour, startMin, color, date等},如果没有date则使用selectedDate
|
||||
allEvents.value.push({
|
||||
...e, date: selectedDate.value,
|
||||
...e,
|
||||
date: e.date || selectedDate.value,
|
||||
id: Date.now()
|
||||
});
|
||||
showAdd.value = false;
|
||||
}
|
||||
|
||||
const value=ref(0);
|
||||
|
||||
// 滑动相关变量
|
||||
|
|
@ -371,6 +383,21 @@ watch(selectedDate, () => {
|
|||
onMounted(() => {
|
||||
initScreenWidth();
|
||||
});
|
||||
|
||||
// 页面显示时处理从新建日程页面返回的数据
|
||||
onShow(() => {
|
||||
// 从全局存储中读取新添加的日程数据
|
||||
try {
|
||||
const newEventData = uni.getStorageSync('newEventData');
|
||||
if (newEventData) {
|
||||
addEvent(newEventData);
|
||||
// 清除存储的数据
|
||||
uni.removeStorageSync('newEventData');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('读取新日程数据失败:', e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user