package store import ( "database/sql" "fmt" "log" "time" ) // Reminder 提醒模型 type Reminder struct { ID string `json:"id"` UserID string `json:"user_id"` Title string `json:"title"` Description string `json:"description"` RemindAt time.Time `json:"remind_at"` Status string `json:"status"` // pending, completed, cancelled CreatedAt time.Time `json:"created_at"` CompletedAt *time.Time `json:"completed_at,omitempty"` RepeatType string `json:"repeat_type"` // none, daily, weekly, monthly SessionID string `json:"session_id"` Notified bool `json:"notified"` } // ReminderStore 提醒持久化存储 type ReminderStore struct { db *sql.DB } // NewReminderStore 使用已有数据库连接初始化提醒存储并自动建表 func NewReminderStore(db *sql.DB) (*ReminderStore, error) { store := &ReminderStore{db: db} if err := store.migrate(); err != nil { return nil, fmt.Errorf("提醒表迁移失败: %w", err) } log.Println("[ReminderStore] 提醒持久化存储已初始化") return store, nil } // migrate 自动创建提醒表结构 func (s *ReminderStore) migrate() error { queries := []string{ `CREATE TABLE IF NOT EXISTS reminders ( id VARCHAR(36) PRIMARY KEY, user_id VARCHAR(255) NOT NULL, title VARCHAR(500) NOT NULL, description TEXT DEFAULT '', remind_at TIMESTAMPTZ NOT NULL, status VARCHAR(20) DEFAULT 'pending', created_at TIMESTAMPTZ DEFAULT NOW(), completed_at TIMESTAMPTZ, repeat_type VARCHAR(20) DEFAULT '', session_id VARCHAR(36) DEFAULT '', notified BOOLEAN DEFAULT FALSE )`, `CREATE INDEX IF NOT EXISTS idx_reminders_user_id ON reminders(user_id)`, `CREATE INDEX IF NOT EXISTS idx_reminders_remind_at ON reminders(remind_at)`, `CREATE INDEX IF NOT EXISTS idx_reminders_status ON reminders(status)`, `CREATE INDEX IF NOT EXISTS idx_reminders_due ON reminders(remind_at, status, notified)`, } for _, q := range queries { if _, err := s.db.Exec(q); err != nil { return fmt.Errorf("迁移SQL执行失败: %w\nSQL: %s", err, q) } } return nil } // CreateReminder 创建新提醒 func (s *ReminderStore) CreateReminder(r *Reminder) error { _, err := s.db.Exec( `INSERT INTO reminders (id, user_id, title, description, remind_at, status, repeat_type, session_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, r.ID, r.UserID, r.Title, r.Description, r.RemindAt, r.Status, r.RepeatType, r.SessionID, ) if err != nil { return fmt.Errorf("创建提醒失败: %w", err) } return nil } // GetRemindersByUser 获取用户的提醒列表(可按状态筛选,按 remind_at 升序) func (s *ReminderStore) GetRemindersByUser(userID, status string, limit, offset int) ([]Reminder, error) { if limit <= 0 { limit = 50 } if offset < 0 { offset = 0 } var rows *sql.Rows var err error if status != "" { rows, err = s.db.Query( `SELECT id, user_id, title, description, remind_at, status, created_at, completed_at, repeat_type, session_id, notified FROM reminders WHERE user_id = $1 AND status = $2 ORDER BY remind_at ASC LIMIT $3 OFFSET $4`, userID, status, limit, offset, ) } else { rows, err = s.db.Query( `SELECT id, user_id, title, description, remind_at, status, created_at, completed_at, repeat_type, session_id, notified FROM reminders WHERE user_id = $1 ORDER BY remind_at ASC LIMIT $2 OFFSET $3`, userID, limit, offset, ) } if err != nil { return nil, fmt.Errorf("查询提醒列表失败: %w", err) } defer rows.Close() var reminders []Reminder for rows.Next() { var r Reminder if err := rows.Scan(&r.ID, &r.UserID, &r.Title, &r.Description, &r.RemindAt, &r.Status, &r.CreatedAt, &r.CompletedAt, &r.RepeatType, &r.SessionID, &r.Notified); err != nil { return nil, fmt.Errorf("扫描提醒行失败: %w", err) } reminders = append(reminders, r) } if reminders == nil { reminders = []Reminder{} } return reminders, rows.Err() } // GetDueReminders 获取所有到期且未通知的提醒 func (s *ReminderStore) GetDueReminders() ([]Reminder, error) { rows, err := s.db.Query( `SELECT id, user_id, title, description, remind_at, status, created_at, completed_at, repeat_type, session_id, notified FROM reminders WHERE remind_at <= NOW() AND status = 'pending' AND notified = FALSE ORDER BY remind_at ASC`, ) if err != nil { return nil, fmt.Errorf("查询到期提醒失败: %w", err) } defer rows.Close() var reminders []Reminder for rows.Next() { var r Reminder if err := rows.Scan(&r.ID, &r.UserID, &r.Title, &r.Description, &r.RemindAt, &r.Status, &r.CreatedAt, &r.CompletedAt, &r.RepeatType, &r.SessionID, &r.Notified); err != nil { return nil, fmt.Errorf("扫描到期提醒行失败: %w", err) } reminders = append(reminders, r) } if reminders == nil { reminders = []Reminder{} } return reminders, rows.Err() } // MarkNotified 标记提醒为已通知 func (s *ReminderStore) MarkNotified(id string) error { _, err := s.db.Exec( `UPDATE reminders SET notified = TRUE WHERE id = $1`, id, ) if err != nil { return fmt.Errorf("标记提醒已通知失败: %w", err) } return nil } // UpdateReminder 更新提醒字段 func (s *ReminderStore) UpdateReminder(id string, r *Reminder) error { _, err := s.db.Exec( `UPDATE reminders SET title = $1, description = $2, remind_at = $3, status = $4, completed_at = $5, repeat_type = $6, session_id = $7, notified = $8 WHERE id = $9`, r.Title, r.Description, r.RemindAt, r.Status, r.CompletedAt, r.RepeatType, r.SessionID, r.Notified, id, ) if err != nil { return fmt.Errorf("更新提醒失败: %w", err) } return nil } // DeleteReminder 删除提醒 func (s *ReminderStore) DeleteReminder(id string) error { _, err := s.db.Exec(`DELETE FROM reminders WHERE id = $1`, id) if err != nil { return fmt.Errorf("删除提醒失败: %w", err) } return nil }