feat: add cover image functionality for articles
- Implemented `resolveApiURL` function to handle various URL formats. - Updated `ArticleDetail` and `UpdateArticleRequest` interfaces to include `cover_asset_url`. - Enhanced `ArticleEditorView` to manage cover image uploads, including a new `CoverPickerModal` component. - Added cover image requirements logic in `cover-requirements.ts` to enforce platform-specific cover image rules. - Modified backend services to handle cover image uploads and validations, including checks for required cover images for specific platforms. - Improved error handling for cover image requirements during article publishing.
This commit is contained in:
@@ -427,8 +427,15 @@ const enUS = {
|
||||
platformsTitle: "Publish platforms",
|
||||
platformsHint: "This stays in sync with Media Management so you can edit the article's publish platforms directly.",
|
||||
coverTitle: "Cover image",
|
||||
coverHint: "Upload a cover asset before publishing. This is local preview only for now.",
|
||||
coverHint: "Off by default. Once uploaded, the cover is saved with the article.",
|
||||
coverRequired: "Baijiahao is selected, so the cover image becomes required.",
|
||||
coverUpload: "Upload cover image",
|
||||
coverReplace: "Choose again",
|
||||
coverRemove: "Remove cover",
|
||||
coverSaved: "Cover asset saved",
|
||||
coverOff: "Cover image is currently off. Turn it on to upload and crop a cover asset.",
|
||||
coverTagRequired: "Required",
|
||||
coverTagOptional: "Optional",
|
||||
imagePrompt: "Enter image URL",
|
||||
tablePicker: {
|
||||
empty: "Drag to choose a table size",
|
||||
@@ -566,7 +573,8 @@ const enUS = {
|
||||
platformsTitle: "Target platforms",
|
||||
platformsHint: "Previously selected and bound accounts are prefilled first. Unbound or locally unavailable platforms stay disabled.",
|
||||
coverTitle: "Cover image",
|
||||
coverHint: "This version uses a cover asset URL. Upload and crop can be wired later.",
|
||||
coverHint: "Off by default. Uploading opens the cover picker and cropper.",
|
||||
coverUpload: "Upload cover image",
|
||||
coverPlaceholder: "Enter an optional cover asset URL",
|
||||
messages: {
|
||||
success: "{count} publish tasks submitted.",
|
||||
@@ -574,6 +582,7 @@ const enUS = {
|
||||
partial: "Publish finished with {success} succeeded and {failed} failed.",
|
||||
partialTitle: "Partial publish failure",
|
||||
selectPlatform: "Choose at least one available platform first.",
|
||||
coverRequired: "Baidu Baijiahao is selected. Please upload a cover image first.",
|
||||
failureTitle: "Publish failed",
|
||||
failureItem: "Publishing to [{platform}] failed: [{reason}]",
|
||||
unknownFailure: "Unknown error",
|
||||
@@ -592,6 +601,46 @@ const enUS = {
|
||||
copySuccess: "Link copied.",
|
||||
},
|
||||
},
|
||||
coverPicker: {
|
||||
title: "Select cover image",
|
||||
tabs: {
|
||||
local: "Body / Local Upload",
|
||||
ai: "AI Cover",
|
||||
},
|
||||
previewTitle: "Cover crop preview",
|
||||
previewHintLocked: "Baijiahao is selected, so the cover will be exported as 16:9 when you confirm.",
|
||||
previewHintFree: "There is no forced cover ratio right now. You can upload the original image directly or adjust framing before confirming.",
|
||||
requirementsTitle: "Platform requirements",
|
||||
requirementsHint: "Requirements switch automatically based on the selected publish platforms. Baijiahao is mandatory.",
|
||||
recommendedRatio: "Recommended ratio",
|
||||
recommendedSize: "Recommended size",
|
||||
required: "Required",
|
||||
optional: "Optional",
|
||||
zoom: "Zoom",
|
||||
fileLabel: "Current cover",
|
||||
emptyTitle: "No publish platform selected",
|
||||
emptyPlatforms: "Choose publish platforms first and each platform's cover requirements will appear here.",
|
||||
emptyHint: "Supports PNG, JPG, GIF, and WebP up to 10MB.",
|
||||
aiTitle: "AI cover is coming soon",
|
||||
aiHint: "For now this flow supports local upload and cropping. AI cover generation can be plugged in here later.",
|
||||
actions: {
|
||||
upload: "Local upload",
|
||||
reset: "Reset framing",
|
||||
remove: "Remove cover",
|
||||
},
|
||||
notes: {
|
||||
required: "This platform currently requires a cover image in the publish flow. Publishing is blocked until one is uploaded.",
|
||||
optional: "This platform already supports standalone covers and reuses the current crop when publishing.",
|
||||
unsupported: "This platform's current integration does not consume a standalone cover yet and falls back to body content or the platform default.",
|
||||
},
|
||||
messages: {
|
||||
invalidType: "Only PNG, JPG, GIF, and WebP images are supported.",
|
||||
tooLarge: "Image size cannot exceed 10MB.",
|
||||
missingImage: "Select a cover image first.",
|
||||
missingArticle: "The article is not ready yet. Refresh and try again.",
|
||||
imageLoadFailed: "Failed to load the cover image. Please choose another image.",
|
||||
},
|
||||
},
|
||||
brands: {
|
||||
eyebrow: "Brand Library",
|
||||
title: "Brand Library",
|
||||
|
||||
@@ -434,8 +434,15 @@ const zhCN = {
|
||||
platformsTitle: "发布平台",
|
||||
platformsHint: "这里会同步媒体管理中的平台和绑定状态,支持直接编辑文章的发布平台。",
|
||||
coverTitle: "封面图",
|
||||
coverHint: "发布前可先上传封面素材,当前只做本地预览。",
|
||||
coverHint: "默认关闭。上传后会保存为文章封面素材。",
|
||||
coverRequired: "已选择百家号,封面图为必传项。",
|
||||
coverUpload: "上传封面图",
|
||||
coverReplace: "重新选择",
|
||||
coverRemove: "移除封面",
|
||||
coverSaved: "已保存封面素材",
|
||||
coverOff: "封面图当前已关闭,开启后可上传并裁剪封面素材。",
|
||||
coverTagRequired: "必传",
|
||||
coverTagOptional: "可选",
|
||||
imagePrompt: "请输入图片地址",
|
||||
tablePicker: {
|
||||
empty: "拖拽选择表格尺寸",
|
||||
@@ -573,7 +580,8 @@ const zhCN = {
|
||||
platformsTitle: "发布平台",
|
||||
platformsHint: "会优先回填文章里已选择且已绑定的账号,未绑定或本地登录态异常的平台不可选。",
|
||||
coverTitle: "封面图",
|
||||
coverHint: "当前版本先使用封面素材 URL,后续可以接入上传与裁剪。",
|
||||
coverHint: "默认关闭。点击上传后可选择或裁剪封面。",
|
||||
coverUpload: "上传封面图",
|
||||
coverPlaceholder: "请输入封面素材 URL(可选)",
|
||||
messages: {
|
||||
success: "已提交 {count} 个平台发布任务",
|
||||
@@ -581,6 +589,7 @@ const zhCN = {
|
||||
partial: "发布执行完成,成功 {success} 个,失败 {failed} 个",
|
||||
partialTitle: "部分发布失败",
|
||||
selectPlatform: "请先选择至少一个可发布的平台",
|
||||
coverRequired: "已选择百家号,请先上传封面图",
|
||||
failureTitle: "发布失败",
|
||||
failureItem: "文章发布到平台【{platform}】失败【{reason}】",
|
||||
unknownFailure: "未知错误",
|
||||
@@ -599,6 +608,46 @@ const zhCN = {
|
||||
copySuccess: "链接已复制",
|
||||
},
|
||||
},
|
||||
coverPicker: {
|
||||
title: "选择封面图",
|
||||
tabs: {
|
||||
local: "正文/本地上传",
|
||||
ai: "AI封图",
|
||||
},
|
||||
previewTitle: "封面裁剪预览",
|
||||
previewHintLocked: "已选择百家号,确认时会按 16:9 输出封面。",
|
||||
previewHintFree: "当前不限制封面比例,可直接上传原图;如需调整也可拖拽缩放后再确认。",
|
||||
requirementsTitle: "平台封面要求",
|
||||
requirementsHint: "会根据当前选中的发布平台自动切换要求,百家号为强制上传。",
|
||||
recommendedRatio: "推荐比例",
|
||||
recommendedSize: "推荐尺寸",
|
||||
required: "必传",
|
||||
optional: "可选",
|
||||
zoom: "缩放",
|
||||
fileLabel: "当前封面",
|
||||
emptyTitle: "暂未选择发布平台",
|
||||
emptyPlatforms: "选择发布平台后,这里会自动显示每个平台的封面要求。",
|
||||
emptyHint: "支持 PNG、JPG、GIF、WebP,最大 10MB",
|
||||
aiTitle: "AI 封图即将开放",
|
||||
aiHint: "当前先支持本地上传和裁剪,后续会把 AI 生成封面接进这里。",
|
||||
actions: {
|
||||
upload: "本地上传",
|
||||
reset: "重置取景",
|
||||
remove: "移除封面",
|
||||
},
|
||||
notes: {
|
||||
required: "该平台当前发布链路要求必须携带封面图,未上传时不能提交发布。",
|
||||
optional: "该平台当前接入已支持独立封面,会复用当前裁剪结果完成发布。",
|
||||
unsupported: "该平台当前接入暂不消费独立封面,会沿用正文内容或平台默认样式。",
|
||||
},
|
||||
messages: {
|
||||
invalidType: "仅支持 PNG、JPG、GIF、WebP 图片",
|
||||
tooLarge: "图片不能超过 10MB",
|
||||
missingImage: "请先选择一张封面图",
|
||||
missingArticle: "文章信息还没准备好,请刷新后重试",
|
||||
imageLoadFailed: "封面图加载失败,请重新选择图片",
|
||||
},
|
||||
},
|
||||
brands: {
|
||||
eyebrow: "Brand Library",
|
||||
title: "品牌词库",
|
||||
|
||||
Reference in New Issue
Block a user