feat: 养护模板/社区运营/体重趋势/计划日历 + 雪花ID重构 + 文件表与图片上传
后端
- 主键改雪花字符串 ID(pkg/idgen + Base.BeforeCreate),全表外键/JWT/中间件随之调整
- 新增 files 表:/api/upload 按 MD5 去重,返回 {id,url,md5},服务端只收图片
- 头像/记录附图/帖子图改 file_id 关联,读取解析为 URL
- 养护模板(物种×阶段)后台可配 + AI 生成草稿;建档按模板生成任务/计划/提醒
- 社区 AI 运营:虚拟账号池 + 每日定时/手动生成,帖子带 AI 标
- 计划路线图节点带真实日期;首页周历与计划日历同源;新增 day-plan 当日安排
- 体重趋势接口带备注;记录列表分页
小程序
- 公共图片上传 utils/upload.js(仅图片);记录拍照/我的头像/社区发图三处接入
- 首页日历点选查当日任务;记录页体重趋势可点看备注 + 时间轴分页折叠
- 计划页日历点选查当日计划;自定义 tabBar 高度调整
后台(React)
- 新增「养护模板」「社区运营」页;用户管理加机器人筛选
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ type HomeInsight struct {
|
||||
type WeekDay struct {
|
||||
Weekday string `json:"weekday"` // 一二三四五六日
|
||||
Day int `json:"day"`
|
||||
Date string `json:"date"` // YYYY-MM-DD,供首页点击查当日任务
|
||||
Active bool `json:"active"` // 是否今天
|
||||
HasDot bool `json:"has_dot"` // 当天有任务/记录/提醒
|
||||
}
|
||||
@@ -36,7 +37,7 @@ type HomeSummary struct {
|
||||
var weekdayCN = []string{"日", "一", "二", "三", "四", "五", "六"}
|
||||
|
||||
// GetHomeSummary 计算首页汇总
|
||||
func (s *Service) GetHomeSummary(userID, petID uint) (*HomeSummary, error) {
|
||||
func (s *Service) GetHomeSummary(userID, petID string) (*HomeSummary, error) {
|
||||
pet, err := s.ownedPet(userID, petID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -54,7 +55,7 @@ func (s *Service) GetHomeSummary(userID, petID uint) (*HomeSummary, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Service) userNickname(userID uint) string {
|
||||
func (s *Service) userNickname(userID string) string {
|
||||
var u model.User
|
||||
if err := s.db.Select("nickname").First(&u, userID).Error; err == nil && u.Nickname != "" {
|
||||
return u.Nickname
|
||||
@@ -76,7 +77,7 @@ func greeting(t time.Time, name string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) homeInsights(petID uint, now time.Time) []HomeInsight {
|
||||
func (s *Service) homeInsights(petID string, now time.Time) []HomeInsight {
|
||||
insights := make([]HomeInsight, 0, 3)
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
|
||||
@@ -112,7 +113,7 @@ func (s *Service) homeInsights(petID uint, now time.Time) []HomeInsight {
|
||||
}
|
||||
|
||||
// streakDays 从今天往前,连续有健康记录的天数
|
||||
func (s *Service) streakDays(petID uint, now time.Time) int {
|
||||
func (s *Service) streakDays(petID string, now time.Time) int {
|
||||
streak := 0
|
||||
day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
for i := 0; i < 60; i++ {
|
||||
@@ -129,7 +130,7 @@ func (s *Service) streakDays(petID uint, now time.Time) int {
|
||||
return streak
|
||||
}
|
||||
|
||||
func (s *Service) homeWeek(petID uint, now time.Time) []WeekDay {
|
||||
func (s *Service) homeWeek(petID string, now time.Time) []WeekDay {
|
||||
// 本周一为起点
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
offset := (int(today.Weekday()) + 6) % 7 // 周一=0
|
||||
@@ -143,6 +144,7 @@ func (s *Service) homeWeek(petID uint, now time.Time) []WeekDay {
|
||||
week[i] = WeekDay{
|
||||
Weekday: weekdayCN[int(d.Weekday())],
|
||||
Day: d.Day(),
|
||||
Date: d.Format("2006-01-02"),
|
||||
Active: d.Equal(today),
|
||||
HasDot: dotSet[d.Format("2006-01-02")],
|
||||
}
|
||||
@@ -151,7 +153,7 @@ func (s *Service) homeWeek(petID uint, now time.Time) []WeekDay {
|
||||
}
|
||||
|
||||
// datesWithActivity 区间内有任务/记录/提醒的日期集合
|
||||
func (s *Service) datesWithActivity(petID uint, start, end time.Time) map[string]bool {
|
||||
func (s *Service) datesWithActivity(petID string, start, end time.Time) map[string]bool {
|
||||
set := map[string]bool{}
|
||||
var ts []time.Time
|
||||
s.db.Model(&model.DailyTask{}).Where("pet_id = ? AND task_date >= ? AND task_date < ?", petID, start, end).Pluck("task_date", &ts)
|
||||
@@ -170,10 +172,14 @@ func (s *Service) datesWithActivity(petID uint, start, end time.Time) map[string
|
||||
set[r.NextDueDate.Format("2006-01-02")] = true
|
||||
}
|
||||
}
|
||||
// 30 天计划路线图节点也算「有活动」,让首页周历与计划日历一致
|
||||
for _, d := range s.planNodeDates(petID, start, end) {
|
||||
set[d.Format("2006-01-02")] = true
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (s *Service) todayCompletionPct(petID uint, now time.Time) int {
|
||||
func (s *Service) todayCompletionPct(petID string, now time.Time) int {
|
||||
start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
end := start.AddDate(0, 0, 1)
|
||||
var total, done int64
|
||||
@@ -214,7 +220,7 @@ type UserSummary struct {
|
||||
}
|
||||
|
||||
// GetUserSummary 汇总当前用户名下计数
|
||||
func (s *Service) GetUserSummary(userID uint) (*UserSummary, error) {
|
||||
func (s *Service) GetUserSummary(userID string) (*UserSummary, error) {
|
||||
var sum UserSummary
|
||||
s.db.Model(&model.Pet{}).Where("user_id = ?", userID).Count(&sum.Pets)
|
||||
s.db.Model(&model.HealthRecord{}).Where("user_id = ?", userID).Count(&sum.Records)
|
||||
|
||||
Reference in New Issue
Block a user