/* todo.go - 待办事项数据结构 定义了任务的基本数据结构和相关方法 */ package todo import ( "fmt" "strings" "time" ) // Priority 任务优先级 type Priority int const ( Low Priority = iota Medium High Urgent ) // String 返回优先级的字符串表示 func (p Priority) String() string { switch p { case Low: return "低" case Medium: return "中" case High: return "高" case Urgent: return "紧急" default: return "未知" } } // Task 表示一个待办事项 type Task struct { ID int `json:"id"` // 任务ID Content string `json:"content"` // 任务内容 Completed bool `json:"completed"` // 是否完成 Priority Priority `json:"priority"` // 优先级 CreatedAt time.Time `json:"created_at"` // 创建时间 UpdatedAt time.Time `json:"updated_at"` // 更新时间 CompletedAt *time.Time `json:"completed_at,omitempty"` // 完成时间 Tags []string `json:"tags,omitempty"` // 标签 Description string `json:"description,omitempty"` // 详细描述 } // NewTask 创建新的任务 func NewTask(id int, content string) *Task { now := time.Now() return &Task{ ID: id, Content: content, Completed: false, Priority: Medium, CreatedAt: now, UpdatedAt: now, Tags: make([]string, 0), } } // Complete 标记任务为完成 func (t *Task) Complete() { if !t.Completed { t.Completed = true now := time.Now() t.CompletedAt = &now t.UpdatedAt = now } } // Uncomplete 标记任务为未完成 func (t *Task) Uncomplete() { if t.Completed { t.Completed = false t.CompletedAt = nil t.UpdatedAt = time.Now() } } // Update 更新任务内容 func (t *Task) Update(content string) { if content != "" && content != t.Content { t.Content = content t.UpdatedAt = time.Now() } } // SetPriority 设置任务优先级 func (t *Task) SetPriority(priority Priority) { if priority != t.Priority { t.Priority = priority t.UpdatedAt = time.Now() } } // AddTag 添加标签 func (t *Task) AddTag(tag string) { if tag == "" { return } // 检查标签是否已存在 for _, existingTag := range t.Tags { if existingTag == tag { return } } t.Tags = append(t.Tags, tag) t.UpdatedAt = time.Now() } // RemoveTag 移除标签 func (t *Task) RemoveTag(tag string) { for i, existingTag := range t.Tags { if existingTag == tag { t.Tags = append(t.Tags[:i], t.Tags[i+1:]...) t.UpdatedAt = time.Now() break } } } // HasTag 检查是否包含指定标签 func (t *Task) HasTag(tag string) bool { for _, existingTag := range t.Tags { if existingTag == tag { return true } } return false } // SetDescription 设置任务描述 func (t *Task) SetDescription(description string) { if description != t.Description { t.Description = description t.UpdatedAt = time.Now() } } // String 返回任务的字符串表示 func (t *Task) String() string { status := "⏳" if t.Completed { status = "✅" } return fmt.Sprintf("[%d] %s %s (优先级: %s)", t.ID, status, t.Content, t.Priority) } // DetailedString 返回任务的详细字符串表示 func (t *Task) DetailedString() string { status := "待完成" if t.Completed { status = "已完成" } result := fmt.Sprintf("任务 #%d\n", t.ID) result += fmt.Sprintf("内容: %s\n", t.Content) result += fmt.Sprintf("状态: %s\n", status) result += fmt.Sprintf("优先级: %s\n", t.Priority) result += fmt.Sprintf("创建时间: %s\n", t.CreatedAt.Format("2006-01-02 15:04:05")) result += fmt.Sprintf("更新时间: %s\n", t.UpdatedAt.Format("2006-01-02 15:04:05")) if t.Completed && t.CompletedAt != nil { result += fmt.Sprintf("完成时间: %s\n", t.CompletedAt.Format("2006-01-02 15:04:05")) } if t.Description != "" { result += fmt.Sprintf("描述: %s\n", t.Description) } if len(t.Tags) > 0 { result += fmt.Sprintf("标签: %v\n", t.Tags) } return result } // IsOverdue 检查任务是否过期(如果有截止日期的话) func (t *Task) IsOverdue() bool { // 这里可以扩展添加截止日期功能 return false } // Age 返回任务的存在时间 func (t *Task) Age() time.Duration { return time.Since(t.CreatedAt) } // CompletionTime 返回任务的完成耗时 func (t *Task) CompletionTime() time.Duration { if !t.Completed || t.CompletedAt == nil { return 0 } return t.CompletedAt.Sub(t.CreatedAt) } // Clone 创建任务的副本 func (t *Task) Clone() *Task { clone := *t // 深拷贝切片 if len(t.Tags) > 0 { clone.Tags = make([]string, len(t.Tags)) copy(clone.Tags, t.Tags) } // 深拷贝时间指针 if t.CompletedAt != nil { completedAt := *t.CompletedAt clone.CompletedAt = &completedAt } return &clone } // Validate 验证任务数据的有效性 func (t *Task) Validate() error { if t.ID <= 0 { return fmt.Errorf("任务ID必须大于0") } if t.Content == "" { return fmt.Errorf("任务内容不能为空") } if t.Priority < Low || t.Priority > Urgent { return fmt.Errorf("无效的优先级") } if t.CreatedAt.IsZero() { return fmt.Errorf("创建时间不能为空") } if t.UpdatedAt.IsZero() { return fmt.Errorf("更新时间不能为空") } if t.Completed && t.CompletedAt == nil { return fmt.Errorf("已完成的任务必须有完成时间") } if !t.Completed && t.CompletedAt != nil { return fmt.Errorf("未完成的任务不应该有完成时间") } return nil } // TaskList 任务列表类型 type TaskList []Task // Len 返回任务列表长度 func (tl TaskList) Len() int { return len(tl) } // Less 比较两个任务的顺序(用于排序) func (tl TaskList) Less(i, j int) bool { // 首先按完成状态排序(未完成的在前) if tl[i].Completed != tl[j].Completed { return !tl[i].Completed } // 然后按优先级排序(高优先级在前) if tl[i].Priority != tl[j].Priority { return tl[i].Priority > tl[j].Priority } // 最后按创建时间排序(新创建的在前) return tl[i].CreatedAt.After(tl[j].CreatedAt) } // Swap 交换两个任务的位置 func (tl TaskList) Swap(i, j int) { tl[i], tl[j] = tl[j], tl[i] } // Filter 过滤任务列表 func (tl TaskList) Filter(predicate func(Task) bool) TaskList { var filtered TaskList for _, task := range tl { if predicate(task) { filtered = append(filtered, task) } } return filtered } // FindByID 根据ID查找任务 func (tl TaskList) FindByID(id int) (*Task, bool) { for i, task := range tl { if task.ID == id { return &tl[i], true } } return nil, false } // GetCompleted 获取已完成的任务 func (tl TaskList) GetCompleted() TaskList { return tl.Filter(func(t Task) bool { return t.Completed }) } // GetPending 获取待完成的任务 func (tl TaskList) GetPending() TaskList { return tl.Filter(func(t Task) bool { return !t.Completed }) } // GetByPriority 根据优先级获取任务 func (tl TaskList) GetByPriority(priority Priority) TaskList { return tl.Filter(func(t Task) bool { return t.Priority == priority }) } // Search 搜索包含关键词的任务 func (tl TaskList) Search(keyword string) TaskList { return tl.Filter(func(t Task) bool { return contains(t.Content, keyword) || contains(t.Description, keyword) || containsInTags(t.Tags, keyword) }) } // contains 检查字符串是否包含子字符串(忽略大小写) func contains(s, substr string) bool { if substr == "" { return true } return len(s) >= len(substr) && strings.Contains(strings.ToLower(s), strings.ToLower(substr)) } // containsInTags 检查标签列表是否包含关键词 func containsInTags(tags []string, keyword string) bool { for _, tag := range tags { if contains(tag, keyword) { return true } } return false }