feat(enterprise-site): add PbootCMS enterprise site publisher
Introduce a new enterprise-site publishing channel that lets tenants push articles to self-hosted PbootCMS sites alongside the existing media supply flow. Backend (server/internal/tenant): - enterprise_site_service: CRUD, ping, category sync, and article publish - enterprise_site_pbootcms: PbootCMS API client integration - enterprise_site_crypto: encrypt/decrypt stored site credentials - enterprise_site_handler + routes under /enterprise-sites - migrations for the enterprise site publisher tables - config: add SERVER_PUBLIC_BASE_URL (Server.PublicBaseURL) for callbacks - article/media services adjusted to support the publish flow Frontend (apps/admin-web): - PublishArticleModal & ArticlePublishStatus: enterprise-site publish UI - MediaView: manage enterprise sites and categories - api + shared-types: enterprise site endpoints and types - http-client: add PATCH method support Integrations: - pbootcms GeoPublisher controller plugin + install guide - docs/enterprise-site-publisher-v1.md design doc
This commit is contained in:
@@ -38,8 +38,10 @@ type PublishRecordResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
PublishBatchID int64 `json:"publish_batch_id"`
|
||||
ArticleID int64 `json:"article_id"`
|
||||
PlatformAccountID int64 `json:"platform_account_id"`
|
||||
PlatformAccountID *int64 `json:"platform_account_id"`
|
||||
DesktopAccountID *string `json:"desktop_account_id"`
|
||||
TargetType string `json:"target_type"`
|
||||
TargetConnectionID *int64 `json:"target_connection_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformName string `json:"platform_name"`
|
||||
PlatformNickname string `json:"platform_nickname"`
|
||||
@@ -98,12 +100,22 @@ func (s *MediaService) ListArticlePublishRecords(ctx context.Context, articleID
|
||||
|
||||
func (s *MediaService) listArticlePublishRecords(ctx context.Context, tenantID, brandID, articleID int64) ([]PublishRecordResponse, error) {
|
||||
rows, err := s.pool.Query(ctx, `
|
||||
SELECT pr.id, pr.publish_batch_id, pr.article_id, pr.platform_account_id, pa.desktop_id::text, pr.platform_id,
|
||||
mp.name, pa.nickname, pr.status, pr.external_article_id, pr.external_article_url,
|
||||
SELECT pr.id, pr.publish_batch_id, pr.article_id, pr.platform_account_id, pa.desktop_id::text,
|
||||
COALESCE(pr.target_type, 'platform_account'), pr.target_connection_id, pr.platform_id,
|
||||
COALESCE(mp.name, esc.site_name, esc.name, pr.platform_id) AS platform_name,
|
||||
CASE
|
||||
WHEN COALESCE(pr.target_type, 'platform_account') = 'enterprise_site'
|
||||
THEN COALESCE(esc.site_name, esc.name, '企业站点')
|
||||
ELSE COALESCE(pa.nickname, '')
|
||||
END AS platform_nickname,
|
||||
pr.status, pr.external_article_id, pr.external_article_url,
|
||||
pr.external_manage_url, pr.published_at, pr.error_message, pr.created_at, pr.updated_at
|
||||
FROM publish_records pr
|
||||
JOIN media_platforms mp ON mp.platform_id = pr.platform_id
|
||||
JOIN platform_accounts pa ON pa.id = pr.platform_account_id
|
||||
LEFT JOIN media_platforms mp ON mp.platform_id = pr.platform_id
|
||||
LEFT JOIN platform_accounts pa ON pa.id = pr.platform_account_id
|
||||
LEFT JOIN enterprise_site_connections esc
|
||||
ON esc.id = pr.target_connection_id
|
||||
AND esc.tenant_id = pr.tenant_id
|
||||
JOIN articles a ON a.id = pr.article_id AND a.tenant_id = pr.tenant_id
|
||||
WHERE pr.tenant_id = $1 AND pr.article_id = $2 AND a.brand_id = $3 AND a.deleted_at IS NULL
|
||||
ORDER BY pr.created_at DESC, pr.id DESC
|
||||
@@ -116,13 +128,15 @@ func (s *MediaService) listArticlePublishRecords(ctx context.Context, tenantID,
|
||||
items := make([]PublishRecordResponse, 0)
|
||||
for rows.Next() {
|
||||
var item PublishRecordResponse
|
||||
var desktopAccountID string
|
||||
var desktopAccountID *string
|
||||
if err := rows.Scan(
|
||||
&item.ID,
|
||||
&item.PublishBatchID,
|
||||
&item.ArticleID,
|
||||
&item.PlatformAccountID,
|
||||
&desktopAccountID,
|
||||
&item.TargetType,
|
||||
&item.TargetConnectionID,
|
||||
&item.PlatformID,
|
||||
&item.PlatformName,
|
||||
&item.PlatformNickname,
|
||||
@@ -137,8 +151,8 @@ func (s *MediaService) listArticlePublishRecords(ctx context.Context, tenantID,
|
||||
); err != nil {
|
||||
return nil, response.ErrInternal(50043, "publish_record_scan_failed", err.Error())
|
||||
}
|
||||
if strings.TrimSpace(desktopAccountID) != "" {
|
||||
item.DesktopAccountID = &desktopAccountID
|
||||
if desktopAccountID != nil && strings.TrimSpace(*desktopAccountID) != "" {
|
||||
item.DesktopAccountID = desktopAccountID
|
||||
}
|
||||
normalizePublishRecordForResponse(&item)
|
||||
items = append(items, item)
|
||||
|
||||
Reference in New Issue
Block a user