feat(ECR-012–016): 合规、题库、时辰刷新、头像、MBTI OEJTS 与埋点

落地输入合规、探索题库、报告日/时辰刷新、账号头像、OEJTS 量表,并补齐 H5 埋点与 Admin 漏斗;同步 ESS 工件、切至自建 Git、清理 GitHub Actions。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-13 01:27:58 +08:00
co-authored by Cursor
parent 13860bf1ef
commit 89756f65b4
227 changed files with 7405 additions and 1407 deletions
+38 -11
View File
@@ -4,6 +4,9 @@ package rhythm
import (
"fmt"
"time"
"github.com/yuxingu/digital-psychology/apps/api/internal/companion"
"github.com/yuxingu/digital-psychology/apps/api/internal/portrait"
)
// Output free summary + gated detail.
@@ -14,8 +17,13 @@ type Output struct {
var elements = []string{"木", "火", "土", "金", "水"}
// Build from birth date.
// Build from birth date (asOf = now).
func Build(birth time.Time, displayName string) Output {
return BuildWith(birth, displayName, time.Time{})
}
// BuildWith anchors today/week tips to asOf (zero = now CST).
func BuildWith(birth time.Time, displayName string, asOf time.Time) Output {
name := displayName
if name == "" {
name = "你"
@@ -36,9 +44,20 @@ func Build(birth time.Time, displayName string) Output {
{"key": "mood", "title": "情绪调节", "teaser": tip.Mood, "score": 71},
}
todayTip := tip.Sleep
weekday := int(time.Now().Weekday())
when := asOf
if when.IsZero() {
when = time.Now().In(time.FixedZone("CST", 8*3600))
} else {
when = when.In(time.FixedZone("CST", 8*3600))
}
todayTips := []string{tip.Sleep, tip.Diet, tip.Move, tip.Mood}
todayTip := todayTips[when.YearDay()%len(todayTips)]
weekday := int(when.Weekday())
weekHints := []string{tip.Mood, tip.Move, tip.Diet, tip.Sleep, tip.WeekTip, tip.Move, tip.Mood}
dayKey := when.Format("2006-01-02")
validUntil := time.Date(when.Year(), when.Month(), when.Day()+1, 0, 0, 0, 0, when.Location())
wx := portrait.WuxingBlock(birth)
st := companion.TodaySolar(when)
summary := map[string]any{
"title": "身心节律·基础",
"style_label": primary + "倾向",
@@ -48,12 +67,20 @@ func Build(birth time.Time, displayName string) Output {
"life_tip": tip.WeekTip,
"today_tip": todayTip,
"week_focus": weekHints[weekday%len(weekHints)],
"keywords": []string{primary, secondary, "生活建议", "节律"},
"dimensions": dims,
"primary_element": primary,
"secondary_element": secondary,
"strengths_preview": tip.Strengths[:min(3, len(tip.Strengths))],
"blind_spots_preview": []string{"完整习惯方案见深度版。"},
"as_of": dayKey,
"valid_until": validUntil.Format(time.RFC3339),
"wuxing": wx,
"solar_term": map[string]any{
"name": st.Name,
"tip": st.Tip,
},
"keywords": []string{primary, secondary, "生活建议", "节律"},
"dimensions": dims,
"primary_element": primary,
"secondary_element": secondary,
"strengths_preview": tip.Strengths[:min(3, len(tip.Strengths))],
"blind_spots_preview": tip.BlindSpots[:min(3, len(tip.BlindSpots))],
"disclaimer_constitution": "体质与调养内容为生活方式参考,非医疗建议。",
}
detail := map[string]any{
@@ -65,8 +92,8 @@ func Build(birth time.Time, displayName string) Output {
{"title": "活动与放松", "body": tip.MoveDeep, "bullets": tip.MoveBullets},
{"title": "情绪与压力", "body": tip.MoodDeep, "bullets": tip.MoodBullets},
{"title": "与节气联动", "body": "可结合「节气生活」调整当季节奏;变化慢一点,观察身体反馈即可。", "bullets": []string{"查看今日节气", "一次只改一个习惯", "不适就医,勿自行当治疗"}},
{"title": "今日生活建议", "body": tip.Sleep + " " + tip.Mood, "bullets": []string{tip.Move, tip.Diet}},
{"title": "本周节奏", "body": tip.WeekTip, "bullets": tip.OverviewBullets},
{"title": "今日生活建议", "body": todayTip + " " + tip.Mood, "bullets": []string{tip.Move, tip.Diet}},
{"title": "本周节奏", "body": weekHints[weekday%len(weekHints)], "bullets": tip.OverviewBullets},
},
"strengths": tip.Strengths,
"blind_spots": tip.BlindSpots,