完善活动运营域与联调标准化

This commit is contained in:
2026-04-03 13:11:41 +08:00
parent 0e28f70bad
commit 129ea935db
56 changed files with 11004 additions and 196 deletions

View File

@@ -58,10 +58,13 @@ type EventConfigBuildView struct {
}
type PublishedReleaseView struct {
EventID string `json:"eventId"`
Release ResolvedReleaseView `json:"release"`
ReleaseNo int `json:"releaseNo"`
PublishedAt string `json:"publishedAt"`
EventID string `json:"eventId"`
Release ResolvedReleaseView `json:"release"`
ReleaseNo int `json:"releaseNo"`
PublishedAt string `json:"publishedAt"`
Runtime *RuntimeSummaryView `json:"runtime,omitempty"`
Presentation *PresentationSummaryView `json:"presentation,omitempty"`
ContentBundle *ContentBundleSummaryView `json:"contentBundle,omitempty"`
}
type ImportLocalEventConfigInput struct {
@@ -75,7 +78,10 @@ type BuildPreviewInput struct {
}
type PublishBuildInput struct {
BuildID string `json:"buildId"`
BuildID string `json:"buildId"`
RuntimeBindingID string `json:"runtimeBindingId,omitempty"`
PresentationID string `json:"presentationId,omitempty"`
ContentBundleID string `json:"contentBundleId,omitempty"`
}
func NewConfigService(store *postgres.Store, localEventDir, assetBaseURL string, publisher *assets.OSSUtilPublisher) *ConfigService {
@@ -306,6 +312,19 @@ func (s *ConfigService) PublishBuild(ctx context.Context, input PublishBuildInpu
return nil, apperr.New(http.StatusNotFound, "event_not_found", "event not found")
}
runtimeBindingID, runtimeSummary, err := s.resolvePublishRuntimeBinding(ctx, event.ID, input.RuntimeBindingID)
if err != nil {
return nil, err
}
presentationID, presentationSummary, err := s.resolvePublishPresentation(ctx, event.ID, input.PresentationID)
if err != nil {
return nil, err
}
contentBundleID, contentBundleSummary, err := s.resolvePublishContentBundle(ctx, event.ID, input.ContentBundleID)
if err != nil {
return nil, err
}
manifest, err := decodeJSONObject(buildRecord.ManifestJSON)
if err != nil {
return nil, apperr.New(http.StatusInternalServerError, "config_build_invalid", "stored build manifest is invalid")
@@ -355,6 +374,9 @@ func (s *ConfigService) PublishBuild(ctx context.Context, input PublishBuildInpu
ManifestChecksum: &checksum,
RouteCode: routeCode,
BuildID: &buildRecord.ID,
RuntimeBindingID: runtimeBindingID,
PresentationID: presentationID,
ContentBundleID: contentBundleID,
Status: "published",
PayloadJSON: buildRecord.ManifestJSON,
})
@@ -386,11 +408,160 @@ func (s *ConfigService) PublishBuild(ctx context.Context, input PublishBuildInpu
ManifestChecksumSha256: releaseRecord.ManifestChecksum,
RouteCode: releaseRecord.RouteCode,
},
ReleaseNo: releaseRecord.ReleaseNo,
PublishedAt: releaseRecord.PublishedAt.Format(timeRFC3339),
ReleaseNo: releaseRecord.ReleaseNo,
PublishedAt: releaseRecord.PublishedAt.Format(timeRFC3339),
Runtime: runtimeSummary,
Presentation: presentationSummary,
ContentBundle: contentBundleSummary,
}, nil
}
func (s *ConfigService) resolvePublishRuntimeBinding(ctx context.Context, eventID string, runtimeBindingPublicID string) (*string, *RuntimeSummaryView, error) {
runtimeBindingPublicID = strings.TrimSpace(runtimeBindingPublicID)
if runtimeBindingPublicID == "" {
defaults, err := s.store.GetEventDefaultBindingsByEventID(ctx, eventID)
if err != nil {
return nil, nil, err
}
if defaults == nil || defaults.RuntimeBindingID == nil || defaults.RuntimeBindingPublicID == nil || defaults.PlacePublicID == nil || defaults.MapAssetPublicID == nil || defaults.TileReleasePublicID == nil || defaults.CourseSetPublicID == nil || defaults.CourseVariantPublicID == nil {
return nil, nil, nil
}
return defaults.RuntimeBindingID, &RuntimeSummaryView{
RuntimeBindingID: *defaults.RuntimeBindingPublicID,
PlaceID: *defaults.PlacePublicID,
PlaceName: defaults.PlaceName,
MapID: *defaults.MapAssetPublicID,
MapName: defaults.MapAssetName,
TileReleaseID: *defaults.TileReleasePublicID,
CourseSetID: *defaults.CourseSetPublicID,
CourseVariantID: *defaults.CourseVariantPublicID,
CourseVariantName: defaults.CourseVariantName,
RouteCode: defaults.RuntimeRouteCode,
}, nil
}
runtimeBinding, err := s.store.GetMapRuntimeBindingByPublicID(ctx, runtimeBindingPublicID)
if err != nil {
return nil, nil, err
}
if runtimeBinding == nil {
return nil, nil, apperr.New(http.StatusNotFound, "runtime_binding_not_found", "runtime binding not found")
}
if runtimeBinding.EventID != eventID {
return nil, nil, apperr.New(http.StatusConflict, "runtime_binding_not_belong_to_event", "runtime binding does not belong to build event")
}
return &runtimeBinding.ID, &RuntimeSummaryView{
RuntimeBindingID: runtimeBinding.PublicID,
PlaceID: runtimeBinding.PlacePublicID,
MapID: runtimeBinding.MapAssetPublicID,
TileReleaseID: runtimeBinding.TileReleasePublicID,
CourseSetID: runtimeBinding.CourseSetPublicID,
CourseVariantID: runtimeBinding.CourseVariantPublicID,
RouteCode: nil,
}, nil
}
func (s *ConfigService) resolvePublishPresentation(ctx context.Context, eventID string, presentationPublicID string) (*string, *PresentationSummaryView, error) {
presentationPublicID = strings.TrimSpace(presentationPublicID)
if presentationPublicID == "" {
defaults, err := s.store.GetEventDefaultBindingsByEventID(ctx, eventID)
if err != nil {
return nil, nil, err
}
if defaults != nil && defaults.PresentationID != nil && defaults.PresentationPublicID != nil {
record, err := s.store.GetEventPresentationByPublicID(ctx, *defaults.PresentationPublicID)
if err != nil {
return nil, nil, err
}
if record != nil {
summary, err := buildPresentationSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return defaults.PresentationID, summary, nil
}
}
record, err := s.store.GetDefaultEventPresentationByEventID(ctx, eventID)
if err != nil {
return nil, nil, err
}
if record == nil {
return nil, nil, nil
}
summary, err := buildPresentationSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return &record.ID, summary, nil
}
record, err := s.store.GetEventPresentationByPublicID(ctx, presentationPublicID)
if err != nil {
return nil, nil, err
}
if record == nil {
return nil, nil, apperr.New(http.StatusNotFound, "presentation_not_found", "presentation not found")
}
if record.EventID != eventID {
return nil, nil, apperr.New(http.StatusConflict, "presentation_not_belong_to_event", "presentation does not belong to build event")
}
summary, err := buildPresentationSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return &record.ID, summary, nil
}
func (s *ConfigService) resolvePublishContentBundle(ctx context.Context, eventID string, contentBundlePublicID string) (*string, *ContentBundleSummaryView, error) {
contentBundlePublicID = strings.TrimSpace(contentBundlePublicID)
if contentBundlePublicID == "" {
defaults, err := s.store.GetEventDefaultBindingsByEventID(ctx, eventID)
if err != nil {
return nil, nil, err
}
if defaults != nil && defaults.ContentBundleID != nil && defaults.ContentBundlePublicID != nil {
record, err := s.store.GetContentBundleByPublicID(ctx, *defaults.ContentBundlePublicID)
if err != nil {
return nil, nil, err
}
if record != nil {
summary, err := buildContentBundleSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return defaults.ContentBundleID, summary, nil
}
}
record, err := s.store.GetDefaultContentBundleByEventID(ctx, eventID)
if err != nil {
return nil, nil, err
}
if record == nil {
return nil, nil, nil
}
summary, err := buildContentBundleSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return &record.ID, summary, nil
}
record, err := s.store.GetContentBundleByPublicID(ctx, contentBundlePublicID)
if err != nil {
return nil, nil, err
}
if record == nil {
return nil, nil, apperr.New(http.StatusNotFound, "content_bundle_not_found", "content bundle not found")
}
if record.EventID != eventID {
return nil, nil, apperr.New(http.StatusConflict, "content_bundle_not_belong_to_event", "content bundle does not belong to build event")
}
summary, err := buildContentBundleSummaryFromRecord(record)
if err != nil {
return nil, nil, err
}
return &record.ID, summary, nil
}
func (s *ConfigService) requireEvent(ctx context.Context, eventPublicID string) (*postgres.Event, error) {
eventPublicID = strings.TrimSpace(eventPublicID)
if eventPublicID == "" {