From 0e39ad7ed89d94c9c8997ebcd38a1f3e5b3c77f2 Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Fri, 27 Mar 2026 12:36:35 -0400 Subject: [PATCH] upgrade cal --- package.json | 2 +- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/src/db.rs | 34 ++++++++++++++++++++++++++++++++++ src-tauri/src/engine.rs | 7 +++++++ src-tauri/src/lib.rs | 1 + src-tauri/tauri.conf.json | 4 ++-- src/App.vue | 33 ++++++++++++++++++++++++++++----- src/store/index.ts | 28 ++++++++++++++++++++++++++++ 9 files changed, 103 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index aee8ff8..2b4d948 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "chrono-snap", "private": true, - "version": "0.2.2", + "version": "0.2.3", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7292e11..66e6735 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -667,7 +667,7 @@ dependencies = [ [[package]] name = "chrono-snap" -version = "0.2.2" +version = "0.2.3" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0077955..16e1704 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chrono-snap" -version = "0.2.2" +version = "0.2.3" description = "An app to record screens and events" authors = ["you"] edition = "2021" diff --git a/src-tauri/src/db.rs b/src-tauri/src/db.rs index 1f05e2d..b4afdae 100644 --- a/src-tauri/src/db.rs +++ b/src-tauri/src/db.rs @@ -227,3 +227,37 @@ pub fn get_overdue_reminders_count(path: &str, date: &str, minute: i32) -> anyho let count: i32 = stmt.query_row(params![date, minute], |row| row.get(0))?; Ok(count) } + +#[derive(Serialize, Deserialize)] +pub struct DayStatus { + pub date: String, + pub has_overdue: bool, + pub has_upcoming: bool, +} + +pub fn get_reminders_by_month(path: &str, year_month: &str, today: &str, now_minute: i32) -> anyhow::Result> { + let conn = Connection::open(path)?; + // 查找该月份内有提醒的所有日期 + let mut stmt = conn.prepare(" + SELECT date, + MAX(CASE WHEN is_completed = 0 AND (date < ?2 OR (date = ?2 AND minute < ?3)) THEN 1 ELSE 0 END) as has_overdue, + MAX(CASE WHEN is_completed = 0 AND (date > ?2 OR (date = ?2 AND minute >= ?3)) THEN 1 ELSE 0 END) as has_upcoming + FROM reminders + WHERE date LIKE ?1 + GROUP BY date + ")?; + + let rows = stmt.query_map(params![format!("{}%", year_month), today, now_minute], |row| { + Ok(DayStatus { + date: row.get(0)?, + has_overdue: row.get::<_, i32>(1)? == 1, + has_upcoming: row.get::<_, i32>(2)? == 1, + }) + })?; + + let mut results = Vec::new(); + for row in rows { + results.push(row?); + } + Ok(results) +} diff --git a/src-tauri/src/engine.rs b/src-tauri/src/engine.rs index 75d3fa1..6421354 100644 --- a/src-tauri/src/engine.rs +++ b/src-tauri/src/engine.rs @@ -107,6 +107,13 @@ pub fn get_overdue_reminders_count(state: tauri::State<'_, AppState>, date: Stri crate::db::get_overdue_reminders_count(path, &date, minute).map_err(|e| e.to_string()) } +#[tauri::command] +pub fn get_reminders_by_month(state: tauri::State<'_, AppState>, year_month: String, today: String, now_minute: i32) -> Result, String> { + let path = state.db_path.lock().unwrap(); + let path = path.as_ref().ok_or("Database path not set")?; + crate::db::get_reminders_by_month(path, &year_month, &today, now_minute).map_err(|e| e.to_string()) +} + #[tauri::command] pub fn update_interval(state: tauri::State<'_, AppState>, seconds: u64) { state.capture_interval_secs.store(seconds, Ordering::SeqCst); diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 683a8f3..c8ff2c5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -37,6 +37,7 @@ pub fn run() { engine::delete_reminder, engine::toggle_reminder, engine::get_overdue_reminders_count, + engine::get_reminders_by_month, engine::write_file ]) .setup(|app| { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 051af2d..4e9044a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ChronoSnap", - "version": "0.2.2", + "version": "0.2.3", "identifier": "top.volan.chrono-snap", "build": { "beforeDevCommand": "pnpm dev", @@ -12,7 +12,7 @@ "app": { "windows": [ { - "title": "瞬影 - 时间记录 v0.2.2", + "title": "瞬影 - 时间记录 v0.2.3", "width": 1760, "height": 1100 } diff --git a/src/App.vue b/src/App.vue index e0e0509..5d7ca7e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -14,7 +14,8 @@ import { retainDays, captureInterval, TIME_OFFSET_MINUTES, TOTAL_MINUTES, getTagColor, getTagName, mainTags, getSubTags, logicalMinutesToTime, logicalMinutesFromTime, formatDuration, - loadTags, loadEvents, loadReminders, toISODate, refreshBadgeCount + loadTags, loadEvents, loadReminders, toISODate, refreshBadgeCount, + calendarStatus, loadCalendarStatus, currentCalendarMonthStr } from "./store"; import { DBEvent, TimelineItem } from "./types"; @@ -90,7 +91,7 @@ const checkReminders = async (currentMin: number) => { for (const r of dueReminders) { if (hasPermission) { - sendNotification({ title: '', body: r.content }); + sendNotification({ title: '瞬影 提醒', body: r.content }); } } } @@ -108,7 +109,7 @@ const updateCurrentMinute = () => { } else { currentLogicalMinute.value = -1; } - // 无论是否看今天,每分钟都尝试刷新全局徽章 + // 无论是否看今天,每分钟都尝试刷新全局徽章和日历状态点 refreshBadgeCount(); }; @@ -126,6 +127,13 @@ const startMinuteTimer = () => { }, msUntilNextMinute); }; +watch(calendarMonth, (newMonth) => { + const y = newMonth.getFullYear(); + const m = String(newMonth.getMonth() + 1).padStart(2, '0'); + currentCalendarMonthStr.value = `${y}-${m}`; + loadCalendarStatus(currentCalendarMonthStr.value); +}, { immediate: true }); + watch(currentDate, () => { updateCurrentMinute(); }); @@ -392,8 +400,23 @@ const togglePause = async () => {
{{d}}
-
- +
+ + +
+
+
+
diff --git a/src/store/index.ts b/src/store/index.ts index 1b41e85..478590f 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -52,6 +52,7 @@ export const lockedImage = ref(null); export const tags = ref([]); export const dayEvents = ref([]); export const reminders = ref([]); +export const calendarStatus = ref>({}); export const timelineImages = ref([]); export const refreshSignal = ref(0); // Counter to trigger dashboard refreshes @@ -114,6 +115,33 @@ export const loadEvents = async () => { export const loadReminders = async () => { reminders.value = await invoke("get_reminders", { date: currentDate.value }); refreshBadgeCount(); + refreshCalendarStatus(); // 提醒更新时也刷新日历状态 +}; + +export const loadCalendarStatus = async (yearMonth: string) => { + if (!dbPath.value) return; + try { + const { date, minute } = getRealNowLogicalTime(); + const statuses: any[] = await invoke("get_reminders_by_month", { + yearMonth, + today: date, + nowMinute: minute + }); + const map: Record = {}; + statuses.forEach(s => { map[s.date] = s; }); + calendarStatus.value = map; + } catch (e) { + console.error("Failed to load calendar status:", e); + } +}; + +// 当前显示的日历月份,用于自动刷新状态 +export const currentCalendarMonthStr = ref(""); + +export const refreshCalendarStatus = () => { + if (currentCalendarMonthStr.value) { + loadCalendarStatus(currentCalendarMonthStr.value); + } }; export const overdueCount = ref(0);