327 lines
6.9 KiB
Vue
327 lines
6.9 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="reminder-time-select-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" style="opacity: 0; min-width: 44px;"></text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 时间选项列表 -->
|
|||
|
|
<scroll-view class="content-scroll" scroll-y>
|
|||
|
|
<view class="time-options">
|
|||
|
|
<view
|
|||
|
|
v-for="option in timeOptions"
|
|||
|
|
:key="option.value"
|
|||
|
|
class="time-option"
|
|||
|
|
:class="{ active: selectedValue === option.value && !isCustom }"
|
|||
|
|
@click="selectTime(option.value)"
|
|||
|
|
>
|
|||
|
|
<text class="time-label">{{ option.label }}</text>
|
|||
|
|
<text v-if="selectedValue === option.value && !isCustom" class="check">✓</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 自定义时间 -->
|
|||
|
|
<view
|
|||
|
|
class="time-option custom-option"
|
|||
|
|
:class="{ active: isCustom }"
|
|||
|
|
@click="openCustomTime"
|
|||
|
|
>
|
|||
|
|
<text class="time-label">自定义时间</text>
|
|||
|
|
<text class="arrow">›</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 自定义时间弹窗 -->
|
|||
|
|
<view v-if="showCustomModal" class="modal-mask" @click="showCustomModal = false">
|
|||
|
|
<view class="modal-content" @click.stop>
|
|||
|
|
<view class="modal-title">自定义时间</view>
|
|||
|
|
<view class="custom-time-content">
|
|||
|
|
<view class="custom-input-group">
|
|||
|
|
<text class="input-label">提前时间(分钟)</text>
|
|||
|
|
<input
|
|||
|
|
v-model="customMinutes"
|
|||
|
|
type="number"
|
|||
|
|
class="custom-input"
|
|||
|
|
placeholder="请输入分钟数"
|
|||
|
|
/>
|
|||
|
|
</view>
|
|||
|
|
<view class="custom-input-group">
|
|||
|
|
<text class="input-label">显示文本</text>
|
|||
|
|
<input
|
|||
|
|
v-model="customText"
|
|||
|
|
class="custom-input"
|
|||
|
|
placeholder="例如:开始前2小时"
|
|||
|
|
/>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="modal-buttons">
|
|||
|
|
<button class="modal-btn" @click="showCustomModal = false">取消</button>
|
|||
|
|
<button class="modal-btn primary" @click="confirmCustomTime">确定</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref } from 'vue';
|
|||
|
|
import { onLoad } from '@dcloudio/uni-app';
|
|||
|
|
|
|||
|
|
// 时间选项
|
|||
|
|
const timeOptions = [
|
|||
|
|
{ label: '开始时', value: 0 },
|
|||
|
|
{ label: '开始前5分钟', value: 5 },
|
|||
|
|
{ label: '开始前15分钟', value: 15 },
|
|||
|
|
{ label: '开始前30分钟', value: 30 },
|
|||
|
|
{ label: '开始前1小时', value: 60 },
|
|||
|
|
{ label: '开始前2小时', value: 120 },
|
|||
|
|
{ label: '开始前1天', value: 1440 },
|
|||
|
|
{ label: '开始前2天', value: 2880 },
|
|||
|
|
{ label: '开始前3天', value: 4320 }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const selectedValue = ref(15);
|
|||
|
|
const isCustom = ref(false);
|
|||
|
|
const showCustomModal = ref(false);
|
|||
|
|
const customMinutes = ref('');
|
|||
|
|
const customText = ref('');
|
|||
|
|
const action = ref('add'); // add 或 edit
|
|||
|
|
const reminderIndex = ref(0);
|
|||
|
|
|
|||
|
|
// 选择时间
|
|||
|
|
const selectTime = (value) => {
|
|||
|
|
selectedValue.value = value;
|
|||
|
|
isCustom.value = false;
|
|||
|
|
// 立即保存并返回
|
|||
|
|
saveAndReturn();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 打开自定义时间
|
|||
|
|
const openCustomTime = () => {
|
|||
|
|
showCustomModal.value = true;
|
|||
|
|
// 如果已经是自定义,填充现有值(从 onLoad 中已设置)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 确认自定义时间
|
|||
|
|
const confirmCustomTime = () => {
|
|||
|
|
if (!customMinutes.value || !customText.value.trim()) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请填写完整信息',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
isCustom.value = true;
|
|||
|
|
selectedValue.value = parseInt(customMinutes.value);
|
|||
|
|
showCustomModal.value = false;
|
|||
|
|
// 保存并返回
|
|||
|
|
saveAndReturn();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 保存并返回
|
|||
|
|
const saveAndReturn = () => {
|
|||
|
|
const reminder = {
|
|||
|
|
type: isCustom.value ? 'custom' : 'preset',
|
|||
|
|
minutes: selectedValue.value
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (isCustom.value) {
|
|||
|
|
reminder.customText = customText.value;
|
|||
|
|
reminder.customMinutes = parseInt(customMinutes.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 通过存储传递数据
|
|||
|
|
uni.setStorageSync('updatedReminder', {
|
|||
|
|
action: action.value,
|
|||
|
|
index: reminderIndex.value,
|
|||
|
|
reminder: reminder
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
uni.navigateBack();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 取消
|
|||
|
|
const handleCancel = () => {
|
|||
|
|
uni.navigateBack();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 页面加载
|
|||
|
|
onLoad((options) => {
|
|||
|
|
action.value = options.action || 'add';
|
|||
|
|
reminderIndex.value = parseInt(options.index || 0);
|
|||
|
|
|
|||
|
|
if (options.type === 'custom') {
|
|||
|
|
isCustom.value = true;
|
|||
|
|
customMinutes.value = options.customMinutes || '';
|
|||
|
|
customText.value = options.customText || '';
|
|||
|
|
selectedValue.value = parseInt(options.customMinutes || 0);
|
|||
|
|
} else {
|
|||
|
|
selectedValue.value = parseInt(options.minutes || 15);
|
|||
|
|
isCustom.value = false;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.reminder-time-select-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: 20px;
|
|||
|
|
color: #333;
|
|||
|
|
padding: 8px;
|
|||
|
|
min-width: 44px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-options {
|
|||
|
|
padding: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-option {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
padding: 16px;
|
|||
|
|
border-bottom: 1px solid #f5f5f5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-option.active {
|
|||
|
|
color: #2885ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-label {
|
|||
|
|
font-size: 16px;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-option.active .time-label {
|
|||
|
|
color: #2885ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.check {
|
|||
|
|
color: #2885ff;
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.arrow {
|
|||
|
|
font-size: 20px;
|
|||
|
|
color: #ccc;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.custom-option.active .arrow {
|
|||
|
|
color: #2885ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 弹窗样式 */
|
|||
|
|
.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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.modal-title {
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.custom-time-content {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.custom-input-group {
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.input-label {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.custom-input {
|
|||
|
|
width: 100%;
|
|||
|
|
padding: 12px;
|
|||
|
|
border: 1px solid #e5e5e5;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-size: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.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;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
|