improve
This commit is contained in:
@@ -373,7 +373,8 @@ const togglePause = async () => {
|
||||
<div class="flex gap-1">
|
||||
<button @click="isReminderManagerOpen = true" class="relative p-2 hover:bg-bg-card rounded-xl text-text-sec">
|
||||
<Bell :size="18" />
|
||||
<span v-if="reminders.some(r => !r.is_completed)" class="absolute top-1.5 right-1.5 w-2 h-2 bg-[#007AFF] rounded-full border border-bg-sidebar"></span>
|
||||
<span v-if="reminders.some(r => !r.is_completed && (currentDate < getLogicDateStr() || (currentDate === getLogicDateStr() && r.minute < currentLogicalMinute)))" class="absolute top-1.5 right-1.5 w-2 h-2 bg-[#FF3B30] rounded-full border border-bg-sidebar"></span>
|
||||
<span v-else-if="reminders.some(r => !r.is_completed)" class="absolute top-1.5 right-1.5 w-2 h-2 bg-[#007AFF] rounded-full border border-bg-sidebar"></span>
|
||||
</button>
|
||||
<button @click="loadTimeline(true); loadEvents(); loadReminders()" class="p-2 hover:bg-bg-card rounded-xl text-text-sec"><RefreshCw :size="18" /></button>
|
||||
</div>
|
||||
@@ -405,7 +406,7 @@ const togglePause = async () => {
|
||||
</div>
|
||||
|
||||
<!-- Reminder Markers -->
|
||||
<div v-for="r in reminders" :key="'rem-'+r.id" class="absolute left-0 w-2 h-0.5 rounded-r-full z-40 transition-all"
|
||||
<div v-for="r in reminders" :key="'rem-'+r.id" class="absolute left-0 w-12 h-0.5 rounded-r-full z-40 transition-all"
|
||||
:class="r.is_completed ? 'bg-text-sec/30' :
|
||||
(currentDate < getLogicDateStr() || (currentDate === getLogicDateStr() && r.minute < currentLogicalMinute)
|
||||
? 'bg-[#FF3B30] shadow-[0_0_8px_rgba(255,59,48,0.6)]'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from "vue";
|
||||
import { X, Plus, Trash2, Check, Clock, Calendar } from "lucide-vue-next";
|
||||
import { X, Plus, Trash2, Check, Clock, Calendar, Edit2 } from "lucide-vue-next";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { reminders, loadReminders, showToast, currentDate, logicalMinutesToTime, logicalMinutesFromTime, currentLogicalMinute, getLogicDateStr, TIME_OFFSET_MINUTES } from "../../store";
|
||||
import { Reminder } from "../../types";
|
||||
@@ -17,6 +17,7 @@ const getInitialMinute = () => {
|
||||
|
||||
const newContent = ref("");
|
||||
const newMinute = ref(getInitialMinute());
|
||||
const editingId = ref<number | null>(null);
|
||||
|
||||
const isTimePickerOpen = ref(false);
|
||||
const timePickerRef = ref<HTMLElement | null>(null);
|
||||
@@ -45,18 +46,33 @@ const addReminder = async () => {
|
||||
showToast("请输入提醒内容", "error");
|
||||
return;
|
||||
}
|
||||
const isEditing = editingId.value !== null;
|
||||
try {
|
||||
await invoke("save_reminder", {
|
||||
reminder: { id: 0, date: currentDate.value, minute: newMinute.value, content: newContent.value, is_completed: false }
|
||||
reminder: { id: editingId.value || 0, date: currentDate.value, minute: newMinute.value, content: newContent.value, is_completed: false }
|
||||
});
|
||||
newContent.value = "";
|
||||
newMinute.value = getInitialMinute();
|
||||
editingId.value = null;
|
||||
await loadReminders();
|
||||
showToast("提醒已添加");
|
||||
showToast(isEditing ? "提醒已更新" : "提醒已添加");
|
||||
} catch (e) {
|
||||
showToast("添加失败: " + e, "error");
|
||||
showToast("保存失败: " + e, "error");
|
||||
}
|
||||
};
|
||||
|
||||
const editReminder = (r: Reminder) => {
|
||||
editingId.value = r.id;
|
||||
newContent.value = r.content;
|
||||
newMinute.value = r.minute;
|
||||
};
|
||||
|
||||
const cancelEdit = () => {
|
||||
editingId.value = null;
|
||||
newContent.value = "";
|
||||
newMinute.value = getInitialMinute();
|
||||
};
|
||||
|
||||
const toggleStatus = async (r: Reminder) => {
|
||||
try {
|
||||
await invoke("toggle_reminder", { id: r.id, isCompleted: !r.is_completed });
|
||||
@@ -96,10 +112,10 @@ const completedReminders = computed(() => safeReminders.value.filter(r => r.is_c
|
||||
<button @click="emit('close')" class="p-2 hover:bg-bg-input rounded-xl text-text-sec"><X :size="24" /></button>
|
||||
</div>
|
||||
|
||||
<div class="p-6 border-b border-border-main/50 bg-bg-input/30">
|
||||
<div class="p-6 border-b border-border-main/50 bg-bg-input/30 relative">
|
||||
<form @submit.prevent="addReminder" class="flex items-center gap-3">
|
||||
<div ref="timePickerRef" class="relative">
|
||||
<button type="button" @click="openTimePicker" class="bg-bg-card border border-border-main rounded-xl px-4 py-3 text-sm font-bold flex items-center justify-center hover:bg-bg-hover transition-all focus:border-[#007AFF]/50 w-24 outline-none">
|
||||
<button type="button" @click="openTimePicker" class="bg-bg-card border border-border-main rounded-xl px-4 py-3 text-sm font-bold flex items-center justify-center hover:bg-bg-hover transition-all focus:border-[#007AFF]/50 w-24 outline-none" :class="{ 'ring-2 ring-[#007AFF]/50 border-transparent': editingId }">
|
||||
{{ logicalMinutesToTime(newMinute) }}
|
||||
</button>
|
||||
<div v-if="isTimePickerOpen" class="absolute top-full left-0 mt-2 bg-bg-card rounded-3xl shadow-2xl border border-border-main z-120 p-4 animate-in fade-in slide-in-from-top-2 flex gap-4 h-64 w-48">
|
||||
@@ -115,49 +131,65 @@ const completedReminders = computed(() => safeReminders.value.filter(r => r.is_c
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" v-model="newContent" placeholder="添加新提醒..." class="flex-1 bg-bg-card border border-border-main rounded-xl px-4 py-3 text-sm font-bold outline-none focus:border-[#007AFF]/50" />
|
||||
<button type="submit" class="bg-[#007AFF] text-white p-3 rounded-xl hover:brightness-110 transition-all shadow-md shadow-[#007AFF]/20"><Plus :size="20" /></button>
|
||||
<div class="flex-1 relative">
|
||||
<input type="text" v-model="newContent" :placeholder="editingId ? '编辑提醒...' : '添加新提醒...'" class="w-full bg-bg-card border border-border-main rounded-xl px-4 py-3 text-sm font-bold outline-none focus:border-[#007AFF]/50 transition-all pr-10" :class="{ 'ring-2 ring-[#007AFF]/50 border-transparent': editingId }" />
|
||||
<button v-if="editingId" type="button" @click="cancelEdit" class="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-text-sec hover:bg-bg-input rounded-lg"><X :size="16" /></button>
|
||||
</div>
|
||||
<button type="submit" class="bg-[#007AFF] text-white p-3 rounded-xl hover:brightness-110 transition-all shadow-md shadow-[#007AFF]/20"><Check v-if="editingId" :size="20" /><Plus v-else :size="20" /></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto p-6 space-y-6 no-scrollbar">
|
||||
<div v-if="overdueReminders.length > 0">
|
||||
<!-- 已超时未办 -->
|
||||
<div v-if="overdueReminders && overdueReminders.length > 0">
|
||||
<h3 class="text-xs font-bold text-[#FF3B30] mb-3 uppercase tracking-wider">已超时未办</h3>
|
||||
<div class="space-y-2 mb-6">
|
||||
<div v-for="r in overdueReminders" :key="r.id" class="flex items-center gap-3 bg-[#FF3B30]/10 p-3 rounded-2xl border border-[#FF3B30]/30 group transition-all hover:bg-[#FF3B30]/20 hover:shadow-sm">
|
||||
<div v-for="r in overdueReminders" :key="r.id" class="flex items-center gap-3 bg-[#FF3B30]/10 p-3 rounded-2xl border border-[#FF3B30]/30 group transition-all hover:bg-[#FF3B30]/20 hover:shadow-sm" :class="{ 'ring-2 ring-[#FF3B30]/50': editingId === r.id }">
|
||||
<button @click="toggleStatus(r)" class="w-6 h-6 rounded-full border-2 border-[#FF3B30]/50 flex items-center justify-center text-transparent hover:border-[#FF3B30] transition-all"><Check :size="14" class="opacity-0 group-hover:opacity-50 group-hover:text-[#FF3B30]"/></button>
|
||||
<div class="font-bold text-[#FF3B30] text-sm w-12">{{ logicalMinutesToTime(r.minute) }}</div>
|
||||
<div class="flex-1 font-medium text-sm text-[#FF3B30] truncate">{{ r.content }}</div>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] opacity-0 group-hover:opacity-100 transition-all rounded-lg hover:bg-[#FF3B30]/20"><Trash2 :size="16" /></button>
|
||||
<div class="flex-1 font-medium text-sm text-[#FF3B30] truncate" :class="{ 'opacity-50': editingId === r.id }">{{ r.content }}</div>
|
||||
<div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-all">
|
||||
<button @click="editReminder(r)" class="p-2 text-text-sec hover:text-[#007AFF] rounded-lg hover:bg-[#007AFF]/10"><Edit2 :size="16" /></button>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] rounded-lg hover:bg-[#FF3B30]/20"><Trash2 :size="16" /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="upcomingReminders.length > 0">
|
||||
<!-- 即将到来 -->
|
||||
<div v-if="upcomingReminders && upcomingReminders.length > 0">
|
||||
<h3 class="text-xs font-bold text-text-sec mb-3 uppercase tracking-wider">即将到来</h3>
|
||||
<div class="space-y-2 mb-6">
|
||||
<div v-for="r in upcomingReminders" :key="r.id" class="flex items-center gap-3 bg-bg-input/50 p-3 rounded-2xl border border-border-main/30 group transition-all hover:bg-bg-input hover:shadow-sm">
|
||||
<div v-for="r in upcomingReminders" :key="r.id" class="flex items-center gap-3 bg-bg-input/50 p-3 rounded-2xl border border-border-main/30 group transition-all hover:bg-bg-input hover:shadow-sm" :class="{ 'ring-2 ring-[#007AFF]/50 border-transparent': editingId === r.id }">
|
||||
<button @click="toggleStatus(r)" class="w-6 h-6 rounded-full border-2 border-border-main flex items-center justify-center text-transparent hover:border-[#007AFF] transition-all"><Check :size="14" class="opacity-0 group-hover:opacity-30 group-hover:text-[#007AFF]"/></button>
|
||||
<div class="font-bold text-[#007AFF] text-sm w-12">{{ logicalMinutesToTime(r.minute) }}</div>
|
||||
<div class="flex-1 font-medium text-sm text-text-main truncate">{{ r.content }}</div>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] opacity-0 group-hover:opacity-100 transition-all rounded-lg hover:bg-[#FF3B30]/10"><Trash2 :size="16" /></button>
|
||||
<div class="flex-1 font-medium text-sm text-text-main truncate" :class="{ 'opacity-50': editingId === r.id }">{{ r.content }}</div>
|
||||
<div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-all">
|
||||
<button @click="editReminder(r)" class="p-2 text-text-sec hover:text-[#007AFF] rounded-lg hover:bg-[#007AFF]/10"><Edit2 :size="16" /></button>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] rounded-lg hover:bg-[#FF3B30]/10"><Trash2 :size="16" /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="completedReminders.length > 0">
|
||||
<!-- 已完成 -->
|
||||
<div v-if="completedReminders && completedReminders.length > 0">
|
||||
<h3 class="text-xs font-bold text-text-sec mb-3 uppercase tracking-wider">已完成</h3>
|
||||
<div class="space-y-2 opacity-60">
|
||||
<div v-for="r in completedReminders" :key="r.id" class="flex items-center gap-3 bg-bg-input/30 p-3 rounded-2xl border border-transparent group transition-all">
|
||||
<div v-for="r in completedReminders" :key="r.id" class="flex items-center gap-3 bg-bg-input/30 p-3 rounded-2xl border border-transparent group transition-all" :class="{ 'ring-2 ring-border-main': editingId === r.id }">
|
||||
<button @click="toggleStatus(r)" class="w-6 h-6 rounded-full bg-[#007AFF] flex items-center justify-center text-white"><Check :size="14" /></button>
|
||||
<div class="font-bold text-text-sec text-sm w-12 line-through">{{ logicalMinutesToTime(r.minute) }}</div>
|
||||
<div class="flex-1 font-medium text-sm text-text-sec line-through truncate">{{ r.content }}</div>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] opacity-0 group-hover:opacity-100 transition-all rounded-lg hover:bg-[#FF3B30]/10"><Trash2 :size="16" /></button>
|
||||
<div class="flex-1 font-medium text-sm text-text-sec line-through truncate" :class="{ 'opacity-50': editingId === r.id }">{{ r.content }}</div>
|
||||
<div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-all">
|
||||
<button @click="editReminder(r)" class="p-2 text-text-sec hover:text-[#007AFF] rounded-lg hover:bg-[#007AFF]/10"><Edit2 :size="16" /></button>
|
||||
<button @click="deleteItem(r.id)" class="p-2 text-text-sec hover:text-[#FF3B30] rounded-lg hover:bg-[#FF3B30]/10"><Trash2 :size="16" /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="overdueReminders.length === 0 && upcomingReminders.length === 0 && completedReminders.length === 0" class="flex flex-col items-center justify-center h-full text-text-sec opacity-40 mt-10">
|
||||
<!-- 无提醒事项 -->
|
||||
<div v-if="(!overdueReminders || overdueReminders.length === 0) && (!upcomingReminders || upcomingReminders.length === 0) && (!completedReminders || completedReminders.length === 0)" class="flex flex-col items-center justify-center h-full text-text-sec opacity-40 mt-10">
|
||||
<Calendar :size="48" class="mb-4" />
|
||||
<p class="font-bold">今天没有提醒事项</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user