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
+11 -3
View File
@@ -14,6 +14,7 @@ import (
"github.com/yuxingu/digital-psychology/apps/api/internal/rhythm"
"github.com/yuxingu/digital-psychology/apps/api/internal/star"
"github.com/yuxingu/digital-psychology/apps/api/internal/star/synastry"
"github.com/yuxingu/digital-psychology/apps/api/internal/textsafe"
)
// Service creates and reads growth reports with entitlement trimming.
@@ -98,6 +99,10 @@ func (s *Service) AcceptInvite(ctx context.Context, guestUser uuid.UUID, token,
if name == "" {
name = "TA"
}
name, err = textsafe.Check(textsafe.DisplayName, name)
if err != nil {
return nil, err
}
host, err := s.Profiles.GetByID(ctx, inv.HostProfileID)
if err != nil {
return nil, errors.New("host profile missing")
@@ -147,6 +152,7 @@ func (s *Service) CreateStar(ctx context.Context, userID, profileID uuid.UUID) (
}
out, err := star.BuildWith(star.BuildOpts{
Birth: p.BirthDate, BirthTime: p.BirthTime, BirthPlace: p.BirthPlace, Name: p.DisplayName,
AsOf: time.Now().In(time.FixedZone("CST", 8*3600)),
})
if err != nil {
return nil, err
@@ -212,7 +218,7 @@ func (s *Service) CreateRhythm(ctx context.Context, userID, profileID uuid.UUID)
if err != nil {
return nil, errors.New("profile not found")
}
out := rhythm.Build(p.BirthDate, p.DisplayName)
out := rhythm.BuildWith(p.BirthDate, p.DisplayName, time.Now().In(time.FixedZone("CST", 8*3600)))
sum, _ := json.Marshal(out.Summary)
det, _ := json.Marshal(out.Detail)
rep, err := s.Reports.UpsertWithPeer(ctx, userID, profileID, nil, "rhythm", sum, det)
@@ -222,21 +228,23 @@ func (s *Service) CreateRhythm(ctx context.Context, userID, profileID uuid.UUID)
return s.applyEntitlement(ctx, userID, rep)
}
// GetLatest returns cached report by profile+type(+peer).
// GetLatest returns cached report by profile+type(+peer); refreshes star/rhythm day tips.
func (s *Service) GetLatest(ctx context.Context, userID, profileID uuid.UUID, typ string, peer *uuid.UUID) (*model.GrowthReport, error) {
rep, err := s.Reports.GetLatest(ctx, userID, profileID, typ, peer)
if err != nil {
return nil, errors.New("report not found")
}
rep, _ = s.refreshTemporalIfNeeded(ctx, userID, rep)
return s.applyEntitlement(ctx, userID, rep)
}
// Get returns a report with detail gated.
// Get returns a report with detail gated; refreshes star/rhythm day tips.
func (s *Service) Get(ctx context.Context, userID, reportID uuid.UUID) (*model.GrowthReport, error) {
rep, err := s.Reports.GetForUser(ctx, userID, reportID)
if err != nil {
return nil, errors.New("report not found")
}
rep, _ = s.refreshTemporalIfNeeded(ctx, userID, rep)
return s.applyEntitlement(ctx, userID, rep)
}