解决冲突
This commit is contained in:
-442
File diff suppressed because one or more lines are too long
+442
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+37
-37
@@ -1,37 +1,37 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script>
|
||||
(function() {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
try {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
if (info.siteLogo) {
|
||||
var link = document.querySelector('link[rel="icon"]');
|
||||
if (link) {
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script type="module" crossorigin src="/assets/index-BVNhLxFb.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D3IaMBsq.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
</body>
|
||||
</html>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script>
|
||||
(function() {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
try {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
if (info.siteLogo) {
|
||||
var link = document.querySelector('link[rel="icon"]');
|
||||
if (link) {
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script type="module" crossorigin src="/assets/index-B2ULZowz.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -27,6 +27,18 @@ const MOCK_USER: User = {
|
||||
username: 'videomaker',
|
||||
email: 'demo@videogen.ai',
|
||||
credits: 2680,
|
||||
resourceCapacity: {
|
||||
enabled: true,
|
||||
source: 'user',
|
||||
hasUserConfig: true,
|
||||
usedBytes: 298161654,
|
||||
availableBytes: 300349549066,
|
||||
totalBytes: 300647710720,
|
||||
usagePercent: 0.1,
|
||||
exceeded: false,
|
||||
limitValue: '280.000',
|
||||
limitUnit: 'GB',
|
||||
},
|
||||
};
|
||||
|
||||
const MOCK_CREDIT_RECORDS: CreditRecord[] = [
|
||||
|
||||
@@ -61,10 +61,146 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useAuthStore } from '../../store/useAuthStore';
|
||||
import { getMenuConfigs, getRechargePackages, getPaymentMethods, createRechargeOrder, getPaymentOrder, cancelPaymentOrder, getSiteInfo, getUnreadCount, createContactRequest } from '../../api';
|
||||
import { getMenuConfigs, getRechargePackages, getPaymentMethods, createRechargeOrder, getPaymentOrder, cancelPaymentOrder, getSiteInfo, getUnreadCount, createContactRequest, getUser } from '../../api';
|
||||
import NotificationPopup from '../NotificationPopup';
|
||||
import './AppLayout.css';
|
||||
|
||||
// ── ResourceCapacity 类型(与 src/types/index.ts 保持一致) ──
|
||||
type ResourceCapacityData = {
|
||||
enabled: boolean;
|
||||
usedBytes: number;
|
||||
totalBytes: number;
|
||||
availableBytes: number;
|
||||
usagePercent: number;
|
||||
exceeded: boolean;
|
||||
limitValue: string;
|
||||
limitUnit: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 资源存储展示卡片
|
||||
* - enabled === true:显示「已用 / 总额」+ 进度条(超额时变红并提示)
|
||||
* - enabled === false:按 usedBytes 大小自动选 KB / MB / GB / TB 单位显示「当前使用」
|
||||
*/
|
||||
const StorageCard: React.FC<{ data: ResourceCapacityData | null }> = ({ data }) => {
|
||||
if (!data) return null;
|
||||
|
||||
// 单位:后端返回的 limitUnit(KB / MB / GB)
|
||||
const unit = (data.limitUnit || 'GB').toUpperCase();
|
||||
const divisor = unit === 'GB' ? 1024 ** 3 : unit === 'MB' ? 1024 ** 2 : 1024;
|
||||
|
||||
// 百分比(可能 > 100)
|
||||
const rawPercent = Number(data.usagePercent) || 0;
|
||||
// 进度条宽度最多 100%
|
||||
const barPercent = Math.min(100, Math.max(0, rawPercent));
|
||||
|
||||
// 总额:优先用后端 limitValue,兜底 totalBytes / divisor
|
||||
const total = data.limitValue
|
||||
? parseFloat(data.limitValue)
|
||||
: data.totalBytes / divisor;
|
||||
|
||||
// 已用 = 总额 × 百分比 / 100(保证数字与 percent 自洽)
|
||||
const used = (total * rawPercent) / 100;
|
||||
// 剩余 = 总额 - 已用
|
||||
const available = total - used;
|
||||
|
||||
// 超额判断
|
||||
const isOver = data.exceeded || rawPercent >= 100;
|
||||
|
||||
// enabled === false 时按 usedBytes 自动选单位
|
||||
const KB = 1024;
|
||||
const MB = 1024 ** 2;
|
||||
const GB = 1024 ** 3;
|
||||
const TB = 1024 ** 4;
|
||||
const formatUsedAuto = (bytes: number) => {
|
||||
const b = Number(bytes) || 0;
|
||||
if (b >= TB) return { val: (b / TB).toFixed(2), unit: 'TB' };
|
||||
if (b >= GB) return { val: (b / GB).toFixed(2), unit: 'GB' };
|
||||
if (b >= MB) return { val: (b / MB).toFixed(2), unit: 'MB' };
|
||||
return { val: (b / KB).toFixed(2), unit: 'KB' };
|
||||
};
|
||||
const usedAuto = formatUsedAuto(data.usedBytes);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
marginTop: 12,
|
||||
padding: '10px 12px',
|
||||
borderRadius: 10,
|
||||
background: 'linear-gradient(135deg, rgba(248, 250, 252, 0.9) 0%, rgba(241, 245, 249, 0.9) 100%)',
|
||||
border: `1px solid ${isOver ? 'rgba(239, 68, 68, 0.25)' : 'rgba(99, 102, 241, 0.15)'}`,
|
||||
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.04)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 6,
|
||||
fontSize: 12,
|
||||
color: '#475569',
|
||||
}}
|
||||
>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<DatabaseOutlined style={{ fontSize: 12, color: isOver ? '#ef4444' : '#6366f1' }} />
|
||||
资源存储
|
||||
</span>
|
||||
{data.enabled ? (
|
||||
<span style={{ fontWeight: 500, color: isOver ? '#ef4444' : '#1e293b' }}>
|
||||
{used.toFixed(2)} / {total.toFixed(2)} {unit}
|
||||
</span>
|
||||
) : (
|
||||
<span style={{ fontWeight: 500, color: '#1e293b' }}>
|
||||
当前使用 {usedAuto.val} {usedAuto.unit}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{data.enabled && (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 6,
|
||||
background: '#e2e8f0',
|
||||
borderRadius: 3,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: `${barPercent}%`,
|
||||
height: '100%',
|
||||
background: isOver
|
||||
? 'linear-gradient(90deg, #ef4444, #dc2626)'
|
||||
: 'linear-gradient(90deg, #6366f1, #8b5cf6)',
|
||||
borderRadius: 3,
|
||||
transition: 'width 0.4s ease',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 4,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
fontSize: 11,
|
||||
color: isOver ? '#ef4444' : '#94a3b8',
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{isOver
|
||||
? `存储超额 · 超用 ${Math.abs(available).toFixed(2)} ${unit}`
|
||||
: `剩余 ${available.toFixed(2)} ${unit}`}
|
||||
</span>
|
||||
<span>{rawPercent.toFixed(1)}%</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface MenuConfig {
|
||||
id: string;
|
||||
key?: string;
|
||||
@@ -186,6 +322,18 @@ const AppLayout: React.FC = () => {
|
||||
const currentOrderNoRef = useRef<string | null>(null);
|
||||
const [enabledMethods, setEnabledMethods] = useState<{ alipay: boolean; wechat: boolean }>({ alipay: false, wechat: false });
|
||||
|
||||
// 资源存储容量(从 getUser().resource_capacity 获取)
|
||||
const [resourceCapacity, setResourceCapacity] = useState<{
|
||||
enabled: boolean;
|
||||
usedBytes: number;
|
||||
totalBytes: number;
|
||||
availableBytes: number;
|
||||
usagePercent: number;
|
||||
exceeded: boolean;
|
||||
limitValue: string;
|
||||
limitUnit: string;
|
||||
} | null>(null);
|
||||
|
||||
const PENDING_ORDER_KEY = 'pending_payment_order';
|
||||
|
||||
useEffect(() => {
|
||||
@@ -212,6 +360,30 @@ const AppLayout: React.FC = () => {
|
||||
|
||||
localStorage.setItem('siteInfo', JSON.stringify({ siteName: name, siteLogo: logo }));
|
||||
}).catch(() => { });
|
||||
|
||||
getUser().then((res: any) => {
|
||||
// console.log('[Storage] getUser 返回:', res);
|
||||
|
||||
const rc = res?.resourceCapacity;
|
||||
if (rc) {
|
||||
setResourceCapacity({
|
||||
enabled: !!rc.enabled,
|
||||
usedBytes: Number(rc.usedBytes) || 0,
|
||||
totalBytes: Number(rc.totalBytes) || 0,
|
||||
availableBytes: Number(rc.availableBytes) || 0,
|
||||
usagePercent: Number(rc.usagePercent) || 0,
|
||||
exceeded: !!rc.exceeded,
|
||||
limitValue: rc.limitValue ?? '',
|
||||
limitUnit: rc.limitUnit || 'GB',
|
||||
});
|
||||
}
|
||||
// 没数据时不显示
|
||||
}).catch((err: any) => {
|
||||
// console.error('[Storage] getUser 失败:', err);
|
||||
// 接口失败也不显示
|
||||
});
|
||||
|
||||
|
||||
}, []);
|
||||
|
||||
const handleContactMouseDown = (e: React.MouseEvent) => {
|
||||
@@ -674,6 +846,9 @@ const AppLayout: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</Dropdown>
|
||||
|
||||
{/* 资源存储容量展示(来自 getUser.resourceCapacity) */}
|
||||
<StorageCard data={resourceCapacity} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -768,6 +943,9 @@ const AppLayout: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 资源存储容量展示(与桌面端共用 StorageCard) */}
|
||||
<StorageCard data={resourceCapacity} />
|
||||
|
||||
{topLevelItems.map(item => {
|
||||
const menuType = item.menu_type ?? item.menuType;
|
||||
const hasChildren = childMap[item.id] && childMap[item.id].length > 0;
|
||||
|
||||
+564
-158
@@ -3,20 +3,26 @@
|
||||
:root {
|
||||
--font-sans: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
--nav-bg: #f8f9fb;
|
||||
--nav-surface: rgba(0,0,0,0.02);
|
||||
--nav-surface: rgba(0, 0, 0, 0.02);
|
||||
--nav-border: #e5e7eb;
|
||||
--nav-text: #1f2937;
|
||||
--nav-text-muted: #6b7280;
|
||||
--nav-hover: rgba(0,0,0,0.04);
|
||||
--nav-active: rgba(99,102,241,0.08);
|
||||
--nav-hover: rgba(0, 0, 0, 0.04);
|
||||
--nav-active: rgba(99, 102, 241, 0.08);
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after { box-sizing: border-box; }
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0; padding: 0;
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: var(--font-sans);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
@@ -24,23 +30,68 @@ html, body {
|
||||
color: #1a1a2e;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
#root { min-height: 100vh; }
|
||||
|
||||
|
||||
#root {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Scrollbar ─────────────────────────── */
|
||||
::-webkit-scrollbar { width: 5px; height: 5px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #d1d5db;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #9ca3af;
|
||||
}
|
||||
|
||||
/* ── Electric Border Animation ─────────── */
|
||||
@keyframes electric-pulse {
|
||||
0%, 100% { opacity: 0.4; filter: blur(1px); }
|
||||
50% { opacity: 1; filter: blur(0); }
|
||||
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.4;
|
||||
filter: blur(1px);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
filter: blur(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes electric-flow {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.content_box {
|
||||
margin: -24px -32px -32px;
|
||||
border-radius: 0 0 16px 16px;
|
||||
height: calc(100vh - 34px);
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.electric-border-card {
|
||||
@@ -51,16 +102,14 @@ html, body {
|
||||
position: absolute;
|
||||
inset: -2px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
#6366f1,
|
||||
#8b5cf6,
|
||||
#a855f7,
|
||||
#6366f1,
|
||||
#8b5cf6,
|
||||
#a855f7,
|
||||
#6366f1
|
||||
);
|
||||
background: linear-gradient(90deg,
|
||||
#6366f1,
|
||||
#8b5cf6,
|
||||
#a855f7,
|
||||
#6366f1,
|
||||
#8b5cf6,
|
||||
#a855f7,
|
||||
#6366f1);
|
||||
background-size: 300% 100%;
|
||||
animation: electric-flow 3s linear infinite, electric-pulse 2s ease-in-out infinite;
|
||||
z-index: 0;
|
||||
@@ -85,6 +134,7 @@ html, body {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
@@ -97,16 +147,14 @@ html, body {
|
||||
.shiny-text {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
#6366f1 0%,
|
||||
#8b5cf6 20%,
|
||||
#a855f7 40%,
|
||||
#c084fc 50%,
|
||||
#a855f7 60%,
|
||||
#8b5cf6 80%,
|
||||
#6366f1 100%
|
||||
);
|
||||
background: linear-gradient(90deg,
|
||||
#6366f1 0%,
|
||||
#8b5cf6 20%,
|
||||
#a855f7 40%,
|
||||
#c084fc 50%,
|
||||
#a855f7 60%,
|
||||
#8b5cf6 80%,
|
||||
#6366f1 100%);
|
||||
background-size: 200% auto;
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
@@ -118,92 +166,225 @@ html, body {
|
||||
|
||||
/* ── Keyframe Animations ───────────────── */
|
||||
@keyframes fadeInUp {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInLeft {
|
||||
from { opacity: 0; transform: translateX(-20px); }
|
||||
to { opacity: 1; transform: translateX(0); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRight {
|
||||
from { opacity: 0; transform: translateX(20px); }
|
||||
to { opacity: 1; transform: translateX(0); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float1 {
|
||||
0%, 100% { transform: translate(0, 0) scale(1); }
|
||||
50% { transform: translate(20px, -30px) scale(1.05); }
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(20px, -30px) scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float2 {
|
||||
0%, 100% { transform: translate(0, 0) scale(1); }
|
||||
50% { transform: translate(-15px, 20px) scale(0.95); }
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(-15px, 20px) scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float3 {
|
||||
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
||||
50% { transform: translate(10px, -15px) rotate(3deg); }
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(10px, -15px) rotate(3deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInCard {
|
||||
from { opacity: 0; transform: translateY(14px) scale(0.97); }
|
||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(14px) scale(0.97);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinSlow {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fadeInUp { animation: fadeInUp 0.45s ease-out both; }
|
||||
.animate-fadeInLeft { animation: fadeInLeft 0.55s ease-out both; }
|
||||
.animate-fadeInRight { animation: fadeInRight 0.55s ease-out both; }
|
||||
.animate-slideInCard { animation: slideInCard 0.4s ease-out both; }
|
||||
.animate-float1 { animation: float1 8s ease-in-out infinite; }
|
||||
.animate-float2 { animation: float2 10s ease-in-out infinite; }
|
||||
.animate-float3 { animation: float3 12s ease-in-out infinite; }
|
||||
.animate-fadeInUp {
|
||||
animation: fadeInUp 0.45s ease-out both;
|
||||
}
|
||||
|
||||
.ref-thumb:hover .ref-delete { opacity: 1 !important; }
|
||||
.animate-fadeInLeft {
|
||||
animation: fadeInLeft 0.55s ease-out both;
|
||||
}
|
||||
|
||||
.stagger-children > *:nth-child(1) { animation-delay: 0.04s; }
|
||||
.stagger-children > *:nth-child(2) { animation-delay: 0.10s; }
|
||||
.stagger-children > *:nth-child(3) { animation-delay: 0.16s; }
|
||||
.stagger-children > *:nth-child(4) { animation-delay: 0.22s; }
|
||||
.stagger-children > *:nth-child(5) { animation-delay: 0.28s; }
|
||||
.stagger-children > *:nth-child(6) { animation-delay: 0.34s; }
|
||||
.animate-fadeInRight {
|
||||
animation: fadeInRight 0.55s ease-out both;
|
||||
}
|
||||
|
||||
.animate-slideInCard {
|
||||
animation: slideInCard 0.4s ease-out both;
|
||||
}
|
||||
|
||||
.animate-float1 {
|
||||
animation: float1 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-float2 {
|
||||
animation: float2 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-float3 {
|
||||
animation: float3 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.ref-thumb:hover .ref-delete {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(1) {
|
||||
animation-delay: 0.04s;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(2) {
|
||||
animation-delay: 0.10s;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(3) {
|
||||
animation-delay: 0.16s;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(4) {
|
||||
animation-delay: 0.22s;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(5) {
|
||||
animation-delay: 0.28s;
|
||||
}
|
||||
|
||||
.stagger-children>*:nth-child(6) {
|
||||
animation-delay: 0.34s;
|
||||
}
|
||||
|
||||
/* ── Ant Design Overrides ──────────────── */
|
||||
.ant-input, .ant-input-affix-wrapper, .ant-select-selector, .ant-input-number {
|
||||
.ant-input,
|
||||
.ant-input-affix-wrapper,
|
||||
.ant-select-selector,
|
||||
.ant-input-number {
|
||||
border-radius: 10px !important;
|
||||
transition: all 0.25s ease !important;
|
||||
}
|
||||
.ant-input:focus, .ant-input-affix-wrapper:focus, .ant-input-affix-wrapper-focused,
|
||||
|
||||
.ant-input:focus,
|
||||
.ant-input-affix-wrapper:focus,
|
||||
.ant-input-affix-wrapper-focused,
|
||||
.ant-select-focused .ant-select-selector {
|
||||
box-shadow: 0 0 0 3px rgba(99,102,241,0.12) !important;
|
||||
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12) !important;
|
||||
border-color: #6366f1 !important;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
border-radius: 10px !important;
|
||||
transition: all 0.25s ease !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
.ant-btn:hover { transform: none; }
|
||||
.ant-btn:active { transform: translateY(0); }
|
||||
.ant-card { border-radius: 16px !important; transition: all 0.3s ease !important; }
|
||||
.ant-modal-content { border-radius: 20px !important; overflow: hidden; }
|
||||
.ant-tag { font-size: 12px; border-radius: 8px !important; }
|
||||
|
||||
.ant-btn:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.ant-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.ant-card {
|
||||
border-radius: 16px !important;
|
||||
transition: all 0.3s ease !important;
|
||||
}
|
||||
|
||||
.ant-modal-content {
|
||||
border-radius: 20px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ant-tag {
|
||||
font-size: 12px;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
/* ── Recharge card hover ───────────────── */
|
||||
.recharge-card {
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.recharge-card:hover {
|
||||
transform: translateY(-8px) scale(1.02) !important;
|
||||
box-shadow: 0 20px 40px rgba(99,102,241,0.15) !important;
|
||||
box-shadow: 0 20px 40px rgba(99, 102, 241, 0.15) !important;
|
||||
}
|
||||
|
||||
.recharge-card .recharge-price {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.recharge-card:hover .recharge-price {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
.recharge-card .recharge-price { transition: all 0.3s ease; }
|
||||
.recharge-card:hover .recharge-price { transform: scale(1.08); }
|
||||
|
||||
/* ── Homepage tabs ────────────────────── */
|
||||
.homepage-tabs .ant-tabs-nav {
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-tab {
|
||||
padding: 8px 16px !important;
|
||||
font-size: 13px !important;
|
||||
@@ -211,13 +392,16 @@ html, body {
|
||||
color: #6b7280 !important;
|
||||
transition: all 0.25s !important;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-tab:hover {
|
||||
color: #6366f1 !important;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-tab-active .ant-tabs-tab-btn {
|
||||
color: #6366f1 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-ink-bar {
|
||||
background: linear-gradient(90deg, #6366f1, #a855f7) !important;
|
||||
height: 3px !important;
|
||||
@@ -230,108 +414,249 @@ html, body {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
transform: translateY(-4px) !important;
|
||||
box-shadow: 0 16px 40px rgba(99,102,241,0.12) !important;
|
||||
box-shadow: 0 16px 40px rgba(99, 102, 241, 0.12) !important;
|
||||
border-color: #6366f1 !important;
|
||||
}
|
||||
|
||||
/* ── Mobile Bottom Nav ─────────────────── */
|
||||
.mobile-bottom-nav {
|
||||
display: none;
|
||||
position: fixed; bottom: 0; left: 0; right: 0; z-index: 200;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 200;
|
||||
height: 60px;
|
||||
background: rgba(255,255,255,0.95);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(24px);
|
||||
border-top: 1px solid rgba(0,0,0,0.05);
|
||||
box-shadow: 0 -4px 20px rgba(0,0,0,0.06);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item {
|
||||
flex: 1; display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center; gap: 2px;
|
||||
cursor: pointer; transition: all 0.2s;
|
||||
color: #8b8fa3; font-size: 9px; font-weight: 400;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: #8b8fa3;
|
||||
font-size: 9px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item.active {
|
||||
color: #08080c;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item .nav-icon {
|
||||
font-size: 18px; transition: transform 0.2s;
|
||||
font-size: 18px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item.active .nav-icon {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* ── Responsive Breakpoints ────────────── */
|
||||
@media (max-width: 768px) {
|
||||
.desktop-sidebar { display: none !important; }
|
||||
.desktop-content { margin-left: 0 !important; padding: 16px !important; padding-bottom: 80px !important; overflow-x: hidden !important; }
|
||||
.desktop-sidebar-toggle-zone { display: none !important; }
|
||||
.mobile-bottom-nav { display: flex !important; }
|
||||
.desktop-sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.desktop-content {
|
||||
margin-left: 0 !important;
|
||||
padding: 16px !important;
|
||||
padding-bottom: 80px !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.desktop-sidebar-toggle-zone {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* Prevent horizontal overflow globally */
|
||||
html, body { overflow-x: hidden !important; }
|
||||
html,
|
||||
body {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.mobile-hide { display: none !important; }
|
||||
.mobile-full { width: 100% !important; max-width: 100% !important; }
|
||||
.mobile-stack { flex-direction: column !important; }
|
||||
.mobile-p-16 { padding: 16px !important; }
|
||||
.mobile-gap-12 { gap: 12px !important; }
|
||||
.mobile-hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mobile-full {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.mobile-stack {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.mobile-p-16 {
|
||||
padding: 16px !important;
|
||||
}
|
||||
|
||||
.mobile-gap-12 {
|
||||
gap: 12px !important;
|
||||
}
|
||||
|
||||
/* Login page */
|
||||
.login-page { flex-direction: column !important; }
|
||||
.login-left { display: none !important; }
|
||||
.login-right { padding: 24px 16px !important; }
|
||||
.login-card { width: 100% !important; }
|
||||
.login-page {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.login-left {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.login-right {
|
||||
padding: 24px 16px !important;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Project list */
|
||||
.project-item { flex-direction: column !important; align-items: flex-start !important; }
|
||||
.project-item .project-actions { margin-left: 0 !important; margin-top: 12px; width: 100%; justify-content: flex-end; }
|
||||
.project-item {
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
|
||||
.project-item .project-actions {
|
||||
margin-left: 0 !important;
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* Generate page header */
|
||||
.gen-header { flex-direction: column !important; gap: 12px !important; padding: 16px 18px !important; }
|
||||
.gen-header {
|
||||
flex-direction: column !important;
|
||||
gap: 12px !important;
|
||||
padding: 16px 18px !important;
|
||||
}
|
||||
|
||||
/* Operation flow bar */
|
||||
.gen-flow-bar { flex-direction: column !important; gap: 14px !important; padding: 16px !important; }
|
||||
.gen-flow-divider { display: none !important; }
|
||||
.gen-flow-bar {
|
||||
flex-direction: column !important;
|
||||
gap: 14px !important;
|
||||
padding: 16px !important;
|
||||
}
|
||||
|
||||
.gen-flow-divider {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Config form params row */
|
||||
.gen-form-row { flex-direction: column !important; gap: 0 !important; }
|
||||
.gen-form-row {
|
||||
flex-direction: column !important;
|
||||
gap: 0 !important;
|
||||
}
|
||||
|
||||
/* Credits estimate bar */
|
||||
.gen-credits-bar { flex-direction: column !important; gap: 8px !important; text-align: center; }
|
||||
.gen-credits-bar {
|
||||
flex-direction: column !important;
|
||||
gap: 8px !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Prompt rows */
|
||||
.gen-prompt-row { flex-direction: column !important; }
|
||||
.gen-prompt-row > * { width: 100% !important; }
|
||||
.gen-params { flex-wrap: wrap !important; gap: 8px !important; }
|
||||
.gen-params > div { flex: 1 1 45% !important; min-width: 0; }
|
||||
.gen-prompt-row {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.gen-prompt-row>* {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.gen-params {
|
||||
flex-wrap: wrap !important;
|
||||
gap: 8px !important;
|
||||
}
|
||||
|
||||
.gen-params>div {
|
||||
flex: 1 1 45% !important;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Expanded detail left+right stacks */
|
||||
.gen-detail-row { flex-direction: column !important; }
|
||||
.gen-detail-row > * { width: 100% !important; min-width: 0 !important; flex: 1 1 auto !important; }
|
||||
.gen-detail-row {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.gen-detail-row>* {
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
flex: 1 1 auto !important;
|
||||
}
|
||||
|
||||
/* Record filter bar stacks */
|
||||
.record-filter-bar { flex-direction: column !important; }
|
||||
.record-filter-bar .ant-space { flex-wrap: wrap !important; }
|
||||
.record-filter-bar .ant-select { width: 100% !important; }
|
||||
.record-filter-bar {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.record-filter-bar .ant-space {
|
||||
flex-wrap: wrap !important;
|
||||
}
|
||||
|
||||
.record-filter-bar .ant-select {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Record summary row stacks */
|
||||
.record-item { flex-direction: column !important; align-items: flex-start !important; gap: 8px !important; overflow: hidden !important; }
|
||||
.record-item .record-actions { width: 100% !important; justify-content: flex-end; }
|
||||
.record-item > span[style*="textOverflow"] { white-space: normal !important; overflow: visible !important; text-overflow: unset !important; }
|
||||
.record-item {
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start !important;
|
||||
gap: 8px !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.record-item .record-actions {
|
||||
width: 100% !important;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.record-item>span[style*="textOverflow"] {
|
||||
white-space: normal !important;
|
||||
overflow: visible !important;
|
||||
text-overflow: unset !important;
|
||||
}
|
||||
|
||||
/* Hide less important meta on mobile */
|
||||
.mobile-meta { display: none !important; }
|
||||
.mobile-meta {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Credits page */
|
||||
.credits-balance { flex-direction: column !important; }
|
||||
.recharge-grid { flex-direction: column !important; }
|
||||
.recharge-grid > * { width: 100% !important; }
|
||||
.credits-balance {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.recharge-grid {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.recharge-grid>* {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Video player fits mobile */
|
||||
video { max-width: 100% !important; }
|
||||
video {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
/* InitialReplication page */
|
||||
.replication-container {
|
||||
@@ -340,17 +665,20 @@ html, body {
|
||||
padding: 16px !important;
|
||||
height: calc(100vh - 64px) !important;
|
||||
}
|
||||
|
||||
.replication-preview {
|
||||
width: 100% !important;
|
||||
height: 30vh !important;
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
.replication-form {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
max-height: calc(70vh - 32px) !important;
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
|
||||
.replication-form-content {
|
||||
padding: 16px !important;
|
||||
max-height: calc(70vh - 64px) !important;
|
||||
@@ -358,56 +686,92 @@ html, body {
|
||||
}
|
||||
|
||||
/* ── Date Display ──────────────────────── */
|
||||
.date-display { font-family: 'SF Mono', 'Menlo', 'Consolas', monospace; }
|
||||
.date-display {
|
||||
font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
|
||||
}
|
||||
|
||||
/* ── Small Mobile Breakpoint (max-width: 480px) ────────────── */
|
||||
@media (max-width: 480px) {
|
||||
|
||||
/* Base styles */
|
||||
html, body { font-size: 14px !important; }
|
||||
html,
|
||||
body {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
/* Login page */
|
||||
.login-card { width: 100% !important; }
|
||||
.login-right { padding: 16px !important; }
|
||||
.login-card {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.login-right {
|
||||
padding: 16px !important;
|
||||
}
|
||||
|
||||
/* Header adjustments */
|
||||
.gen-header { padding: 12px 14px !important; }
|
||||
.gen-header {
|
||||
padding: 12px 14px !important;
|
||||
}
|
||||
|
||||
/* Form elements */
|
||||
.gen-form-row { gap: 8px !important; }
|
||||
|
||||
.gen-form-row {
|
||||
gap: 8px !important;
|
||||
}
|
||||
|
||||
/* Button adjustments */
|
||||
.ant-btn { height: 36px !important; font-size: 13px !important; padding: 0 12px !important; }
|
||||
|
||||
.ant-btn {
|
||||
height: 36px !important;
|
||||
font-size: 13px !important;
|
||||
padding: 0 12px !important;
|
||||
}
|
||||
|
||||
/* Input adjustments */
|
||||
.ant-input, .ant-input-affix-wrapper, .ant-select-selector {
|
||||
height: 36px !important;
|
||||
.ant-input,
|
||||
.ant-input-affix-wrapper,
|
||||
.ant-select-selector {
|
||||
height: 36px !important;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
/* Card padding */
|
||||
.ant-card { padding: 12px !important; }
|
||||
.ant-card {
|
||||
padding: 12px !important;
|
||||
}
|
||||
|
||||
/* Mobile bottom nav adjustments */
|
||||
.mobile-bottom-nav { height: 56px !important; }
|
||||
.mobile-bottom-nav .nav-item .nav-icon { font-size: 18px !important; }
|
||||
.mobile-bottom-nav .nav-item { font-size: 9px !important; gap: 2px !important; }
|
||||
.mobile-bottom-nav {
|
||||
height: 56px !important;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item .nav-icon {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
.mobile-bottom-nav .nav-item {
|
||||
font-size: 9px !important;
|
||||
gap: 2px !important;
|
||||
}
|
||||
|
||||
/* InitialReplication page - Small Mobile */
|
||||
.replication-container {
|
||||
padding: 12px !important;
|
||||
gap: 12px !important;
|
||||
}
|
||||
|
||||
.replication-preview {
|
||||
height: 25vh !important;
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
|
||||
.replication-form-content {
|
||||
padding: 12px !important;
|
||||
}
|
||||
|
||||
.replication-form-content .ant-btn {
|
||||
height: 36px !important;
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.replication-form-content .ant-input,
|
||||
.replication-form-content .ant-input-affix-wrapper {
|
||||
height: 36px !important;
|
||||
@@ -415,30 +779,56 @@ html, body {
|
||||
}
|
||||
|
||||
/* Video and image containers */
|
||||
video, img {
|
||||
max-height: 160px !important;
|
||||
video,
|
||||
img {
|
||||
max-height: 160px !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
/* Upload areas */
|
||||
.upload-area { padding: 12px !important; }
|
||||
.upload-area {
|
||||
padding: 12px !important;
|
||||
}
|
||||
|
||||
/* Spacing adjustments */
|
||||
.mobile-p-16 { padding: 12px !important; }
|
||||
.mobile-gap-12 { gap: 8px !important; }
|
||||
.mobile-p-16 {
|
||||
padding: 12px !important;
|
||||
}
|
||||
|
||||
.mobile-gap-12 {
|
||||
gap: 8px !important;
|
||||
}
|
||||
|
||||
/* Font size adjustments */
|
||||
h1 { font-size: 18px !important; }
|
||||
h2 { font-size: 16px !important; }
|
||||
h3 { font-size: 14px !important; }
|
||||
p { font-size: 12px !important; }
|
||||
h1 {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
/* Button text */
|
||||
.btn-text-sm { font-size: 12px !important; }
|
||||
.btn-text-sm {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
/* Margin adjustments */
|
||||
.mobile-mb-8 { margin-bottom: 8px !important; }
|
||||
.mobile-mb-12 { margin-bottom: 12px !important; }
|
||||
.mobile-mb-8 {
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.mobile-mb-12 {
|
||||
margin-bottom: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Tablet Breakpoint (769px to 1024px) ────────────── */
|
||||
@@ -450,33 +840,49 @@ html, body {
|
||||
*/
|
||||
|
||||
/* Card max-width */
|
||||
.ant-card { max-width: calc(50% - 8px) !important; }
|
||||
.ant-card {
|
||||
max-width: calc(50% - 8px) !important;
|
||||
}
|
||||
|
||||
/* Font adjustments */
|
||||
html, body { font-size: 15px !important; }
|
||||
html,
|
||||
body {
|
||||
font-size: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Large Desktop Breakpoint (min-width: 1200px) ────────────── */
|
||||
@media (min-width: 1200px) {
|
||||
|
||||
/* Max width container */
|
||||
.max-w-container { max-width: 1400px; margin: 0 auto; }
|
||||
.max-w-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Card grid */
|
||||
.card-grid { grid-template-columns: repeat(3, 1fr) !important; }
|
||||
.card-grid {
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── HomePage Tabs ────────────── */
|
||||
.homepage-tabs .ant-tabs-nav { margin-bottom: 0; }
|
||||
.homepage-tabs .ant-tabs-nav {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-tab {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 8px 20px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-tab-active {
|
||||
color: #6366f1;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.homepage-tabs .ant-tabs-ink-bar {
|
||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||
}
|
||||
}
|
||||
@@ -8,127 +8,326 @@ import {
|
||||
PlayCircleOutlined,
|
||||
CheckCircleOutlined,
|
||||
HeartOutlined,
|
||||
EyeOutlined,
|
||||
ArrowRightOutlined,
|
||||
CrownOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const CreativePlazaPage: React.FC = () => {
|
||||
const handleUnlock = () => {
|
||||
message.info('请联系客服开通');
|
||||
message.info('请联系客服开通会员');
|
||||
};
|
||||
|
||||
|
||||
// 顶部特性卡片
|
||||
const features = [
|
||||
{
|
||||
icon: <ThunderboltOutlined style={{ fontSize: 28, color: '#8b5cf6' }} />,
|
||||
title: 'AI智能生成',
|
||||
description: '先进的AI技术,一键生成高质量视频内容',
|
||||
icon: <ThunderboltOutlined style={{ fontSize: 26, color: '#8b5cf6' }} />,
|
||||
title: 'AI 智能生成',
|
||||
description: '先进 AI 技术一键产出高质量视频内容',
|
||||
},
|
||||
{
|
||||
icon: <PlayCircleOutlined style={{ fontSize: 28, color: '#ec4899' }} />,
|
||||
icon: <PlayCircleOutlined style={{ fontSize: 26, color: '#ec4899' }} />,
|
||||
title: '多格式输出',
|
||||
description: '支持多种视频格式,满足不同场景需求',
|
||||
description: '支持多种视频格式,满足不同场景需求',
|
||||
},
|
||||
{
|
||||
icon: <CheckCircleOutlined style={{ fontSize: 28, color: '#10b981' }} />,
|
||||
icon: <CheckCircleOutlined style={{ fontSize: 26, color: '#10b981' }} />,
|
||||
title: '品质保证',
|
||||
description: '专业级画质,细节清晰,色彩鲜艳',
|
||||
description: '专业级画质,细节清晰,色彩鲜艳',
|
||||
},
|
||||
{
|
||||
icon: <HeartOutlined style={{ fontSize: 28, color: '#f59e0b' }} />,
|
||||
icon: <HeartOutlined style={{ fontSize: 26, color: '#f59e0b' }} />,
|
||||
title: '创意无限',
|
||||
description: '丰富的模板和风格,激发创作灵感',
|
||||
description: '丰富模板与风格,激发创作灵感',
|
||||
},
|
||||
];
|
||||
|
||||
// 精选案例占位
|
||||
const caseList = [
|
||||
{ title: '美妆直播切片', tag: '热门', tagColor: '#ef4444' },
|
||||
{ title: '3C 数码测评', tag: '推荐', tagColor: '#6366f1' },
|
||||
{ title: '美食探店 vlog', tag: '推荐', tagColor: '#6366f1' },
|
||||
{ title: '服饰穿搭合集', tag: '热门', tagColor: '#ef4444' },
|
||||
{ title: '家居场景展示', tag: '推荐', tagColor: '#6366f1' },
|
||||
{ title: '母婴亲子内容', tag: '热门', tagColor: '#ef4444' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px 0' }}>
|
||||
<div style={{ marginBottom: 32 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
|
||||
<div style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 14,
|
||||
background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 4px 16px rgba(139,92,246,0.3)',
|
||||
}}>
|
||||
<GiftOutlined style={{ fontSize: 22, color: '#fff' }} />
|
||||
<div className="content_box">
|
||||
{/* 顶部 Hero 区域 */}
|
||||
<div
|
||||
className="animate-fadeInUp"
|
||||
style={{
|
||||
padding: '28px 32px',
|
||||
borderRadius: 16,
|
||||
background: 'linear-gradient(135deg, #f5f3ff 0%, #ede9fe 50%, #fce7f3 100%)',
|
||||
border: '1px solid rgba(139, 92, 246, 0.12)',
|
||||
marginBottom: 24,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 12 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: 14,
|
||||
background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 6px 20px rgba(139, 92, 246, 0.3)',
|
||||
}}
|
||||
>
|
||||
<GiftOutlined style={{ fontSize: 24, color: '#fff' }} />
|
||||
</div>
|
||||
<div>
|
||||
<Typography.Title level={2} style={{ margin: 0, color: '#1e293b', fontWeight: 700 }}>
|
||||
创意素材案例
|
||||
<span style={{ color: '#6366f1', fontSize: 14, fontWeight: 400, marginLeft: 8 }}>
|
||||
探索AI创作无限可能
|
||||
<div className="shiny-text-container" style={{ marginBottom: 4 }}>
|
||||
<span className="shiny-text" style={{ fontSize: 26, fontWeight: 700 }}>
|
||||
创意素材案例
|
||||
</span>
|
||||
</Typography.Title>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: '#7c3aed' }}>
|
||||
<CrownOutlined style={{ fontSize: 12 }} />
|
||||
<span>探索 AI 创作无限可能</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Typography.Text style={{ color: '#64748b' }}>
|
||||
精选AI生成的优秀素材案例,展示AI创作的无限潜力与创意灵感
|
||||
<Typography.Text style={{ color: '#64748b', fontSize: 14, lineHeight: 1.7 }}>
|
||||
精选 AI 生成的优秀素材案例,展示 AI 创作的无限潜力与创意灵感
|
||||
</Typography.Text>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 20, marginBottom: 32 }}>
|
||||
{/* 特性卡片 */}
|
||||
{/* <div
|
||||
className="animate-fadeInUp stagger-children"
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(4, 1fr)',
|
||||
gap: 16,
|
||||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
{features.map((feature, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
bordered={false}
|
||||
hoverable
|
||||
className="project-card"
|
||||
style={{
|
||||
borderRadius: 16,
|
||||
background: 'linear-gradient(135deg, rgba(139,92,246,0.04) 0%, rgba(99,102,241,0.04) 100%)',
|
||||
border: '1px solid rgba(139,92,246,0.1)',
|
||||
padding: 20,
|
||||
background: '#fff',
|
||||
border: '1px solid #e2e8f0',
|
||||
padding: '4px 0',
|
||||
}}
|
||||
styles={{ body: { padding: 20 } }}
|
||||
>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<div style={{ marginBottom: 16 }}>{feature.icon}</div>
|
||||
<Typography.Title level={4} style={{ marginBottom: 8, color: '#1e293b' }}>
|
||||
<div style={{ textAlign: 'left' }}>
|
||||
<div
|
||||
style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 12,
|
||||
background: 'linear-gradient(135deg, rgba(139, 92, 246, 0.08), rgba(99, 102, 241, 0.08))',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 14,
|
||||
}}
|
||||
>
|
||||
{feature.icon}
|
||||
</div>
|
||||
<div style={{ fontSize: 15, fontWeight: 600, color: '#1e293b', marginBottom: 6 }}>
|
||||
{feature.title}
|
||||
</Typography.Title>
|
||||
<Typography.Text style={{ color: '#64748b', fontSize: 13 }}>
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: '#64748b', lineHeight: 1.6 }}>
|
||||
{feature.description}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
||||
<Typography.Title level={4} style={{ margin: 0, color: '#1e293b' }}>
|
||||
<StarOutlined style={{ marginRight: 8, color: '#f59e0b' }} />
|
||||
精选案例展示
|
||||
</Typography.Title>
|
||||
<Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
background: 'linear-gradient(135deg, #8b5cf6 0%, #a78bfa 100%)',
|
||||
border: 'none',
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
解锁全部案例
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card
|
||||
bordered={false}
|
||||
{/* 精选案例展示区域 */}
|
||||
<div
|
||||
className="animate-fadeInUp"
|
||||
style={{
|
||||
padding: '24px 28px',
|
||||
borderRadius: 16,
|
||||
background: '#fafafa',
|
||||
padding: 40,
|
||||
textAlign: 'center',
|
||||
background: '#fff',
|
||||
// border: '1px solid #e2e8f0',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<div style={{ color: '#94a3b8', fontSize: 14 }}>
|
||||
敬请期待更多创意案例
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<div
|
||||
style={{
|
||||
width: 4,
|
||||
height: 18,
|
||||
background: 'linear-gradient(180deg, #6366f1, #8b5cf6)',
|
||||
borderRadius: 2,
|
||||
marginRight: 10,
|
||||
}}
|
||||
/>
|
||||
<StarOutlined style={{ marginRight: 8, color: '#f59e0b', fontSize: 16 }} />
|
||||
<span style={{ fontSize: 17, fontWeight: 600, color: '#1f2937' }}>精选案例展示</span>
|
||||
|
||||
</div>
|
||||
{/* <Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
fontWeight: 500,
|
||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||
border: 'none',
|
||||
boxShadow: '0 4px 14px rgba(99, 102, 241, 0.28)',
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
解锁全部案例
|
||||
<ArrowRightOutlined style={{ marginLeft: 4, fontSize: 12 }} />
|
||||
</Button> */}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 案例网格 */}
|
||||
<div
|
||||
className="stagger-children"
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
gap: 16,
|
||||
marginBottom: 16,
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
zIndex: 1,
|
||||
background: 'rgb(255,255,255)',
|
||||
// background:
|
||||
// 'linear-gradient(180deg, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.55) 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
borderRadius: 14,
|
||||
// boxShadow: '0px 4px 16px rgba(0, 0, 0, 0.08)',
|
||||
gap: 4,
|
||||
color: '#fff',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
fontWeight: 500,
|
||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||
border: 'none',
|
||||
boxShadow: '0 4px 14px rgba(99, 102, 241, 0.28)',
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
解锁全部案例
|
||||
<ArrowRightOutlined style={{ marginLeft: 4, fontSize: 12 }} />
|
||||
</Button>
|
||||
{/* <LockOutlined style={{ fontSize: 22, color: '#94a3b8', cursor: 'pointer' }}
|
||||
onClick={handleUnlock}
|
||||
/>
|
||||
<span style={{ fontSize: 16, color: '#1f2937', opacity: 0.9 }}>会员可查看</span> */}
|
||||
</div>
|
||||
|
||||
{caseList.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="project-card animate-fadeInUp"
|
||||
style={{
|
||||
position: 'relative',
|
||||
borderRadius: 14,
|
||||
overflow: 'hidden',
|
||||
cursor: 'pointer',
|
||||
border: '1px solid #e2e8f0',
|
||||
background: '#fff',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
aspectRatio: '16/9',
|
||||
background:
|
||||
'linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #4c1d95 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{/* 模糊视频缩略图占位 */}
|
||||
<PlayCircleOutlined style={{ fontSize: 36, color: 'rgba(255,255,255,0.6)' }} />
|
||||
{/* 标签 */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
left: 10,
|
||||
padding: '2px 8px',
|
||||
borderRadius: 6,
|
||||
background: item.tagColor,
|
||||
color: '#fff',
|
||||
fontSize: 11,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{item.tag}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
padding: '10px 14px',
|
||||
background: '#f8fafc',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: 13,
|
||||
color: '#334155',
|
||||
fontWeight: 500,
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
</span>
|
||||
<EyeOutlined style={{ fontSize: 13, color: '#94a3b8' }} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* 锁定遮罩 */}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreativePlazaPage;
|
||||
export default CreativePlazaPage;
|
||||
|
||||
@@ -111,11 +111,7 @@ const AIChatPage: React.FC = () => {
|
||||
const [conversations, setConversations] = useState<Conversation[]>([
|
||||
]);
|
||||
|
||||
|
||||
|
||||
const [inputValue, setInputValue] = useState<string>('');
|
||||
|
||||
// 从 store 读取生成配置状态
|
||||
// 从 store 读取生成配置状态(包括输入框内容)
|
||||
const {
|
||||
mediaType,
|
||||
countType,
|
||||
@@ -128,6 +124,7 @@ const AIChatPage: React.FC = () => {
|
||||
videoResolution,
|
||||
engineOptions,
|
||||
enginesele,
|
||||
inputValue,
|
||||
setMediaType,
|
||||
setCountType,
|
||||
setSelectedRatio,
|
||||
@@ -139,6 +136,7 @@ const AIChatPage: React.FC = () => {
|
||||
setVideoResolution,
|
||||
setEngineOptions,
|
||||
setEnginesele,
|
||||
setInputValue,
|
||||
} = useAppStore();
|
||||
|
||||
const [uploading, setUploading] = useState<boolean>(false);
|
||||
@@ -2223,6 +2221,7 @@ const AIChatPage: React.FC = () => {
|
||||
<span style={{ fontSize: 12, color: '#9ca3af' }}>秒</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* 选择分辨率 */}
|
||||
|
||||
@@ -45,7 +45,6 @@ const HomePage: React.FC = () => {
|
||||
try {
|
||||
|
||||
getmedit(5).then((res) => {
|
||||
console.log('getmedit:', res);
|
||||
for (let item in res) {
|
||||
res[item].forEach(element => {
|
||||
// 给每条 element 标记它所属的模块(item 是接口返回的 key)
|
||||
@@ -56,13 +55,11 @@ const HomePage: React.FC = () => {
|
||||
}
|
||||
// 最终再打印一次汇总(state 异步更新,这里打印的是本次追加的累计长度)
|
||||
setMockVideos(prev => {
|
||||
console.log('mockVideos 最终条数:', prev.length);
|
||||
return prev;
|
||||
});
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('HomePage fetch error:', err);
|
||||
}
|
||||
};
|
||||
fetchAll();
|
||||
@@ -72,7 +69,7 @@ const HomePage: React.FC = () => {
|
||||
setActiveTab(key);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const aiEntries = [
|
||||
{
|
||||
@@ -120,21 +117,43 @@ const HomePage: React.FC = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
margin: '-24px -32px -32px',
|
||||
borderRadius: 20,
|
||||
height: 'calc(100vh - 34px)',
|
||||
overflow: 'auto',
|
||||
scrollbarWidth: 'none',
|
||||
padding: '0 28px 32px',
|
||||
}}>
|
||||
<div className="content_box">
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||
<h3>首页工作台</h3>
|
||||
<p
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
fontSize: 12, letterSpacing: 0.3,
|
||||
padding: '10px 16px',
|
||||
backgroundColor: '#ffffffff',
|
||||
borderRadius: 30,
|
||||
boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.1)',
|
||||
|
||||
}}
|
||||
|
||||
>如需进行账户素材推送:
|
||||
<span
|
||||
style={{
|
||||
color: '#1a50bbff',
|
||||
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate('/authorization')
|
||||
}}>
|
||||
一键推送
|
||||
<ArrowRightOutlined style={{ marginLeft: 8, transform: 'rotate(0deg)' }} />
|
||||
</span>
|
||||
|
||||
|
||||
</p>
|
||||
</div>
|
||||
{/* ========== 顶部工作台引导区域(三步流程) ========== */}
|
||||
<div className="animate-fadeInUp" style={{
|
||||
padding: '24px 28px',
|
||||
borderRadius: 16,
|
||||
background: 'linear-gradient(135deg, #f0f9ff 0%, #faf5ff 50%, #fef3c7 100%)',
|
||||
border: '1px solid rgba(99,102,241,0.10)',
|
||||
margin: '24px 0 20px',
|
||||
margin: '0 0 20px',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
@@ -151,7 +170,7 @@ const HomePage: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div >
|
||||
{/* <div >
|
||||
<span style={{
|
||||
cursor: 'pointer',
|
||||
fontSize: 12, color: '#1a50bbff', letterSpacing: 0.3,
|
||||
@@ -159,11 +178,11 @@ const HomePage: React.FC = () => {
|
||||
onClick={() => {
|
||||
navigate('/authorization')
|
||||
}}
|
||||
>一键授权
|
||||
>如需进行账户素材推送 一键推送
|
||||
<ArrowRightOutlined style={{ marginLeft: 8, transform: 'rotate(0deg)' }} />
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -553,7 +572,7 @@ const HomePage: React.FC = () => {
|
||||
近期作品
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{/* Tab切换 */}
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
@@ -679,17 +698,8 @@ const HomePage: React.FC = () => {
|
||||
<div style={{
|
||||
padding: '10px 12px',
|
||||
background: '#f8fafc',
|
||||
paddingTop: 0,
|
||||
}}>
|
||||
{/* <div style={{
|
||||
fontSize: 13,
|
||||
color: '#334155',
|
||||
fontWeight: 500,
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}>
|
||||
{video.title || video.name || video.originalPrompt || video.prompt || '未命名作品'}
|
||||
</div> */}
|
||||
<div style={{
|
||||
marginTop: 6,
|
||||
display: 'flex',
|
||||
@@ -739,7 +749,7 @@ const HomePage: React.FC = () => {
|
||||
|
||||
|
||||
{/* ========== 素材案例区域 ========== */}
|
||||
<div className="animate-fadeInUp" style={{
|
||||
{/* <div className="animate-fadeInUp" style={{
|
||||
padding: '24px 28px',
|
||||
borderRadius: 16,
|
||||
background: '#fff',
|
||||
@@ -800,7 +810,7 @@ const HomePage: React.FC = () => {
|
||||
alt={`素材案例 ${index + 1}`}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
/>
|
||||
{/* 案例悬停遮罩(由父级 hover 触发) */}
|
||||
案例悬停遮罩(由父级 hover 触发)
|
||||
<div
|
||||
className="case-overlay"
|
||||
style={{
|
||||
@@ -824,7 +834,7 @@ const HomePage: React.FC = () => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -31,6 +31,8 @@ function InitialInfo() {
|
||||
// 引擎和视频参数相关状态
|
||||
const [enginesele, setEnginesele] = useState<any>({});
|
||||
const [countType, setCountType] = useState('');
|
||||
// 图片引擎 id:取自 getEngine().engine.image[0].id
|
||||
const [imageEngineId, setImageEngineId] = useState<string>('');
|
||||
const [showEngineModal, setShowEngineModal] = useState(false);
|
||||
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
||||
const [videoDuration, setVideoDuration] = useState(5);
|
||||
@@ -160,6 +162,10 @@ function InitialInfo() {
|
||||
durations: firstEngine.supportedDurations || [5, 8, 10, 12, 15],
|
||||
});
|
||||
}
|
||||
// 默认选中第一个图片引擎
|
||||
if (data.engine?.image && data.engine.image.length > 0) {
|
||||
setImageEngineId(data.engine.image[0].id);
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
});
|
||||
@@ -335,7 +341,7 @@ function InitialInfo() {
|
||||
|
||||
const createimage = (stepId: number) => {
|
||||
let params = {
|
||||
engine_id: "0019e3dac0b795b925b",
|
||||
engine_id: imageEngineId,
|
||||
image_proportion: "1:1",
|
||||
image_px: "2048x2048",
|
||||
image_size: "2K"
|
||||
@@ -349,7 +355,7 @@ function InitialInfo() {
|
||||
const newcreateimage = () => {
|
||||
// console.log('下一步:', stepId);
|
||||
let params = {
|
||||
engine_id: "0019e3dac0b795b925b",
|
||||
engine_id: imageEngineId,
|
||||
image_proportion: "1:1",
|
||||
image_px: "2048x2048",
|
||||
image_size: "2K"
|
||||
|
||||
@@ -852,6 +852,7 @@ const GenerateConver: React.FC = () => {
|
||||
</div>
|
||||
) : (
|
||||
<Upload
|
||||
style={{ width: '100%' }}
|
||||
beforeUpload={beforeVideoUpload}
|
||||
showUploadList={false}
|
||||
accept="video/mp4,video/quicktime,.mp4,.mov"
|
||||
@@ -967,6 +968,8 @@ const GenerateConver: React.FC = () => {
|
||||
</div>
|
||||
) : (
|
||||
<Upload
|
||||
style={{ width: '100%' }}
|
||||
|
||||
beforeUpload={beforeImageUpload}
|
||||
showUploadList={false}
|
||||
accept="image/jpeg,image/jpg,image/png,.jpg,.jpeg,.png"
|
||||
|
||||
@@ -1,115 +1,655 @@
|
||||
import React from 'react';
|
||||
import { Button, Card, message, Typography } from 'antd';
|
||||
import { Button, message, Typography } from 'antd';
|
||||
import {
|
||||
StarOutlined,
|
||||
CrownOutlined,
|
||||
LockOutlined,
|
||||
ThunderboltOutlined,
|
||||
GiftOutlined,
|
||||
BarChartOutlined,
|
||||
FireOutlined,
|
||||
TrophyOutlined,
|
||||
LockOutlined,
|
||||
ArrowRightOutlined,
|
||||
PlayCircleOutlined,
|
||||
EyeOutlined,
|
||||
LikeOutlined,
|
||||
CommentOutlined,
|
||||
ShareAltOutlined,
|
||||
RiseOutlined,
|
||||
ThunderboltOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const PopularPage: React.FC = () => {
|
||||
const handleUnlock = () => {
|
||||
message.info('请联系客服开通');
|
||||
message.info('请联系客服开通会员');
|
||||
};
|
||||
|
||||
// 顶部统计 KPI
|
||||
const stats = [
|
||||
{
|
||||
icon: <FireOutlined style={{ fontSize: 22, color: '#f59e0b' }} />,
|
||||
label: '今日爆款',
|
||||
value: '1,286',
|
||||
unit: '条',
|
||||
trend: '+12.5%',
|
||||
color: '#f59e0b',
|
||||
},
|
||||
{
|
||||
icon: <EyeOutlined style={{ fontSize: 22, color: '#6366f1' }} />,
|
||||
label: '总浏览量',
|
||||
value: '428',
|
||||
unit: '万',
|
||||
trend: '+8.2%',
|
||||
color: '#6366f1',
|
||||
},
|
||||
{
|
||||
icon: <LikeOutlined style={{ fontSize: 22, color: '#ec4899' }} />,
|
||||
label: '总互动数',
|
||||
value: '76.4',
|
||||
unit: '万',
|
||||
trend: '+15.7%',
|
||||
color: '#ec4899',
|
||||
},
|
||||
{
|
||||
icon: <ThunderboltOutlined style={{ fontSize: 22, color: '#10b981' }} />,
|
||||
label: '上升最快',
|
||||
value: '美妆',
|
||||
unit: '赛道',
|
||||
trend: '+28.3%',
|
||||
color: '#10b981',
|
||||
},
|
||||
];
|
||||
|
||||
// 行业热度排行(假数据)
|
||||
const industryRank = [
|
||||
{ rank: 1, name: '美妆个护', hot: 98.5, change: 'up' as const, value: 98234 },
|
||||
{ rank: 2, name: '服饰穿搭', hot: 95.2, change: 'up' as const, value: 87643 },
|
||||
{ rank: 3, name: '美食探店', hot: 91.7, change: 'up' as const, value: 78921 },
|
||||
{ rank: 4, name: '3C 数码', hot: 87.3, change: 'down' as const, value: 65432 },
|
||||
{ rank: 5, name: '家居生活', hot: 82.6, change: 'up' as const, value: 54321 },
|
||||
{ rank: 6, name: '母婴亲子', hot: 78.1, change: 'flat' as const, value: 43210 },
|
||||
{ rank: 7, name: '运动健身', hot: 72.4, change: 'up' as const, value: 38765 },
|
||||
];
|
||||
|
||||
// 爆款素材榜单
|
||||
const popularList = [
|
||||
{
|
||||
rank: 1,
|
||||
title: '夏日美妆教程:3 步打造奶油肌',
|
||||
author: '美妆博主·小雅',
|
||||
views: '128.4w',
|
||||
likes: '12.6w',
|
||||
comments: '8,234',
|
||||
tag: 'NO.1',
|
||||
tagColor: '#f59e0b',
|
||||
},
|
||||
{
|
||||
rank: 2,
|
||||
title: '平价穿搭 | 学生党一周不重样',
|
||||
author: '穿搭达人·Miki',
|
||||
views: '96.2w',
|
||||
likes: '9.8w',
|
||||
comments: '6,128',
|
||||
tag: 'NO.2',
|
||||
tagColor: '#a78bfa',
|
||||
},
|
||||
{
|
||||
rank: 3,
|
||||
title: '探店 vlog | 网红咖啡馆测评',
|
||||
author: '美食探店·阿伦',
|
||||
views: '78.5w',
|
||||
likes: '7.4w',
|
||||
comments: '4,892',
|
||||
tag: 'NO.3',
|
||||
tagColor: '#6366f1',
|
||||
},
|
||||
{
|
||||
rank: 4,
|
||||
title: 'iPhone 16 Pro 一周深度体验',
|
||||
author: '数码评测·老王',
|
||||
views: '65.7w',
|
||||
likes: '6.1w',
|
||||
comments: '3,847',
|
||||
tag: 'NO.4',
|
||||
tagColor: '#94a3b8',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px 0' }}>
|
||||
<div style={{ marginBottom: 32 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
|
||||
<div style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 14,
|
||||
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 4px 16px rgba(245,158,11,0.3)',
|
||||
}}>
|
||||
<BarChartOutlined style={{ fontSize: 22, color: '#fff' }} />
|
||||
<div className="content_box">
|
||||
{/* Hero 区域 - 橙金主题(区别创意素材案例的紫粉) */}
|
||||
<div
|
||||
className="animate-fadeInUp"
|
||||
style={{
|
||||
padding: '28px 32px',
|
||||
borderRadius: 16,
|
||||
background: 'linear-gradient(135deg, #fffbeb 0%, #fef3c7 50%, #fed7aa 100%)',
|
||||
border: '1px solid rgba(245, 158, 11, 0.18)',
|
||||
marginBottom: 24,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 12 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: 14,
|
||||
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 6px 20px rgba(245, 158, 11, 0.3)',
|
||||
}}
|
||||
>
|
||||
<BarChartOutlined style={{ fontSize: 24, color: '#fff' }} />
|
||||
</div>
|
||||
<div>
|
||||
<Typography.Title level={2} style={{ margin: 0, color: '#1e293b', fontWeight: 700 }}>
|
||||
行业爆款大盘
|
||||
<span style={{ color: '#6366f1', fontSize: 14, fontWeight: 400, marginLeft: 8 }}>
|
||||
发现热门素材趋势
|
||||
<div className="shiny-text-container" style={{ marginBottom: 4 }}>
|
||||
<span
|
||||
className="shiny-text"
|
||||
style={{
|
||||
fontSize: 26,
|
||||
fontWeight: 700,
|
||||
backgroundImage:
|
||||
'linear-gradient(90deg, #f59e0b 0%, #d97706 30%, #ea580c 50%, #d97706 70%, #f59e0b 100%)',
|
||||
}}
|
||||
>
|
||||
行业爆款大盘
|
||||
</span>
|
||||
</Typography.Title>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: '#b45309' }}>
|
||||
<RiseOutlined style={{ fontSize: 12 }} />
|
||||
<span>实时追踪全网热门素材趋势</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Typography.Text style={{ color: '#64748b' }}>
|
||||
实时追踪各行业爆款素材,把握创作风向,打造热门内容
|
||||
<Typography.Text style={{ color: '#78716c', fontSize: 14, lineHeight: 1.7 }}>
|
||||
实时追踪各行业爆款素材,把握创作风向,打造热门内容
|
||||
</Typography.Text>
|
||||
</div>
|
||||
|
||||
<Card
|
||||
bordered={false}
|
||||
{/* 4 个 KPI 统计卡片 */}
|
||||
{/* <div
|
||||
className="animate-fadeInUp stagger-children"
|
||||
style={{
|
||||
borderRadius: 20,
|
||||
background: 'linear-gradient(135deg, rgba(245,158,11,0.04) 0%, rgba(217,119,6,0.04) 100%)',
|
||||
border: '1px solid rgba(245,158,11,0.1)',
|
||||
padding: 10,
|
||||
marginBottom: 32,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(4, 1fr)',
|
||||
gap: 16,
|
||||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
<Typography.Title level={4} style={{ marginBottom: 20, color: '#1e293b' }}>
|
||||
<FireOutlined style={{ marginRight: 8, color: '#f59e0b' }} />
|
||||
行业热度排行
|
||||
</Typography.Title>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
borderRadius: 16,
|
||||
background: '#fafafa',
|
||||
padding: 40,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<div style={{ color: '#94a3b8', fontSize: 14 }}>
|
||||
敬请期待行业热度排行
|
||||
{stats.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="project-card"
|
||||
style={{
|
||||
padding: 20,
|
||||
borderRadius: 16,
|
||||
background: '#fff',
|
||||
border: '1px solid #e2e8f0',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 14,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 12,
|
||||
background: `linear-gradient(135deg, ${item.color}15, ${item.color}08)`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 2,
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: '#10b981',
|
||||
background: 'rgba(16, 185, 129, 0.08)',
|
||||
padding: '2px 8px',
|
||||
borderRadius: 6,
|
||||
}}
|
||||
>
|
||||
<RiseOutlined style={{ fontSize: 10 }} />
|
||||
{item.trend}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginBottom: 4 }}>
|
||||
<span style={{ fontSize: 24, fontWeight: 700, color: '#1e293b' }}>{item.value}</span>
|
||||
<span style={{ fontSize: 13, color: '#94a3b8' }}>{item.unit}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 13, color: '#64748b' }}>{item.label}</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Card>
|
||||
))}
|
||||
</div> */}
|
||||
{/* 行业热度排行 */}
|
||||
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
||||
<Typography.Title level={4} style={{ margin: 0, color: '#1e293b' }}>
|
||||
<TrophyOutlined style={{ marginRight: 8, color: '#6366f1' }} />
|
||||
爆款素材榜单
|
||||
</Typography.Title>
|
||||
<Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
<div style={{ position: 'relative' }}>
|
||||
{/* <div
|
||||
className="animate-fadeInUp"
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||
border: 'none',
|
||||
padding: '24px 28px',
|
||||
borderRadius: 16,
|
||||
background: '#fff',
|
||||
border: '1px solid #e2e8f0',
|
||||
marginBottom: 24,
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
立即解锁全部
|
||||
</Button>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 20,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<div
|
||||
style={{
|
||||
width: 4,
|
||||
height: 18,
|
||||
background: 'linear-gradient(180deg, #f59e0b, #d97706)',
|
||||
borderRadius: 2,
|
||||
marginRight: 10,
|
||||
}}
|
||||
/>
|
||||
<FireOutlined style={{ marginRight: 8, color: '#f59e0b', fontSize: 16 }} />
|
||||
<span style={{ fontSize: 17, fontWeight: 600, color: '#1f2937' }}>行业热度排行</span>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
fontSize: 12,
|
||||
fontWeight: 400,
|
||||
color: '#94a3b8',
|
||||
}}
|
||||
>
|
||||
基于近 7 天数据 · 实时更新
|
||||
</span>
|
||||
</div>
|
||||
<span style={{ fontSize: 12, color: '#94a3b8' }}>更新时间: 10 分钟前</span>
|
||||
</div>
|
||||
<div style={{position: 'relative', height: 300}}>
|
||||
<Typography.Text style={{ width: '100%', textAlign: 'center', color: '#64748b', display: 'block', height: 100, background: '#f3f4f6', marginTop: 20, marginBottom: 20, padding: 20, }}>
|
||||
实时追踪各行业爆款素材,把握创作风向,打造热门内容
|
||||
</Typography.Text>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
// background:
|
||||
// ' linear-gradient(180deg, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.7) 100%)',
|
||||
background: 'rgb(255,255,255)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
color: '#fff',
|
||||
borderRadius: 6,
|
||||
// boxShadow: '0 0 10px rgba(0,0,0,0.5)',
|
||||
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ fontSize: 18, color: '#94a3b8', cursor: 'pointer' }}
|
||||
onClick={handleUnlock}
|
||||
/>
|
||||
<span style={{ fontSize: 16, color: '#1f2937', opacity: 0.9 }}>立即解锁全部</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div className="stagger-children">
|
||||
{industryRank.map((item) => {
|
||||
const rankColors: Record<number, string> = {
|
||||
1: 'linear-gradient(135deg, #f59e0b, #d97706)',
|
||||
2: 'linear-gradient(135deg, #94a3b8, #64748b)',
|
||||
3: 'linear-gradient(135deg, #ea580c, #c2410c)',
|
||||
};
|
||||
const rankColor = rankColors[item.rank] || '#cbd5e1';
|
||||
const trendIcon =
|
||||
item.change === 'up' ? (
|
||||
<RiseOutlined style={{ fontSize: 11, color: '#10b981' }} />
|
||||
) : item.change === 'down' ? (
|
||||
<RiseOutlined
|
||||
style={{ fontSize: 11, color: '#ef4444', transform: 'rotate(180deg)' }}
|
||||
/>
|
||||
) : (
|
||||
<span style={{ fontSize: 11, color: '#94a3b8' }}>—</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.rank}
|
||||
className="project-card animate-fadeInUp"
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '12px 16px',
|
||||
borderRadius: 12,
|
||||
marginBottom: 8,
|
||||
background: '#f8fafc',
|
||||
border: '1px solid transparent',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
background: rankColor,
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: 700,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 14,
|
||||
boxShadow: item.rank <= 3 ? '0 2px 8px rgba(0,0,0,0.15)' : 'none',
|
||||
}}
|
||||
>
|
||||
{item.rank}
|
||||
</div>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 14,
|
||||
fontWeight: 600,
|
||||
color: '#1e293b',
|
||||
marginBottom: 6,
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: 6,
|
||||
background: '#e2e8f0',
|
||||
borderRadius: 3,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: `${item.hot}%`,
|
||||
height: '100%',
|
||||
background:
|
||||
item.rank === 1
|
||||
? 'linear-gradient(90deg, #f59e0b, #d97706)'
|
||||
: item.rank === 2
|
||||
? 'linear-gradient(90deg, #94a3b8, #64748b)'
|
||||
: item.rank === 3
|
||||
? 'linear-gradient(90deg, #ea580c, #c2410c)'
|
||||
: 'linear-gradient(90deg, #6366f1, #8b5cf6)',
|
||||
borderRadius: 3,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: 80,
|
||||
textAlign: 'right',
|
||||
fontSize: 14,
|
||||
fontWeight: 600,
|
||||
color: '#1e293b',
|
||||
marginLeft: 16,
|
||||
}}
|
||||
>
|
||||
{item.hot}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: 80,
|
||||
textAlign: 'right',
|
||||
fontSize: 12,
|
||||
color: '#64748b',
|
||||
marginLeft: 12,
|
||||
}}
|
||||
>
|
||||
{item.value.toLocaleString()} 素材
|
||||
</div>
|
||||
<div style={{ width: 24, marginLeft: 12, textAlign: 'center' }}>{trendIcon}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* 爆款素材榜单 */}
|
||||
<div
|
||||
className="animate-fadeInUp"
|
||||
style={{
|
||||
padding: '24px 28px',
|
||||
borderRadius: 16,
|
||||
background: '#fff',
|
||||
// border: '1px solid #e2e8f0',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<div
|
||||
style={{
|
||||
width: 4,
|
||||
height: 18,
|
||||
background: 'linear-gradient(180deg, #6366f1, #8b5cf6)',
|
||||
borderRadius: 2,
|
||||
marginRight: 10,
|
||||
}}
|
||||
/>
|
||||
<TrophyOutlined style={{ marginRight: 8, color: '#6366f1', fontSize: 16 }} />
|
||||
<span style={{ fontSize: 17, fontWeight: 600, color: '#1f2937' }}>爆款素材榜单</span>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
fontSize: 12,
|
||||
fontWeight: 400,
|
||||
color: '#94a3b8',
|
||||
}}
|
||||
>
|
||||
{/* TOP 100 */}
|
||||
</span>
|
||||
</div>
|
||||
{/* <Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
fontWeight: 500,
|
||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||
border: 'none',
|
||||
boxShadow: '0 4px 14px rgba(99, 102, 241, 0.28)',
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
立即解锁全部
|
||||
<ArrowRightOutlined style={{ marginLeft: 4, fontSize: 12 }} />
|
||||
</Button> */}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="stagger-children"
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: 16,
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
zIndex: 1,
|
||||
inset: 0,
|
||||
// background:
|
||||
// ' linear-gradient(180deg, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.7) 100%)',
|
||||
background: 'rgb(255,255,255)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
color: '#fff',
|
||||
borderRadius: 6,
|
||||
// boxShadow: '0 0 10px rgba(0,0,0,0.5)',
|
||||
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
size="middle"
|
||||
onClick={handleUnlock}
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
fontWeight: 500,
|
||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
||||
border: 'none',
|
||||
boxShadow: '0 4px 14px rgba(99, 102, 241, 0.28)',
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ marginRight: 6 }} />
|
||||
立即解锁全部
|
||||
<ArrowRightOutlined style={{ marginLeft: 4, fontSize: 12 }} />
|
||||
</Button>
|
||||
{/* <LockOutlined style={{ fontSize: 18, color: '#94a3b8', cursor: 'pointer' }}
|
||||
onClick={handleUnlock}
|
||||
/>
|
||||
<span style={{ fontSize: 16, color: '#1f2937', opacity: 0.9 }}>立即解锁全部</span> */}
|
||||
</div>
|
||||
|
||||
{popularList.map((item) => (
|
||||
<div
|
||||
key={item.rank}
|
||||
className="project-card animate-fadeInUp"
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: 14,
|
||||
padding: 14,
|
||||
borderRadius: 14,
|
||||
background: '#fff',
|
||||
border: '1px solid #e2e8f0',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: 140,
|
||||
height: 80,
|
||||
flexShrink: 0,
|
||||
borderRadius: 10,
|
||||
overflow: 'hidden',
|
||||
background: 'linear-gradient(135deg, #1e1b4b 0%, #312e81 50%, #4c1d95 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<PlayCircleOutlined style={{ fontSize: 28, color: 'rgba(255,255,255,0.6)' }} />
|
||||
{/* 排名徽章 */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 6,
|
||||
left: 6,
|
||||
padding: '2px 8px',
|
||||
borderRadius: 6,
|
||||
background: item.tagColor,
|
||||
color: '#fff',
|
||||
fontSize: 11,
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
{item.tag}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 14,
|
||||
fontWeight: 600,
|
||||
color: '#1e293b',
|
||||
marginBottom: 4,
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
</div>
|
||||
<div style={{ fontSize: 12, color: '#94a3b8', marginBottom: 8 }}>
|
||||
{item.author}
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 12, fontSize: 12, color: '#64748b' }}>
|
||||
<span>
|
||||
<EyeOutlined style={{ marginRight: 3 }} />
|
||||
{item.views}
|
||||
</span>
|
||||
<span>
|
||||
<LikeOutlined style={{ marginRight: 3 }} />
|
||||
{item.likes}
|
||||
</span>
|
||||
<span>
|
||||
<CommentOutlined style={{ marginRight: 3 }} />
|
||||
{item.comments}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* 锁定遮罩 */}
|
||||
{/* <div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
background:
|
||||
' linear-gradient(to right, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.7) 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
color: '#fff',
|
||||
borderRadius: 6,
|
||||
|
||||
}}
|
||||
>
|
||||
<LockOutlined style={{ fontSize: 18 }} />
|
||||
<span style={{ fontSize: 10, opacity: 0.9 }}>会员可看</span>
|
||||
</div> */}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
borderRadius: 16,
|
||||
background: '#fafafa',
|
||||
padding: 40,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<div style={{ color: '#94a3b8', fontSize: 14 }}>
|
||||
敬请期待更多爆款素材
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PopularPage;
|
||||
export default PopularPage;
|
||||
|
||||
@@ -116,7 +116,6 @@ function RemoveInfo() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('轮询获取拆镜列表失败:', error);
|
||||
}
|
||||
}, 30000); // 30秒轮询
|
||||
}
|
||||
@@ -155,7 +154,6 @@ function RemoveInfo() {
|
||||
if (!taskDetail) return;
|
||||
|
||||
if (taskDetail.analysisStatus === 'processing') {
|
||||
console.log("开始轮询");
|
||||
|
||||
analysisPollingRef.current = window.setInterval(async () => {
|
||||
try {
|
||||
@@ -236,7 +234,6 @@ function RemoveInfo() {
|
||||
material_image_url: buildAssetUrl(productImage),
|
||||
idempotency_key: `replication_${Date.now()}`,
|
||||
};
|
||||
console.log(currentSegment,params);
|
||||
|
||||
|
||||
setLoading(true);
|
||||
@@ -245,10 +242,8 @@ function RemoveInfo() {
|
||||
message.success('视频生成任务创建成功');
|
||||
handleCloseDrawer();
|
||||
Removelist(creatID).then((res: any) => {
|
||||
console.log('123123123123',res);
|
||||
|
||||
const targetItem = res.items.find((item: any) => item.id === currentSegment);
|
||||
console.log(targetItem);
|
||||
message.loading('创建中...', 3);
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -355,7 +350,6 @@ function RemoveInfo() {
|
||||
render: (_: any, record: any) => (
|
||||
<div style={{ position: 'relative', width: 120, height: 80, borderRadius: 6, overflow: 'hidden', background: '#f1f5f9', cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
console.log('video clicked:', record.segmentVideoUrl);
|
||||
if (record.segmentVideoUrl) {
|
||||
setPreviewVideoUrl(buildAssetUrl(record.segmentVideoUrl));
|
||||
setPreviewModalVisible(true);
|
||||
|
||||
@@ -31,6 +31,8 @@ function InitialInfo() {
|
||||
// 引擎和视频参数相关状态
|
||||
const [enginesele, setEnginesele] = useState<any>({});
|
||||
const [countType, setCountType] = useState('');
|
||||
// 图片引擎 id:取自 getEngine().engine.image[0].id
|
||||
const [imageEngineId, setImageEngineId] = useState<string>('');
|
||||
const [showEngineModal, setShowEngineModal] = useState(false);
|
||||
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
||||
const [videoDuration, setVideoDuration] = useState(5);
|
||||
@@ -155,6 +157,10 @@ function InitialInfo() {
|
||||
durations: firstEngine.supportedDurations || [5, 8, 10, 12, 15],
|
||||
});
|
||||
}
|
||||
// 默认选中第一个图片引擎
|
||||
if (data.engine?.image && data.engine.image.length > 0) {
|
||||
setImageEngineId(data.engine.image[0].id);
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
});
|
||||
@@ -188,7 +194,6 @@ function InitialInfo() {
|
||||
// 获取任务详情数据
|
||||
useEffect(() => {
|
||||
|
||||
console.log('creatID', creatID);
|
||||
|
||||
if (creatID) {
|
||||
removeDetail(creatID).then((res: any) => {
|
||||
@@ -341,7 +346,7 @@ function InitialInfo() {
|
||||
|
||||
const createimage = (stepId: number) => {
|
||||
let params = {
|
||||
engine_id: "0019e3dac0b795b925b",
|
||||
engine_id: imageEngineId,
|
||||
image_proportion: "1:1",
|
||||
image_px: "2048x2048",
|
||||
image_size: "2K"
|
||||
@@ -355,7 +360,7 @@ function InitialInfo() {
|
||||
const newcreateimage = () => {
|
||||
// console.log('下一步:', stepId);
|
||||
let params = {
|
||||
engine_id: "0019e3dac0b795b925b",
|
||||
engine_id: imageEngineId,
|
||||
image_proportion: "1:1",
|
||||
image_px: "2048x2048",
|
||||
image_size: "2K"
|
||||
|
||||
@@ -31,6 +31,7 @@ interface AppState {
|
||||
durations: number[];
|
||||
};
|
||||
enginesele: any;
|
||||
inputValue: string;
|
||||
|
||||
fetchProjects: () => Promise<void>;
|
||||
createProject: (name: string, industry: Industry) => Promise<Project>;
|
||||
@@ -56,6 +57,7 @@ interface AppState {
|
||||
setVideoAspectRatio: (aspectRatio: string) => void;
|
||||
setVideoResolution: (resolution: string) => void;
|
||||
setEnginesele: (enginesele: any) => void;
|
||||
setInputValue: (inputValue: string) => void;
|
||||
resetGenerationConfig: () => void;
|
||||
}
|
||||
|
||||
@@ -80,6 +82,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
||||
durations: [5, 8, 10, 12, 15],
|
||||
},
|
||||
enginesele: [],
|
||||
inputValue: '',
|
||||
|
||||
fetchProjects: async () => {
|
||||
set({ loading: true });
|
||||
@@ -168,6 +171,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
||||
setVideoAspectRatio: (aspectRatio) => set({ videoAspectRatio: aspectRatio }),
|
||||
setVideoResolution: (resolution) => set({ videoResolution: resolution }),
|
||||
setEnginesele: (enginesele) => set({ enginesele }),
|
||||
setInputValue: (inputValue) => set({ inputValue }),
|
||||
resetGenerationConfig: () => set({
|
||||
mediaType: 'image',
|
||||
countType: '请选择',
|
||||
@@ -184,5 +188,6 @@ export const useAppStore = create<AppState>((set, get) => ({
|
||||
durations: [5, 8, 10, 12, 15],
|
||||
},
|
||||
enginesele: [],
|
||||
inputValue: '',
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
export interface ResourceCapacity {
|
||||
enabled: boolean;
|
||||
source?: string;
|
||||
hasUserConfig?: boolean;
|
||||
usedBytes: number;
|
||||
availableBytes: number;
|
||||
totalBytes: number;
|
||||
usagePercent: number;
|
||||
exceeded: boolean;
|
||||
limitValue?: string;
|
||||
limitUnit: string; // 'KB' | 'MB' | 'GB' 等
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
email: string;
|
||||
avatar?: string;
|
||||
credits: number;
|
||||
isAdmin?: boolean;
|
||||
phone?: string;
|
||||
allowedMenus?: string[] | null;
|
||||
mustSetPassword?: boolean;
|
||||
resourceCapacity?: ResourceCapacity;
|
||||
}
|
||||
|
||||
export interface CreditRecord {
|
||||
|
||||
Reference in New Issue
Block a user