From 0ab58b7e6e1ea1cb792f8befba515a705fde343d Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 10 Feb 2026 19:15:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=A3=E7=90=86=E5=95=86=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E6=98=BE=E7=A4=BA=20+=20Brief=20=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E9=A2=84=E8=A7=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端 TaskResponse.ProjectInfo 新增 platform 字段 - 修复代理商 6 个页面硬编码 platform='douyin' 的问题,改为读取实际值 - Brief 预览弹窗:占位符改为 iframe/img 实际展示文件内容 - PDF 用 iframe 在线预览 - 图片直接展示 - 其他类型提示下载 - Brief 下载:改用 a 标签触发下载 Co-Authored-By: Claude Opus 4.6 --- backend/app/api/tasks.py | 1 + backend/app/schemas/task.py | 1 + frontend/app/agency/appeals/page.tsx | 2 +- frontend/app/agency/briefs/[id]/page.tsx | 133 +++++++++++++++++++---- frontend/app/agency/briefs/page.tsx | 4 +- frontend/app/agency/creators/page.tsx | 2 +- frontend/app/agency/tasks/[id]/page.tsx | 7 +- frontend/app/creator/page.tsx | 2 +- frontend/types/task.ts | 1 + 9 files changed, 126 insertions(+), 27 deletions(-) diff --git a/backend/app/api/tasks.py b/backend/app/api/tasks.py index 904e1c3..98565d8 100644 --- a/backend/app/api/tasks.py +++ b/backend/app/api/tasks.py @@ -68,6 +68,7 @@ def _task_to_response(task: Task) -> TaskResponse: id=task.project.id, name=task.project.name, brand_name=task.project.brand.name if task.project.brand else None, + platform=task.project.platform, ), agency=AgencyInfo( id=task.agency.id, diff --git a/backend/app/schemas/task.py b/backend/app/schemas/task.py index 797e39e..95e20ea 100644 --- a/backend/app/schemas/task.py +++ b/backend/app/schemas/task.py @@ -87,6 +87,7 @@ class ProjectInfo(BaseModel): id: str name: str brand_name: Optional[str] = None + platform: Optional[str] = None class TaskResponse(BaseModel): diff --git a/frontend/app/agency/appeals/page.tsx b/frontend/app/agency/appeals/page.tsx index 02edb2e..c22af79 100644 --- a/frontend/app/agency/appeals/page.tsx +++ b/frontend/app/agency/appeals/page.tsx @@ -149,7 +149,7 @@ function mapTaskToAppeal(task: TaskResponse): Appeal { taskTitle: task.name, creatorId: task.creator.id, creatorName: task.creator.name, - platform: 'douyin', // Backend does not expose platform on task; default for now + platform: task.project?.platform || 'douyin', type, contentType, reason: task.appeal_reason || '申诉', diff --git a/frontend/app/agency/briefs/[id]/page.tsx b/frontend/app/agency/briefs/[id]/page.tsx index e0383db..e25659c 100644 --- a/frontend/app/agency/briefs/[id]/page.tsx +++ b/frontend/app/agency/briefs/[id]/page.tsx @@ -356,7 +356,7 @@ export default function BriefConfigPage() { id: brief?.id || `no-brief-${projectId}`, projectName: project.name, brandName: project.brand_name || '未知品牌', - platform: 'douyin', // 后端暂无 platform 字段 + platform: project.platform || 'douyin', files: briefFiles, brandRules: { restrictions: brief?.other_requirements || '暂无限制条件', @@ -418,15 +418,37 @@ export default function BriefConfigPage() { } try { const signedUrl = await api.getSignedUrl(file.url) - window.open(signedUrl, '_blank') + // 使用 a 标签触发下载 + const a = document.createElement('a') + a.href = signedUrl + a.target = '_blank' + a.rel = 'noopener noreferrer' + a.download = file.name + document.body.appendChild(a) + a.click() + document.body.removeChild(a) } catch { toast.error('获取下载链接失败') } } // 预览文件 - const handlePreview = (file: BriefFile) => { + const [previewUrl, setPreviewUrl] = useState(null) + const [previewLoading, setPreviewLoading] = useState(false) + const handlePreview = async (file: BriefFile) => { setPreviewFile(file) + setPreviewUrl(null) + if (!USE_MOCK && file.url) { + setPreviewLoading(true) + try { + const signedUrl = await api.getSignedUrl(file.url) + setPreviewUrl(signedUrl) + } catch { + toast.error('获取预览链接失败') + } finally { + setPreviewLoading(false) + } + } } // 导出平台规则文档 @@ -622,8 +644,22 @@ export default function BriefConfigPage() { })) } - const handlePreviewAgencyFile = (file: AgencyFile) => { + const [previewAgencyUrl, setPreviewAgencyUrl] = useState(null) + const [previewAgencyLoading, setPreviewAgencyLoading] = useState(false) + const handlePreviewAgencyFile = async (file: AgencyFile) => { setPreviewAgencyFile(file) + setPreviewAgencyUrl(null) + if (!USE_MOCK && file.url) { + setPreviewAgencyLoading(true) + try { + const signedUrl = await api.getSignedUrl(file.url) + setPreviewAgencyUrl(signedUrl) + } catch { + toast.error('获取预览链接失败') + } finally { + setPreviewAgencyLoading(false) + } + } } const handleDownloadAgencyFile = async (file: AgencyFile) => { @@ -633,7 +669,14 @@ export default function BriefConfigPage() { } try { const signedUrl = await api.getSignedUrl(file.url) - window.open(signedUrl, '_blank') + const a = document.createElement('a') + a.href = signedUrl + a.target = '_blank' + a.rel = 'noopener noreferrer' + a.download = file.name + document.body.appendChild(a) + a.click() + document.body.removeChild(a) } catch { toast.error('获取下载链接失败') } @@ -1179,20 +1222,44 @@ export default function BriefConfigPage() { {/* 文件预览弹窗(品牌方) */} setPreviewFile(null)} + onClose={() => { setPreviewFile(null); setPreviewUrl(null) }} title={previewFile?.name || '文件预览'} size="lg" >
-
-
- -

文件预览区域

-

实际开发中将嵌入文件预览组件

-
+
+ {previewLoading ? ( +
+ + 加载预览中... +
+ ) : previewUrl && previewFile?.name.toLowerCase().endsWith('.pdf') ? ( +