feat: 每日任务顺延与增删改 + 计划到期续期 + 靠谱养护模板 + 图片URL修复
后端 - 每日任务惰性生成:某天为空则从最近一天顺延复制(done 重置),首天用模板 - 任务增删改 API(POST /pets/:id/tasks、PUT/DELETE /tasks/:id),改动自动顺延 - 30 天计划到期自动归档并按当前阶段生成新一轮 - 内置养护模板重写为兽医常识向:狗每阶段含遛狗/牵引/狂犬,猫含猫砂/梳毛/饮水 - 文件 URL 改为按 object_name + 当前配置动态拼接,换 IP/域名不再有旧地址 小程序 - 首页今日任务加「管理」入口:增删改任务弹层 - 记录时间轴显示照片缩略图(可全屏预览)+ 拍照成功提示 - 社区发布条精简为单个「发布图文」按钮,去掉头像/输入框误触 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -24,14 +24,52 @@ func (s *Service) TogglePlanTask(userID, taskID string) error {
|
||||
return s.db.Model(&model.PlanTask{}).Where("id = ?", taskID).Update("done", !pt.Done).Error
|
||||
}
|
||||
|
||||
// GetPlan 取宠物的 30 天计划(含明细)
|
||||
// newStagePlan 按宠物当前阶段的养护模板生成一份 30 天计划(未保存)
|
||||
func (s *Service) newStagePlan(pet *model.Pet, start time.Time) model.Plan {
|
||||
var planTasks []model.PlanTask
|
||||
for _, it := range s.careTemplateItems(SpeciesOf(pet.Type), pet.Stage) {
|
||||
if it.Kind == model.CareKindPlan {
|
||||
planTasks = append(planTasks, model.PlanTask{
|
||||
Day: it.Day, DayLabel: it.DayLabel, Title: it.Title, Description: it.Description, SheetType: it.SheetType,
|
||||
})
|
||||
}
|
||||
}
|
||||
end := start.AddDate(0, 0, 30)
|
||||
return model.Plan{
|
||||
PetID: pet.ID, UserID: pet.UserID, Kind: model.PlanThirtyDay, Stage: pet.Stage,
|
||||
StartDate: &start, EndDate: &end, CompletionPct: 0, Status: "active", Tasks: planTasks,
|
||||
}
|
||||
}
|
||||
|
||||
// ensurePlan 计划到期自动续期:active 计划过期则归档并按当前阶段生成新一轮;无 active 则补建
|
||||
func (s *Service) ensurePlan(pet *model.Pet) {
|
||||
now := time.Now()
|
||||
var plan model.Plan
|
||||
err := s.db.Where("pet_id = ? AND kind = ? AND status = ?", pet.ID, model.PlanThirtyDay, "active").
|
||||
Order("id desc").First(&plan).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
p := s.newStagePlan(pet, now)
|
||||
s.db.Create(&p)
|
||||
return
|
||||
}
|
||||
if err == nil && plan.EndDate != nil && plan.EndDate.Before(now) {
|
||||
s.db.Model(&model.Plan{}).Where("id = ?", plan.ID).Update("status", "archived")
|
||||
p := s.newStagePlan(pet, now)
|
||||
s.db.Create(&p)
|
||||
}
|
||||
}
|
||||
|
||||
// GetPlan 取宠物的 30 天计划(含明细);过期自动续期
|
||||
func (s *Service) GetPlan(userID, petID string) (*model.Plan, error) {
|
||||
if _, err := s.ownedPet(userID, petID); err != nil {
|
||||
pet, err := s.ownedPet(userID, petID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.ensurePlan(pet)
|
||||
var plan model.Plan
|
||||
err := s.db.Preload("Tasks").
|
||||
err = s.db.Preload("Tasks").
|
||||
Where("pet_id = ? AND kind = ?", petID, model.PlanThirtyDay).
|
||||
Where("status = ?", "active").
|
||||
Order("id desc").First(&plan).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, ErrNotFound
|
||||
|
||||
Reference in New Issue
Block a user