diff --git a/apps/web/src/pages/viral-video/ViralVideoPage.css b/apps/web/src/pages/viral-video/ViralVideoPage.css index 914a2ec4a..530527c8a 100644 --- a/apps/web/src/pages/viral-video/ViralVideoPage.css +++ b/apps/web/src/pages/viral-video/ViralVideoPage.css @@ -172,14 +172,7 @@ } /* ── 通用表单元素 ─────────────────────────────────── */ -.vv-label { - display: block; - font-size: 12px; - color: #6b7280; - margin-bottom: 6px; -} .vv-input, -.vv-select, .vv-textarea { width: 100%; border: 1px solid #e5e7eb; @@ -194,29 +187,70 @@ box-shadow 0.15s; font-family: inherit; } +.vv-input { + height: 36px; + padding: 0 12px; +} +.vv-input:disabled { + background: #f9fafb; + color: #9ca3af; + cursor: not-allowed; +} +.vv-input::placeholder, +.vv-textarea::placeholder { + color: #9ca3af; +} +.vv-select { + width: 100%; +} +.vv-select .ant-select-selector { + border-radius: 8px !important; + border-color: #e5e7eb !important; + box-shadow: none !important; + height: 36px !important; + padding: 0 12px !important; + transition: + border-color 0.15s, + box-shadow 0.15s !important; +} +.vv-select.ant-select-focused .ant-select-selector, +.vv-select.ant-select-open .ant-select-selector { + border-color: #7c3aed !important; + box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.1) !important; +} +.vv-select .ant-select-selection-item { + font-size: 13px !important; + color: #111827 !important; + line-height: 34px !important; +} +.vv-select .ant-select-selection-placeholder { + font-size: 13px !important; + color: #d1d5db !important; + line-height: 34px !important; +} +.vv-select .ant-select-arrow { + color: #9ca3af; + inset-inline-end: 10px; +} +.vv-select.ant-select-disabled .ant-select-selector { + background: #f9fafb !important; + color: #9ca3af !important; + cursor: not-allowed; +} +.vv-select.ant-select-disabled .ant-select-selection-item, +.vv-select.ant-select-disabled .ant-select-selection-placeholder { + color: #9ca3af !important; +} .vv-textarea { line-height: 1.6; resize: vertical; min-height: 90px; } .vv-input:focus, -.vv-select:focus, .vv-textarea:focus { border-color: #7c3aed; box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.1); } -.vv-input::placeholder, -.vv-textarea::placeholder { - color: #d1d5db; -} -.vv-form-row { - margin-bottom: 12px; -} -.vv-form-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px; -} /* ── Tab 分段 ─────────────────────────────────────── */ .vv-seg-tabs { @@ -905,15 +939,7 @@ box-shadow: none !important; transform: none !important; } -.vv-btn-ghost { - background: #fff; - color: #6b7280; - border-color: #e5e7eb; -} -.vv-btn-ghost:hover { - border-color: #7c3aed; - color: #7c3aed; -} + .vv-btn-warn { background: #fef3c7; color: #b45309; @@ -1235,31 +1261,7 @@ color: #9ca3af !important; } -/* 列禁用态 */ -.vv-col-disabled .vv-section-body, -.vv-col-disabled .vv-step-subhead, -.vv-col-disabled .vv-credits, -.vv-col-disabled .vv-preview, -.vv-col-disabled .vv-error, -.vv-col-disabled .vv-hint-gray, -.vv-col-disabled .vv-hint-yellow { - opacity: 0.55; -} -.vv-col-disabled .vv-btn-primary, -.vv-col-disabled .vv-btn-primary:hover { - opacity: 1 !important; -} -.vv-col-disabled .vv-section .vv-form-row, -.vv-col-disabled .vv-section .vv-pill-row, -.vv-col-disabled .vv-section input, -.vv-col-disabled .vv-section textarea, -.vv-col-disabled .vv-section .ant-select, -.vv-col-disabled .vv-section .vv-pill, -.vv-col-disabled .vv-section .vv-action-btn, -.vv-col-disabled .vv-section .vv-audio-cell, -.vv-col-disabled .vv-section .vv-step-lock { - pointer-events: none; -} +/* 步骤列禁用态已移除:不再锁控件,仅通过按钮 disabled 控制 */ /* Section 内小标题 */ .vv-section-subtitle { @@ -1622,68 +1624,6 @@ color: #9ca3af; font-weight: 400; } -.vv-input { - width: 100%; - height: 36px; - border-radius: 8px; - border: 1px solid #e5e7eb; - background: #fff; - padding: 0 12px; - font-size: 13px; - color: #111827; - outline: none; - transition: - border-color 0.15s, - box-shadow 0.15s; -} -.vv-input:focus { - border-color: #7c3aed; - box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.15); -} -.vv-input:disabled { - background: #f9fafb; - color: #9ca3af; - cursor: not-allowed; -} -.vv-input::placeholder { - color: #9ca3af; -} - -/* 自定义 Select 样式(浅色紫调) */ -.vv-select-purple .ant-select-selector { - border-radius: 8px !important; - border: 1px solid #e5e7eb !important; - background: #fff !important; - min-height: 36px !important; - padding: 0 28px 0 12px !important; - box-shadow: none !important; - transition: - border-color 0.15s, - box-shadow 0.15s !important; -} -.vv-select-purple.ant-select-focused .ant-select-selector, -.vv-select-purple .ant-select-focused .ant-select-selector { - border-color: #7c3aed !important; - box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.15) !important; -} -.vv-select-purple .ant-select-selection-item, -.vv-select-purple .ant-select-selection-placeholder { - line-height: 34px !important; - font-size: 13px !important; - color: #111827 !important; -} -.vv-select-purple .ant-select-selection-placeholder { - color: #9ca3af !important; -} -.vv-select-purple .ant-select-arrow { - color: #6b7280; - right: 10px !important; -} -.vv-select-purple.ant-select-disabled .ant-select-selector { - background: #f9fafb !important; - color: #9ca3af !important; - cursor: not-allowed; -} /* ghost/outline 按钮 */ .vv-btn-ghost { @@ -1739,9 +1679,18 @@ margin-bottom: 4px; } .vv-sb-input { - height: 32px; font-size: 13px; } +.vv-sb-input.vv-input { + height: 32px; +} +.vv-sb-input.vv-select .ant-select-selector { + height: 32px !important; +} +.vv-sb-input.vv-select .ant-select-selection-item, +.vv-sb-input.vv-select .ant-select-selection-placeholder { + line-height: 30px !important; +} /* 分块标题 */ .vv-sb-section { diff --git a/apps/web/src/pages/viral-video/ViralVideoPage.tsx b/apps/web/src/pages/viral-video/ViralVideoPage.tsx index eb939ed3a..39a3921b2 100644 --- a/apps/web/src/pages/viral-video/ViralVideoPage.tsx +++ b/apps/web/src/pages/viral-video/ViralVideoPage.tsx @@ -152,10 +152,25 @@ const TARGET_CUSTOMERS = [ ] const PERSONAS = ["亲切邻家姐姐", "专业顾问", "搞笑段子手", "真实测评博主", "闺蜜种草", "行业专家"] const STRUCTURES = [ - "痛点开场→卖点→促单", - "反差对比→证据→促单", - "故事讲述→共鸣→促单", - "专家背书→数据→促单", + "反差破局+亮明观点+还原现状", + "痛点场景植入+给出通关秘籍", + "反常识开场+扎心现状+制造焦虑", + "核心难题+化解焦虑+描绘愿景", + "痛点前置+前后对比+给出期许", + "悬念拉满+揭露危害+明确目的", + "情绪共鸣+勾起好奇+拔高价值", + "颠覆认知+现状拆解+赋予价值", + "结果先行+消除顾虑+保留悬念", + "真实困境+认知反转+传授秘籍", + "反差事实+案例佐证+戳破真相", + "预埋悬念+标杆案例+引出核心", + "危机渲染+放大痛点+输出干货", + "逆袭开场+成功诀窍+低价引流", + "反常识观点+分析危害+描述现状", + "正反对比+解析原因+简易方法", + "真实场景+内心刻画+共情引导+展望未来", + "连续否定+代入感受+打破认知+精准戳痛", + "揭秘行业+类比施压+放大焦虑+精准锁客", ] const PURPOSES = ["品牌种草", "新品上市", "促销转化", "活动引流"] const DURATIONS = [15, 20, 30, 45, 60] @@ -943,24 +958,61 @@ const ViralVideoPage: React.FC = () => { {products.map((p, i) => (
- {p.name && ( +
+ 商品: + + {p.name || "未识别"} + {p.spec && ({p.spec})} + {p.brand && · {p.brand}} + {p.category && · {p.category}} + +
+ {featureText(p.key_features ?? p.features) && (
- 商品: - {p.name} - {p.spec && ({p.spec})} - {p.brand && · {p.brand}} + 核心特征: + {featureText(p.key_features ?? p.features)}
)} - {featureText(p.features) && ( + {p.colors && p.colors.length > 0 && (
- 视觉特征: - {featureText(p.features)} + 主色调: + {p.colors.join(" / ")}
)} - {p.label_text && ( + {p.material_or_texture && (
- 品牌/标签文字: - {p.label_text} + 材质/纹理: + {p.material_or_texture} +
+ )} + {p.visual_style && ( +
+ 视觉风格: + {p.visual_style} +
+ )} + {p.scene && ( +
+ 场景: + {p.scene} +
+ )} + {p.target_audience_hint && ( +
+ 目标人群: + {p.target_audience_hint} +
+ )} + {(p.text_on_image || p.label_text) && ( +
+ 包装文字: + {p.text_on_image || p.label_text} +
+ )} + {p.selling_points && ( +
+ 卖点: + {p.selling_points}
)}
@@ -1689,7 +1741,7 @@ const ViralVideoPage: React.FC = () => { {/* ═══════════ 中列 STEP 2 ═══════════ */} -
+
2 @@ -1705,7 +1757,7 @@ const ViralVideoPage: React.FC = () => { key={f.value} className={`vv-fusion-btn ${task.fusionLevel === f.value ? "active" : ""}`} onClick={() => setTask({ fusionLevel: f.value })} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} > {f.label} {f.desc} @@ -1720,7 +1772,7 @@ const ViralVideoPage: React.FC = () => { placeholder="请输入你想要的原始文案,AI 将严格保留你的表达" value={task.userCopy} onChange={(e) => setTask({ userCopy: e.target.value })} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
)} @@ -1736,7 +1788,7 @@ const ViralVideoPage: React.FC = () => { placeholder="如:家具店、宠物店、装修公司" value={task.industry} onChange={(e) => setTask({ industry: e.target.value })} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1749,7 +1801,7 @@ const ViralVideoPage: React.FC = () => { onChange={(v) => setTask({ targetCustomer: v })} options={TARGET_CUSTOMERS.map((i) => ({ value: i, label: i }))} allowClear - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1760,7 +1812,7 @@ const ViralVideoPage: React.FC = () => { value={task.language} onChange={(v) => setTask({ language: v })} options={LANGUAGES.map((i) => ({ value: i, label: i }))} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1773,7 +1825,7 @@ const ViralVideoPage: React.FC = () => { onChange={(v) => setTask({ persona: v })} options={PERSONAS.map((i) => ({ value: i, label: i }))} allowClear - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1784,7 +1836,7 @@ const ViralVideoPage: React.FC = () => { value={task.viralStructure} onChange={(v) => setTask({ viralStructure: v })} options={STRUCTURES.map((i) => ({ value: i, label: i }))} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1795,7 +1847,7 @@ const ViralVideoPage: React.FC = () => { value={task.marketingPurpose} onChange={(v) => setTask({ marketingPurpose: v })} options={PURPOSES.map((i) => ({ value: i, label: i }))} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1806,7 +1858,7 @@ const ViralVideoPage: React.FC = () => { value={task.duration} onChange={(v) => setTask({ duration: v })} options={DURATIONS.map((n) => ({ value: n, label: `${n}秒` }))} - disabled={!canEditStep2 || !step2Enabled} + disabled={!canEditStep2} />
@@ -1860,7 +1912,7 @@ const ViralVideoPage: React.FC = () => {
{/* ═══════════ 右列 STEP 3 ═══════════ */} -
+
3 @@ -1876,11 +1928,7 @@ const ViralVideoPage: React.FC = () => { value={task.videoRatio} onChange={(v) => setTask({ videoRatio: v })} options={RATIOS.map((r) => ({ value: r.v, label: r.label }))} - disabled={ - !step3Enabled || - task.uiStep === "step3_generating" || - task.uiStep === "step3_done" - } + disabled={task.uiStep === "step3_generating" || task.uiStep === "step3_done"} />
@@ -1891,11 +1939,7 @@ const ViralVideoPage: React.FC = () => { value={task.videoModel} onChange={(v) => setTask({ videoModel: v })} options={MODELS.map((m) => ({ value: m.v, label: m.label }))} - disabled={ - !step3Enabled || - task.uiStep === "step3_generating" || - task.uiStep === "step3_done" - } + disabled={task.uiStep === "step3_generating" || task.uiStep === "step3_done"} />