feat(publish): require cover image for WeChat Official Account
WeChat 公众号在管理员/运营者授权发布场景下需要 2.35:1 封面, 新增共享 publishPlatformRequiresCover 校验并同步前端封面要求与文案, 避免在调度与即时发布两条路径上重复维护平台名单。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1101,7 +1101,7 @@ const enUS = {
|
|||||||
previewHintLocked: "A selected platform requires a fixed cover ratio, so the cover will be exported using the current platform requirement.",
|
previewHintLocked: "A selected platform requires a fixed cover ratio, so the cover will be exported using the current platform requirement.",
|
||||||
previewHintFree: "There is no forced cover ratio right now. You can upload the original image directly or adjust framing before confirming.",
|
previewHintFree: "There is no forced cover ratio right now. You can upload the original image directly or adjust framing before confirming.",
|
||||||
requirementsTitle: "Platform requirements",
|
requirementsTitle: "Platform requirements",
|
||||||
requirementsHint: "Requirements switch automatically based on the selected publish platforms. Baijiahao and Dongchedi require a cover image.",
|
requirementsHint: "Requirements switch automatically based on the selected publish platforms. WeChat Official Account, Baijiahao, and Dongchedi require a cover image.",
|
||||||
recommendedRatio: "Recommended ratio",
|
recommendedRatio: "Recommended ratio",
|
||||||
recommendedSize: "Recommended size",
|
recommendedSize: "Recommended size",
|
||||||
required: "Required",
|
required: "Required",
|
||||||
|
|||||||
@@ -1110,7 +1110,7 @@ const zhCN = {
|
|||||||
previewHintLocked: "已选择需要固定封面比例的平台,确认时会按当前平台要求输出封面。",
|
previewHintLocked: "已选择需要固定封面比例的平台,确认时会按当前平台要求输出封面。",
|
||||||
previewHintFree: "当前不限制封面比例,可直接上传原图;如需调整也可拖拽缩放后再确认。",
|
previewHintFree: "当前不限制封面比例,可直接上传原图;如需调整也可拖拽缩放后再确认。",
|
||||||
requirementsTitle: "平台封面要求",
|
requirementsTitle: "平台封面要求",
|
||||||
requirementsHint: "会根据当前选中的发布平台自动切换要求,百家号和懂车帝为强制上传。",
|
requirementsHint: "会根据当前选中的发布平台自动切换要求,微信公众号、百家号和懂车帝为强制上传。",
|
||||||
recommendedRatio: "推荐比例",
|
recommendedRatio: "推荐比例",
|
||||||
recommendedSize: "推荐尺寸",
|
recommendedSize: "推荐尺寸",
|
||||||
required: "必传",
|
required: "必传",
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ const defaultRequirement = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const requirementCatalog: Record<string, Partial<PlatformCoverRequirement>> = {
|
const requirementCatalog: Record<string, Partial<PlatformCoverRequirement>> = {
|
||||||
|
weixin_gzh: {
|
||||||
|
required: true,
|
||||||
|
supportMode: "native",
|
||||||
|
aspectRatio: 2.35,
|
||||||
|
aspectLabel: "2.35:1",
|
||||||
|
outputWidth: 1200,
|
||||||
|
outputHeight: 511,
|
||||||
|
priority: 110,
|
||||||
|
},
|
||||||
baijiahao: {
|
baijiahao: {
|
||||||
required: true,
|
required: true,
|
||||||
supportMode: "native",
|
supportMode: "native",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
@@ -136,13 +137,22 @@ func (s *MediaService) listArticlePublishRecords(ctx context.Context, tenantID,
|
|||||||
|
|
||||||
func publishBatchRequiresCover(accounts []platformAccountSeed) bool {
|
func publishBatchRequiresCover(accounts []platformAccountSeed) bool {
|
||||||
for _, account := range accounts {
|
for _, account := range accounts {
|
||||||
if account.PlatformID == "baijiahao" || account.PlatformID == "dongchedi" {
|
if publishPlatformRequiresCover(account.PlatformID) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func publishPlatformRequiresCover(platformID string) bool {
|
||||||
|
switch strings.TrimSpace(platformID) {
|
||||||
|
case "weixin_gzh", "baijiahao", "dongchedi":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func pointerStringValue(value *string) string {
|
func pointerStringValue(value *string) string {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func (s *PublishJobService) Create(ctx context.Context, actor auth.Actor, req Cr
|
|||||||
accountSeeds = append(accountSeeds, *target.accountSeed)
|
accountSeeds = append(accountSeeds, *target.accountSeed)
|
||||||
}
|
}
|
||||||
if publishBatchRequiresCover(accountSeeds) && strings.TrimSpace(pointerStringValue(articleMeta.CoverAssetURL)) == "" {
|
if publishBatchRequiresCover(accountSeeds) && strings.TrimSpace(pointerStringValue(articleMeta.CoverAssetURL)) == "" {
|
||||||
return nil, response.ErrBadRequest(40044, "publish_cover_required", "baijiahao publishing requires a cover image")
|
return nil, response.ErrBadRequest(40044, "publish_cover_required", "selected publishing platform requires a cover image")
|
||||||
}
|
}
|
||||||
|
|
||||||
publishBatchID, publishRecordIDs, err := createPublishBatchRecords(
|
publishBatchID, publishRecordIDs, err := createPublishBatchRecords(
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestPublishPlatformRequiresCover(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for _, platformID := range []string{"weixin_gzh", "baijiahao", "dongchedi"} {
|
||||||
|
if !publishPlatformRequiresCover(platformID) {
|
||||||
|
t.Fatalf("publishPlatformRequiresCover(%q) = false, want true", platformID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if publishPlatformRequiresCover("zhihu") {
|
||||||
|
t.Fatal("publishPlatformRequiresCover(\"zhihu\") = true, want false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPublishCoverRequirementCallersIncludeWeixinGzh(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
accounts := []platformAccountSeed{{PlatformID: "weixin_gzh"}}
|
||||||
|
if !publishBatchRequiresCover(accounts) {
|
||||||
|
t.Fatal("publishBatchRequiresCover() = false for weixin_gzh, want true")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !schedulePublishPlatformsRequireCover([]string{"weixin_gzh"}) {
|
||||||
|
t.Fatal("schedulePublishPlatformsRequireCover() = false for weixin_gzh, want true")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -564,8 +564,7 @@ func (s *ScheduleTaskService) loadPublishAccountPlatformIDs(ctx context.Context,
|
|||||||
|
|
||||||
func schedulePublishPlatformsRequireCover(platformIDs []string) bool {
|
func schedulePublishPlatformsRequireCover(platformIDs []string) bool {
|
||||||
for _, platformID := range platformIDs {
|
for _, platformID := range platformIDs {
|
||||||
switch strings.TrimSpace(platformID) {
|
if publishPlatformRequiresCover(platformID) {
|
||||||
case "baijiahao", "dongchedi":
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user