add toast
This commit is contained in:
39
src/App.vue
39
src/App.vue
@@ -29,6 +29,12 @@ const isSettingsOpen = ref(false);
|
|||||||
const isTagManagerOpen = ref(false);
|
const isTagManagerOpen = ref(false);
|
||||||
const isEventModalOpen = ref(false);
|
const isEventModalOpen = ref(false);
|
||||||
|
|
||||||
|
const toast = ref({ message: "", type: "success", visible: false });
|
||||||
|
const showToast = (message: string, type = "success") => {
|
||||||
|
toast.value = { message, type, visible: true };
|
||||||
|
setTimeout(() => { toast.value.visible = false; }, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
const mergeScreens = ref(false);
|
const mergeScreens = ref(false);
|
||||||
const retainDays = ref(30);
|
const retainDays = ref(30);
|
||||||
const captureInterval = ref(30);
|
const captureInterval = ref(30);
|
||||||
@@ -95,24 +101,48 @@ const loadTags = async () => { tags.value = await invoke("get_tags"); };
|
|||||||
const loadEvents = async () => { dayEvents.value = await invoke("get_events", { date: currentDate.value }); };
|
const loadEvents = async () => { dayEvents.value = await invoke("get_events", { date: currentDate.value }); };
|
||||||
|
|
||||||
const handleAddTag = async (name: string, parentId: number | null, color: string) => {
|
const handleAddTag = async (name: string, parentId: number | null, color: string) => {
|
||||||
|
try {
|
||||||
await invoke("add_tag", { name, parentId, color });
|
await invoke("add_tag", { name, parentId, color });
|
||||||
await loadTags();
|
await loadTags();
|
||||||
|
showToast("标签添加成功");
|
||||||
|
} catch (e) {
|
||||||
|
showToast("添加失败: " + e, "error");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteTag = async (id: number) => {
|
const handleDeleteTag = async (id: number) => {
|
||||||
|
try {
|
||||||
await invoke("delete_tag", { id });
|
await invoke("delete_tag", { id });
|
||||||
await loadTags();
|
await loadTags();
|
||||||
|
showToast("标签已删除");
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e.toString().includes("FOREIGN KEY")) {
|
||||||
|
showToast("该标签正在被使用,无法删除", "error");
|
||||||
|
} else {
|
||||||
|
showToast("删除失败: " + e, "error");
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveEvent = async () => {
|
const saveEvent = async () => {
|
||||||
|
try {
|
||||||
await invoke("save_event", { event: editingEvent.value });
|
await invoke("save_event", { event: editingEvent.value });
|
||||||
isEventModalOpen.value = false;
|
isEventModalOpen.value = false;
|
||||||
await loadEvents();
|
await loadEvents();
|
||||||
|
showToast("事件已保存");
|
||||||
|
} catch (e) {
|
||||||
|
showToast("保存失败: " + e, "error");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteEvent = async (id: number) => {
|
const deleteEvent = async (id: number) => {
|
||||||
|
try {
|
||||||
await invoke("delete_event", { id });
|
await invoke("delete_event", { id });
|
||||||
await loadEvents();
|
await loadEvents();
|
||||||
|
showToast("事件已删除");
|
||||||
|
} catch (e) {
|
||||||
|
showToast("删除失败: " + e, "error");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const timeToLogicalMinutes = (timeStr: string, isNextDay = false) => {
|
const timeToLogicalMinutes = (timeStr: string, isNextDay = false) => {
|
||||||
@@ -336,6 +366,15 @@ const resetTagForm = () => { newTagName.value = ""; newTagParent.value = null; n
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isFullscreen && previewSrc" class="fixed inset-0 z-[200] bg-black/95 flex items-center justify-center p-6 backdrop-blur-xl"><button @click="isFullscreen = false" class="absolute top-10 right-10 w-12 h-12 bg-white/10 rounded-full flex items-center justify-center"><X :size="32" class="text-white" /></button><img :src="previewSrc" class="max-w-full max-h-full object-contain shadow-2xl" /></div>
|
<div v-if="isFullscreen && previewSrc" class="fixed inset-0 z-[200] bg-black/95 flex items-center justify-center p-6 backdrop-blur-xl"><button @click="isFullscreen = false" class="absolute top-10 right-10 w-12 h-12 bg-white/10 rounded-full flex items-center justify-center"><X :size="32" class="text-white" /></button><img :src="previewSrc" class="max-w-full max-h-full object-contain shadow-2xl" /></div>
|
||||||
|
|
||||||
|
<!-- Toast Notification -->
|
||||||
|
<div v-if="toast.visible" class="fixed bottom-10 left-1/2 -translate-x-1/2 z-[300] animate-in fade-in slide-in-from-bottom-4 duration-300">
|
||||||
|
<div class="px-6 py-3 rounded-2xl shadow-2xl backdrop-blur-md flex items-center gap-3 border border-white/20" :class="toast.type === 'error' ? 'bg-[#FF3B30] text-white' : 'bg-white/90 text-[#1D1D1F]'">
|
||||||
|
<div v-if="toast.type === 'error'" class="w-5 h-5 rounded-full border-2 border-white flex items-center justify-center text-[12px] font-black">!</div>
|
||||||
|
<div v-else class="w-5 h-5 rounded-full bg-[#34C759] flex items-center justify-center text-white text-[10px]">✓</div>
|
||||||
|
<span class="text-sm font-bold">{{ toast.message }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user