diff --git a/apps/web/src/components/layout/MainLayout.css b/apps/web/src/components/layout/MainLayout.css
index 5a6ffc690..d5c60167e 100644
--- a/apps/web/src/components/layout/MainLayout.css
+++ b/apps/web/src/components/layout/MainLayout.css
@@ -1,10 +1,12 @@
-/* V21 主容器 */
+/* V21 主布局样式 */
.xx-app-shell {
display: flex;
flex-direction: column;
min-height: 100vh;
background: var(--bg, #f8fafc);
color: var(--slate, #0f172a);
+ position: relative;
+ z-index: 1;
}
.xx-app-content {
@@ -15,7 +17,7 @@
padding: 38px 24px 76px;
}
-/* 根 CSS 变量 */
+/* V21 颜色变量 */
:root {
--indigo: #4f46e5;
--slate: #0f172a;
@@ -28,5 +30,5 @@
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
}
diff --git a/apps/web/src/index.css b/apps/web/src/index.css
index f376d2ac7..07b9945c9 100644
--- a/apps/web/src/index.css
+++ b/apps/web/src/index.css
@@ -1,12 +1,27 @@
+/**
+ * V21 全局基础样式
+ */
:root {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC',
'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
- line-height: 1.5;
+ line-height: 1.6;
font-weight: 400;
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
+ /* V21 颜色系统 */
+ --indigo: #4f46e5;
+ --indigo-dark: #4338ca;
+ --indigo-soft: #eef2ff;
+ --slate: #0f172a;
+ --muted: #64748b;
+ --line: #e2e8f0;
+ --bg: #f8fafc;
+ --green: #10b981;
+ --amber: #f59e0b;
+ --red: #ef4444;
+
+ color-scheme: light;
+ color: var(--slate);
+ background-color: var(--bg);
font-synthesis: none;
text-rendering: optimizeLegibility;
@@ -21,16 +36,11 @@
}
body {
- margin: 0;
- display: flex;
- place-items: center;
min-width: 320px;
min-height: 100vh;
}
#root {
width: 100%;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
+ min-height: 100vh;
}
diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx
index 6d7ac3d4b..daecd65fa 100644
--- a/apps/web/src/main.tsx
+++ b/apps/web/src/main.tsx
@@ -1,5 +1,5 @@
/**
- * 更新主入口,引入全局样式
+ * V21 设计系统入口
*/
import React from 'react';
import ReactDOM from 'react-dom/client';
@@ -17,17 +17,21 @@ const queryClient = new QueryClient({
queries: {
retry: 1,
refetchOnWindowFocus: false,
- staleTime: 5 * 60 * 1000, // 5 分钟
- gcTime: 10 * 60 * 1000, // 10 分钟
+ staleTime: 5 * 60 * 1000,
+ gcTime: 10 * 60 * 1000,
},
},
});
-// Ant Design 主题配置
+// V21 Ant Design 主题配置
const theme = {
token: {
- colorPrimary: '#1890ff',
- borderRadius: 4,
+ // V21 Indigo 主色
+ colorPrimary: '#4f46e5',
+ // V21 大圆角
+ borderRadius: 14,
+ borderRadiusLG: 22,
+ borderRadiusSM: 12,
},
};
diff --git a/apps/web/src/pages/subscription/Plans.css b/apps/web/src/pages/subscription/Plans.css
index 729dfc609..8fd6a158b 100644
--- a/apps/web/src/pages/subscription/Plans.css
+++ b/apps/web/src/pages/subscription/Plans.css
@@ -1,11 +1,38 @@
-/* V21 订阅计划 */
+/* V21 定价页面 */
.xx-plans-page {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 60px 24px;
}
+/* 页面头部 */
+.xx-page-head {
+ text-align: center;
+ margin-bottom: 60px;
+}
+
+.xx-page-head h2 {
+ font-size: 42px;
+ font-weight: 900;
+ color: var(--slate, #0f172a);
+ margin: 0 0 16px;
+ letter-spacing: -0.02em;
+}
+
+.xx-page-head p {
+ font-size: 18px;
+ color: var(--muted, #64748b);
+ margin: 0;
+ max-width: 560px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/* 定价卡片网格 - 4列 */
.xx-plans-grid {
display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 20px;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 24px;
margin-top: 30px;
}
@@ -18,86 +45,172 @@
@media (max-width: 768px) {
.xx-plans-grid {
grid-template-columns: 1fr;
+ max-width: 400px;
+ margin-left: auto;
+ margin-right: auto;
}
}
+/* V21 定价卡片 */
.xx-plan-card {
- background: rgba(255, 255, 255, 0.94);
- border: 1px solid #e2e8f0;
+ background: rgba(255,255,255,0.94);
+ border: 1px solid rgba(226,232,240,0.95);
border-radius: 28px;
- box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09);
- padding: 28px;
+ box-shadow: 0 24px 70px rgba(15,23,42,0.09);
+ padding: 32px 28px;
position: relative;
- transition: all 0.2s;
+ transition: all 0.3s;
+ display: flex;
+ flex-direction: column;
}
.xx-plan-card:hover {
- border-color: #4f46e5;
- box-shadow: 0 32px 90px rgba(79, 70, 229, 0.15);
+ border-color: var(--indigo, #4f46e5);
+ box-shadow: 0 32px 90px rgba(79,70,229,0.15);
+ transform: translateY(-4px);
}
.xx-plan-card.featured {
- border-color: #4f46e5;
- box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.12), 0 32px 90px rgba(79, 70, 229, 0.15);
+ border: 2px solid var(--indigo, #4f46e5);
+ box-shadow: 0 0 0 4px rgba(79,70,229,0.1), 0 32px 90px rgba(79,70,229,0.15);
+ transform: scale(1.02);
}
+.xx-plan-card.featured:hover {
+ transform: scale(1.02) translateY(-4px);
+}
+
+/* 推荐标签 */
.xx-badge {
position: absolute;
- top: 0;
- right: 24px;
- transform: translateY(-50%);
- background: #4f46e5;
+ top: -12px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
color: white;
- padding: 4px 12px;
+ padding: 6px 16px;
border-radius: 999px;
font-size: 12px;
font-weight: 850;
+ white-space: nowrap;
}
+/* 企业版定制标签 */
+.xx-badge.enterprise {
+ background: linear-gradient(135deg, #f59e0b, #d97706);
+}
+
+/* 套餐名称 */
.xx-plan-card h3 {
- font-size: 24px;
- margin: 0 0 16px;
- color: #0f172a;
+ font-size: 22px;
font-weight: 900;
+ color: var(--slate, #0f172a);
+ margin: 0 0 20px;
+ text-align: center;
}
+/* 价格 */
.xx-plan-price {
- font-size: 42px;
+ text-align: center;
+ margin-bottom: 12px;
+}
+
+.xx-plan-price .currency {
+ font-size: 18px;
+ font-weight: 700;
+ color: var(--muted, #64748b);
+ vertical-align: top;
+}
+
+.xx-plan-price .amount {
+ font-size: 48px;
font-weight: 900;
- color: #4f46e5;
- margin-bottom: 8px;
+ color: var(--indigo, #4f46e5);
+ line-height: 1;
}
-.xx-plan-price span {
+.xx-plan-price .period {
font-size: 16px;
- color: #64748b;
- font-weight: 750;
+ color: var(--muted, #64748b);
+ font-weight: 500;
}
+/* 企业版价格 */
+.xx-plan-price.custom .amount {
+ font-size: 32px;
+}
+
+/* 描述 */
.xx-plan-description {
- color: #64748b;
+ color: var(--muted, #64748b);
font-size: 14px;
+ text-align: center;
margin-bottom: 24px;
+ padding-bottom: 24px;
+ border-bottom: 1px solid var(--line, #e2e8f0);
}
+/* 功能列表 */
.xx-features {
- margin-top: 24px;
+ margin-top: 8px;
padding-top: 24px;
- border-top: 1px solid #e2e8f0;
+ flex: 1;
}
.xx-feature {
display: flex;
- gap: 10px;
+ gap: 12px;
align-items: flex-start;
- color: #64748b;
+ color: var(--muted, #64748b);
font-size: 14px;
- margin-bottom: 12px;
+ margin-bottom: 16px;
line-height: 1.5;
}
-.xx-feature span {
- color: #10b981;
+.xx-feature span:first-child {
+ color: var(--green, #10b981);
font-weight: 900;
flex-shrink: 0;
}
+
+/* 订阅按钮 */
+.xx-subscribe-btn {
+ width: 100%;
+ margin-top: 24px;
+ padding: 14px 24px !important;
+ font-size: 15px !important;
+ font-weight: 850 !important;
+ border-radius: 14px !important;
+ transition: all 0.2s !important;
+}
+
+.xx-subscribe-btn.primary {
+ background: linear-gradient(135deg, #6366f1, #4f46e5) !important;
+ color: white !important;
+ border: none !important;
+ box-shadow: 0 14px 26px rgba(79,70,229,0.22) !important;
+}
+
+.xx-subscribe-btn.primary:hover {
+ box-shadow: 0 18px 34px rgba(79,70,229,0.28) !important;
+ transform: translateY(-1px);
+}
+
+.xx-subscribe-btn.ghost {
+ background: white !important;
+ border: 1px solid var(--line, #e2e8f0) !important;
+ color: var(--slate, #0f172a) !important;
+}
+
+.xx-subscribe-btn.ghost:hover {
+ border-color: var(--indigo, #4f46e5) !important;
+ color: var(--indigo, #4f46e5) !important;
+}
+
+/* 企业版按钮 */
+.xx-subscribe-btn.enterprise {
+ background: linear-gradient(135deg, #f59e0b, #d97706) !important;
+ color: white !important;
+ border: none !important;
+ box-shadow: 0 14px 26px rgba(245,158,11,0.22) !important;
+}
diff --git a/apps/web/src/pages/subscription/Plans.tsx b/apps/web/src/pages/subscription/Plans.tsx
index 99ff8d016..6d952ed2f 100644
--- a/apps/web/src/pages/subscription/Plans.tsx
+++ b/apps/web/src/pages/subscription/Plans.tsx
@@ -1,14 +1,68 @@
/**
- * 订阅/计划页面 - V21 完全对标
+ * 定价页面 - V21 UI 四级定价
*/
import React, { useState } from 'react';
import { message } from 'antd';
import './Plans.css';
const PLANS = [
- { id: 'free', name: 'Free', price: 0, description: '免费试用', recommended: false, features: ['10个项目', '基础视频编辑', '社区支持'] },
- { id: 'pro', name: 'Pro', price: 99, description: '专业用户', recommended: true, features: ['无限项目', '高级编辑', '优先支持', 'API 访问'] },
- { id: 'enterprise', name: 'Enterprise', price: 999, description: '企业级', recommended: false, features: ['定制方案', '专属支持', '白标服务', 'SLA 保证'] },
+ {
+ id: 'free',
+ name: '体验版',
+ price: 0,
+ description: '适合个人体验',
+ recommended: false,
+ features: [
+ '3个视频成片',
+ '基础标题模板',
+ '基础配音音色',
+ '720p导出'
+ ]
+ },
+ {
+ id: 'standard',
+ name: '标准版',
+ price: 99,
+ description: '适合内容创作者',
+ recommended: false,
+ features: [
+ '无限视频成片',
+ '高级标题模板',
+ '全部配音音色',
+ '1080p导出',
+ 'API接口'
+ ]
+ },
+ {
+ id: 'pro',
+ name: '专业版',
+ price: 299,
+ description: '适合专业团队',
+ recommended: true,
+ features: [
+ '无限视频成片',
+ '自定义标题',
+ '全部配音音色',
+ '4K导出',
+ '优先渲染队列',
+ '专属客服'
+ ]
+ },
+ {
+ id: 'enterprise',
+ name: '企业版',
+ price: null,
+ description: '适合企业用户',
+ recommended: false,
+ features: [
+ '私有化部署',
+ '自定义品牌形象',
+ ' SLA服务保障',
+ '技术支持',
+ '团队协作',
+ '数据报表'
+ ]
+ },
];
const Plans: React.FC = () => {
@@ -28,41 +82,57 @@ const Plans: React.FC = () => {
return (
-
-
选择订阅计划
-
升级您的账户享受更多功能
-
+
选择适合您的方案
+
灵活定价,满足不同规模的创作需求
{PLANS.map((plan) => (
-
+
{plan.recommended &&
推荐
}
+ {plan.id === 'enterprise' &&
定制
}
{plan.name}
-
- ¥{plan.price}
-
/月
+
+
+ {plan.price !== null ? (
+ <>
+ ¥
+ {plan.price}
+ /月
+ >
+ ) : (
+ 联系我们
+ )}
+
{plan.description}
-
-
- {plan.features.map((feature: string, idx: number) => (
+ {plan.features.map((feature, idx) => (
✓
- {feature}
+ {feature}
))}
+
+
))}
diff --git a/apps/web/src/pages/workspace/ProjectAssets.css b/apps/web/src/pages/workspace/ProjectAssets.css
index 762900c58..d230650a9 100644
--- a/apps/web/src/pages/workspace/ProjectAssets.css
+++ b/apps/web/src/pages/workspace/ProjectAssets.css
@@ -1,200 +1,208 @@
-/* V21 素材库 */
+/* V21 素材库页面 */
.xx-project-assets {
+ max-width: 1200px;
+ margin: 0 auto;
}
+/* 页面头部 */
+.xx-page-head {
+ margin-bottom: 32px;
+}
+
+.xx-page-head h2 {
+ font-size: 28px;
+ font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 0 0 8px;
+}
+
+.xx-page-head p {
+ font-size: 14px;
+ color: var(--muted, #64748b);
+ margin: 0;
+}
+
+/* V21 大卡片 */
.xx-card {
- background: rgba(255, 255, 255, 0.94);
- border: 1px solid rgba(226, 232, 240, 0.95);
+ background: rgba(255,255,255,0.94);
+ border: 1px solid rgba(226,232,240,0.95);
border-radius: 28px;
- box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09);
+ box-shadow: 0 24px 70px rgba(15,23,42,0.09);
padding: 28px;
- margin-bottom: 20px;
+ margin-bottom: 24px;
+ transition: all 0.25s;
+}
+
+.xx-card:hover {
+ box-shadow: 0 26px 64px rgba(15,23,42,0.14);
+ transform: translateY(-2px);
}
.xx-card h3 {
- font-size: 21px;
- margin: 0 0 16px;
- color: #0f172a;
+ font-size: 18px;
font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 0 0 16px;
}
-.xx-loading {
- padding: 60px 24px;
- text-align: center;
- color: #64748b;
-}
-
+/* 上传区域 */
.xx-upload-zone {
- border: 2px dashed #e2e8f0;
+ border: 2px dashed var(--line, #e2e8f0);
border-radius: 24px;
- padding: 40px;
+ padding: 48px;
text-align: center;
- background: #f8fafc;
+ background: var(--bg, #f8fafc);
cursor: pointer;
transition: all 0.2s;
}
.xx-upload-zone:hover {
- border-color: #4f46e5;
- background: #eef2ff;
+ border-color: var(--indigo, #4f46e5);
+ background: var(--indigo-soft, #eef2ff);
+}
+
+.xx-upload-zone .icon {
+ font-size: 48px;
+ margin-bottom: 16px;
}
.xx-upload-zone p {
- color: #64748b;
+ color: var(--muted, #64748b);
margin: 12px 0;
font-size: 14px;
}
-.xx-video-grid {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 16px;
+/* V21 上传按钮 */
+.xx-upload-btn {
+ background: linear-gradient(135deg, #6366f1, #4f46e5) !important;
+ color: white !important;
+ border: none !important;
+ border-radius: 14px !important;
+ padding: 12px 24px !important;
+ font-weight: 850 !important;
+ box-shadow: 0 14px 26px rgba(79,70,229,0.22) !important;
+ transition: all 0.2s !important;
+ cursor: pointer;
}
-@media (max-width: 1200px) {
- .xx-video-grid {
+.xx-upload-btn:hover {
+ box-shadow: 0 18px 34px rgba(79,70,229,0.28) !important;
+ transform: translateY(-1px);
+}
+
+/* 素材网格 - 9:16 竖屏卡片 */
+.xx-assets-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+ gap: 20px;
+}
+
+@media (max-width: 768px) {
+ .xx-assets-grid {
grid-template-columns: repeat(2, 1fr);
}
}
-@media (max-width: 768px) {
- .xx-video-grid {
+@media (max-width: 480px) {
+ .xx-assets-grid {
grid-template-columns: 1fr;
}
}
-.xx-video-card {
- border: 1px solid #e2e8f0;
+/* V21 素材卡片 - 大圆角 */
+.xx-asset-card {
background: white;
+ border: 1px solid var(--line, #e2e8f0);
border-radius: 22px;
padding: 12px;
- transition: all 0.2s;
+ transition: all 0.25s;
+ cursor: pointer;
}
-.xx-video-card:hover {
- border-color: #4f46e5;
- box-shadow: 0 12px 36px rgba(79, 70, 229, 0.12);
+.xx-asset-card:hover {
+ border-color: var(--indigo, #4f46e5);
+ box-shadow: 0 26px 64px rgba(15,23,42,0.14);
+ transform: translateY(-4px);
}
-.xx-video-thumb {
- aspect-ratio: 16 / 9;
+/* 缩略图 - 9:16 竖屏 */
+.xx-asset-thumb {
+ aspect-ratio: 9 / 16;
border-radius: 16px;
- background: linear-gradient(135deg, #0ea5e9, #312e81);
+ background: linear-gradient(135deg, #6366f1, #0ea5e9, #10b981);
position: relative;
overflow: hidden;
display: grid;
place-items: center;
color: white;
- margin-bottom: 10px;
+ font-size: 32px;
+ margin-bottom: 12px;
}
-.mini-play {
- width: 46px;
- height: 46px;
- border-radius: 50%;
- display: grid;
- place-items: center;
- background: rgba(255, 255, 255, 0.22);
- border: 1px solid rgba(255, 255, 255, 0.3);
- backdrop-filter: blur(8px);
- font-size: 18px;
-}
-
-.xx-video-card b {
- display: block;
- color: #0f172a;
- font-weight: 850;
-}
-
-.xx-video-card p {
- margin: 5px 0 0;
- color: #64748b;
- font-size: 12px;
-}
-
-.row {
- display: flex;
- justify-content: space-between;
+/* 状态标签 - Pill 样式 */
+.xx-asset-status {
+ display: inline-flex;
align-items: center;
- gap: 8px;
- margin-bottom: 4px;
-}
-
-.pill {
+ gap: 4px;
font-size: 11px;
- padding: 3px 7px;
- border-radius: 999px;
font-weight: 850;
+ padding: 3px 10px;
+ border-radius: 999px;
white-space: nowrap;
}
-.pill.ok {
+.xx-asset-status.ready {
background: #dcfce7;
color: #15803d;
}
-.pill.warn {
+.xx-asset-status.processing {
background: #fef3c7;
color: #b45309;
}
-.pill.bad {
- background: #ffe4e6;
- color: #be123c;
+.xx-asset-status.failed {
+ background: #fee2e2;
+ color: #b91c1c;
}
-.assist-actions {
- display: grid;
- gap: 10px;
- margin-top: 16px;
- grid-template-columns: 1fr 1fr;
-}
-
-.btn {
- border: 0;
- border-radius: 14px;
- padding: 12px 17px;
- font-weight: 850;
- cursor: pointer;
+.xx-asset-card b {
+ display: block;
font-size: 14px;
- transition: all 0.2s;
+ font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 8px 0 4px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
-.btn.primary {
- background: #4f46e5;
- color: white;
- box-shadow: 0 16px 28px rgba(79, 70, 229, 0.24);
-}
-
-.btn.primary:hover {
- background: #4338ca;
- box-shadow: 0 20px 36px rgba(79, 70, 229, 0.32);
-}
-
-.btn.primary:disabled {
- opacity: 0.6;
- cursor: not-allowed;
-}
-
-.btn.ghost {
- background: white;
- border: 1px solid #e2e8f0;
- color: #475569;
-}
-
-.btn.ghost:hover {
- background: #f8fafc;
- border-color: #4f46e5;
- color: #4f46e5;
+.xx-asset-card p {
+ font-size: 12px;
+ color: var(--muted, #64748b);
+ margin: 0;
}
+/* 空状态 */
.xx-empty-state {
text-align: center;
- padding: 40px 24px;
- color: #64748b;
+ padding: 60px 24px;
+ color: var(--muted, #64748b);
}
.xx-empty-state p {
font-size: 16px;
- margin: 0;
+ margin: 12px 0;
+}
+
+/* 加载状态 */
+.xx-loading {
+ padding: 60px 24px;
+ text-align: center;
+ color: var(--muted, #64748b);
+}
+
+/* 隐藏文件输入 */
+input[type="file"] {
+ display: none;
}
diff --git a/apps/web/src/pages/workspace/ProjectAssets.tsx b/apps/web/src/pages/workspace/ProjectAssets.tsx
index d748e0584..a6b5ecc29 100644
--- a/apps/web/src/pages/workspace/ProjectAssets.tsx
+++ b/apps/web/src/pages/workspace/ProjectAssets.tsx
@@ -1,5 +1,5 @@
/**
- * 素材库页面 - V21 完全对标
+ * 素材库页面 - V21 UI
*/
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
@@ -26,15 +26,13 @@ const ProjectAssets: React.FC = () => {
return (
-
+
素材管理
+
上传和管理您的视频素材,支持多种格式
- {/* 上传区 */}
+ {/* 上传区域 - V21 设计 */}
-
上传新素材
+
📤 上传素材
e.preventDefault()}
@@ -43,43 +41,46 @@ const ProjectAssets: React.FC = () => {
if (e.dataTransfer.files) handleFileUpload(e.dataTransfer.files);
}}
>
-
📁
-
拖拽文件到这里或点击选择
+
🎬
+
拖拽视频文件到此处,或点击下方按钮上传
+
支持 MP4、MOV、AVI 格式,单个文件最大 500MB
e.target.files && handleFileUpload(e.target.files)}
/>
- {/* 素材列表 */}
+ {/* 素材库 - V21 竖屏卡片网格 */}
-
已上传素材
+
📁 我的素材库
{assets.length === 0 ? (
-
还没有上传任何素材
+
📂
+
还没有上传素材
) : (
-
+
{assets.map((asset) => (
-
-
-
▶
+
+
+ ▶
-
- {asset.name}
-
-
视频素材
+
+ {asset.status === 'processing' ? '⏳ 处理中' : '✓ 就绪'}
+
+
{asset.name}
+
{(asset.size / 1024 / 1024).toFixed(2)} MB
))}
diff --git a/apps/web/src/pages/workspace/ProjectGeneration.css b/apps/web/src/pages/workspace/ProjectGeneration.css
index db7a1de78..3200f16ff 100644
--- a/apps/web/src/pages/workspace/ProjectGeneration.css
+++ b/apps/web/src/pages/workspace/ProjectGeneration.css
@@ -1,11 +1,77 @@
-/* V21 视频剪辑 */
+/* V21 剪辑计划页面 */
.xx-project-generation {
+ max-width: 1200px;
+ margin: 0 auto;
}
+/* 页面头部 */
+.xx-page-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 18px;
+ margin-bottom: 32px;
+}
+
+.xx-page-head h2 {
+ font-size: 28px;
+ font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 0 0 8px;
+}
+
+.xx-page-head p {
+ font-size: 14px;
+ color: var(--muted, #64748b);
+ margin: 0;
+}
+
+/* V21 按钮 */
+.xx-primary-btn {
+ background: linear-gradient(135deg, #6366f1, #4f46e5) !important;
+ color: white !important;
+ border: none !important;
+ border-radius: 14px !important;
+ padding: 12px 24px !important;
+ font-weight: 850 !important;
+ box-shadow: 0 14px 26px rgba(79,70,229,0.22) !important;
+ transition: all 0.2s !important;
+ cursor: pointer;
+}
+
+.xx-primary-btn:hover {
+ box-shadow: 0 18px 34px rgba(79,70,229,0.28) !important;
+ transform: translateY(-1px);
+}
+
+/* V21 卡片 */
+.xx-card {
+ background: rgba(255,255,255,0.94);
+ border: 1px solid rgba(226,232,240,0.95);
+ border-radius: 28px;
+ box-shadow: 0 24px 70px rgba(15,23,42,0.09);
+ padding: 28px;
+ margin-bottom: 24px;
+ transition: all 0.25s;
+}
+
+.xx-card:hover {
+ box-shadow: 0 26px 64px rgba(15,23,42,0.14);
+ transform: translateY(-2px);
+}
+
+.xx-card h3 {
+ font-size: 18px;
+ font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 0 0 20px;
+}
+
+/* 模板网格 */
.xx-template-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
- gap: 14px;
+ gap: 16px;
}
@media (max-width: 1200px) {
@@ -20,59 +86,141 @@
}
}
-.xx-choice {
+/* V21 模板卡片 */
+.xx-choice-card {
position: relative;
- border: 2px solid #e2e8f0;
- border-radius: 18px;
- padding: 14px;
+ border: 2px solid var(--line, #e2e8f0);
+ border-radius: 20px;
+ padding: 0;
background: white;
cursor: pointer;
- transition: all 0.2s;
+ transition: all 0.25s;
+ overflow: hidden;
}
-.xx-choice:hover {
- border-color: #4f46e5;
+.xx-choice-card:hover {
+ border-color: var(--indigo, #4f46e5);
+ box-shadow: 0 12px 36px rgba(79,70,229,0.15);
+ transform: translateY(-2px);
}
-.xx-choice.selected {
- border-color: #4f46e5;
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.16);
+.xx-choice-card.selected {
+ border-color: var(--indigo, #4f46e5);
+ box-shadow: 0 0 0 4px rgba(79,70,229,0.1), 0 12px 36px rgba(79,70,229,0.2);
}
-.check {
+/* 模板封面 */
+.xx-template-cover {
+ height: 100px;
+ border-radius: 18px 18px 0 0;
+ display: grid;
+ place-items: center;
+ color: white;
+ font-size: 32px;
+ margin: 8px 8px 0;
+}
+
+.xx-template-cover.gradient-1 {
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
+}
+
+.xx-template-cover.gradient-2 {
+ background: linear-gradient(135deg, #f97316, #ef4444);
+}
+
+.xx-template-cover.gradient-3 {
+ background: linear-gradient(135deg, #10b981, #0284c7);
+}
+
+.xx-template-cover.gradient-4 {
+ background: linear-gradient(135deg, #8b5cf6, #ec4899);
+}
+
+/* 选中标记 */
+.xx-choice-card.selected .xx-template-cover::after {
+ content: '✓';
position: absolute;
- right: -7px;
- top: -7px;
- width: 26px;
- height: 26px;
+ top: 12px;
+ right: 12px;
+ width: 28px;
+ height: 28px;
border-radius: 50%;
- background: #4f46e5;
+ background: var(--indigo, #4f46e5);
color: white;
display: grid;
place-items: center;
font-weight: 900;
+ font-size: 14px;
}
-.cover {
- height: 78px;
- border-radius: 14px;
- display: grid;
- place-items: center;
- color: white;
- font-size: 28px;
- margin-bottom: 10px;
+.xx-choice-card .xx-template-info {
+ padding: 12px 16px 16px;
}
-.xx-choice b {
+.xx-choice-card b {
+ display: block;
font-size: 15px;
font-weight: 850;
- color: #0f172a;
- display: block;
+ color: var(--slate, #0f172a);
+ margin-bottom: 4px;
}
-.xx-choice p {
- margin: 5px 0 0;
- color: #64748b;
+.xx-choice-card p {
font-size: 12px;
+ color: var(--muted, #64748b);
+ margin: 0;
line-height: 1.4;
}
+
+/* 分栏布局 */
+.xx-generation-layout {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 24px;
+}
+
+@media (max-width: 768px) {
+ .xx-generation-layout {
+ grid-template-columns: 1fr;
+ }
+}
+
+/* 计划预览 */
+.xx-preview-section {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.xx-preview-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 16px;
+ background: var(--bg, #f8fafc);
+ border-radius: 16px;
+}
+
+.xx-preview-item .icon {
+ width: 48px;
+ height: 48px;
+ border-radius: 12px;
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
+ display: grid;
+ place-items: center;
+ font-size: 20px;
+ color: white;
+}
+
+.xx-preview-item h4 {
+ font-size: 14px;
+ font-weight: 850;
+ color: var(--slate, #0f172a);
+ margin: 0 0 4px;
+}
+
+.xx-preview-item p {
+ font-size: 12px;
+ color: var(--muted, #64748b);
+ margin: 0;
+}
diff --git a/apps/web/src/pages/workspace/ProjectGeneration.tsx b/apps/web/src/pages/workspace/ProjectGeneration.tsx
index 8710d8ec3..c64d15b66 100644
--- a/apps/web/src/pages/workspace/ProjectGeneration.tsx
+++ b/apps/web/src/pages/workspace/ProjectGeneration.tsx
@@ -1,15 +1,16 @@
/**
- * 视频剪辑/生成页面 - V21 完全对标
+ * 剪辑计划页面 - V21 UI
*/
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import { Select, Modal, Form, message } from 'antd';
import './ProjectGeneration.css';
-const TITLE_OPTIONS = [
- { id: '1', name: '产品介绍', content: '完整介绍产品功能和优势' },
- { id: '2', name: '用户评价', content: '展示用户真实反馈和评分' },
- { id: '3', name: '功能演示', content: '详细演示产品各项功能' },
+const TEMPLATE_OPTIONS = [
+ { id: '1', name: '知识科普', content: '适合科普、教育类内容' },
+ { id: '2', name: '产品展示', content: '适合电商、产品介绍' },
+ { id: '3', name: '生活分享', content: '适合日常Vlog、生活记录' },
+ { id: '4', name: '新闻资讯', content: '适合新闻、热点解读' },
];
const ProjectGeneration: React.FC = () => {
@@ -21,12 +22,12 @@ const ProjectGeneration: React.FC = () => {
const handleGenerate = async () => {
const values = await form.validateFields();
try {
- message.success('成片生成任务已创建');
+ message.success('开始生成成片');
setGenerateOpen(false);
form.resetFields();
setSelectedTitle('');
} catch (error: any) {
- message.error('创建生成任务失败');
+ message.error('生成失败');
}
};
@@ -34,44 +35,71 @@ const ProjectGeneration: React.FC = () => {
-
视频剪辑
-
生成您的成片
+
剪辑计划
+
选择模板和标题,创建您的视频成片
-
-
-
生成计划
-
- {TITLE_OPTIONS.map((title, idx) => {
- const colors = [
- 'linear-gradient(135deg,#4f46e5,#818cf8)',
- 'linear-gradient(135deg,#f97316,#ef4444)',
- 'linear-gradient(135deg,#10b981,#0284c7)',
- 'linear-gradient(135deg,#64748b,#334155)',
- ];
- return (
-
setSelectedTitle(title.id)}
- >
-
- 📹
+
+ {/* 模板选择 */}
+
+
🎨 选择模板
+
+ {TEMPLATE_OPTIONS.map((title, idx) => {
+ const gradients = ['gradient-1', 'gradient-2', 'gradient-3', 'gradient-4'];
+ return (
+
setSelectedTitle(title.id)}
+ >
+
+ {idx + 1}
+
+
+
{title.name}
+
{title.content}
+
- {selectedTitle === title.id &&
✓
}
-
{title.name}
-
{title.content.substring(0, 50)}...
+ );
+ })}
+
+
+
+ {/* 计划预览 */}
+
+
+
📋 计划概览
+
+
+
✍️
+
+
标题模板
+
{selectedTitle ? TEMPLATE_OPTIONS.find(t => t.id === selectedTitle)?.name : '未选择'}
+
+
+
+
{
label="选择模板"
rules={[{ required: true, message: '请选择模板' }]}
>
-