feat: reorganize project task planning UI

This commit is contained in:
2026-07-21 01:00:27 +08:00
parent c613d4c997
commit d6395d3c64
13 changed files with 251 additions and 171 deletions

View File

@@ -54,14 +54,16 @@ type InboxMessage struct {
}
type WorkTask struct {
ID string `json:"id"`
Title string `json:"title"`
Summary string `json:"summary"`
Completed bool `json:"completed"`
Owner string `json:"owner"`
Due string `json:"due"`
CreatedAt string `json:"createdAt"`
Tag string `json:"tag"`
ID string `json:"id"`
Title string `json:"title"`
Summary string `json:"summary"`
Completed bool `json:"completed"`
Owner string `json:"owner"`
Due string `json:"due"`
CreatedAt string `json:"createdAt"`
CompletedAt string `json:"completedAt"`
Duration string `json:"duration"`
Tag string `json:"tag"`
}
type AISessionItem struct {
@@ -550,15 +552,24 @@ func (s *Service) workspaceTasks(projectID uint) ([]WorkTask, error) {
if err != nil {
return nil, err
}
completed := task.Status == "done"
completedAt := ""
duration := ""
if completed {
completedAt = displayTime(task.UpdatedAt)
duration = displayDuration(task.CreatedAt, task.UpdatedAt)
}
items = append(items, WorkTask{
ID: fmt.Sprint(task.ID),
Title: task.Title,
Summary: task.Description,
Completed: task.Status == "done",
Owner: owner,
Due: displayOptionalTime(task.DueAt),
CreatedAt: displayTime(task.CreatedAt),
Tag: tagNames[task.ID],
ID: fmt.Sprint(task.ID),
Title: task.Title,
Summary: task.Description,
Completed: completed,
Owner: owner,
Due: displayOptionalTime(task.DueAt),
CreatedAt: displayTime(task.CreatedAt),
CompletedAt: completedAt,
Duration: duration,
Tag: tagNames[task.ID],
})
}
return items, nil
@@ -740,6 +751,26 @@ func displayOptionalTime(value *time.Time) string {
return displayTime(*value)
}
func displayDuration(start time.Time, end time.Time) string {
if start.IsZero() || end.IsZero() || end.Before(start) {
return ""
}
duration := end.Sub(start)
days := int(duration.Hours()) / 24
if days > 0 {
return fmt.Sprintf("%d 天", days)
}
hours := int(duration.Hours())
if hours > 0 {
return fmt.Sprintf("%d 小时", hours)
}
minutes := int(duration.Minutes())
if minutes > 0 {
return fmt.Sprintf("%d 分钟", minutes)
}
return "1 分钟内"
}
func sourceDisplayName(source models.SenlinAgentSource) string {
switch source.Kind {
case "file":