解决冲突
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>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<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.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<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" />
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||||
<title>民众智创</title>
|
<title>民众智创</title>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var cached = localStorage.getItem('siteInfo');
|
var cached = localStorage.getItem('siteInfo');
|
||||||
if (cached) {
|
if (cached) {
|
||||||
try {
|
try {
|
||||||
var info = JSON.parse(cached);
|
var info = JSON.parse(cached);
|
||||||
if (info.siteName) {
|
if (info.siteName) {
|
||||||
document.title = info.siteName;
|
document.title = info.siteName;
|
||||||
}
|
}
|
||||||
if (info.siteLogo) {
|
if (info.siteLogo) {
|
||||||
var link = document.querySelector('link[rel="icon"]');
|
var link = document.querySelector('link[rel="icon"]');
|
||||||
if (link) {
|
if (link) {
|
||||||
link.href = info.siteLogo;
|
link.href = info.siteLogo;
|
||||||
link.type = 'image/png';
|
link.type = 'image/png';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script type="module" crossorigin src="/assets/index-BVNhLxFb.js"></script>
|
<script type="module" crossorigin src="/assets/index-B2ULZowz.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-D3IaMBsq.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BhPFzWLH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>␍
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -27,6 +27,18 @@ const MOCK_USER: User = {
|
|||||||
username: 'videomaker',
|
username: 'videomaker',
|
||||||
email: 'demo@videogen.ai',
|
email: 'demo@videogen.ai',
|
||||||
credits: 2680,
|
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[] = [
|
const MOCK_CREDIT_RECORDS: CreditRecord[] = [
|
||||||
|
|||||||
@@ -61,10 +61,146 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { useAuthStore } from '../../store/useAuthStore';
|
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 NotificationPopup from '../NotificationPopup';
|
||||||
import './AppLayout.css';
|
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 {
|
interface MenuConfig {
|
||||||
id: string;
|
id: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
@@ -186,6 +322,18 @@ const AppLayout: React.FC = () => {
|
|||||||
const currentOrderNoRef = useRef<string | null>(null);
|
const currentOrderNoRef = useRef<string | null>(null);
|
||||||
const [enabledMethods, setEnabledMethods] = useState<{ alipay: boolean; wechat: boolean }>({ alipay: false, wechat: false });
|
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';
|
const PENDING_ORDER_KEY = 'pending_payment_order';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -212,6 +360,30 @@ const AppLayout: React.FC = () => {
|
|||||||
|
|
||||||
localStorage.setItem('siteInfo', JSON.stringify({ siteName: name, siteLogo: logo }));
|
localStorage.setItem('siteInfo', JSON.stringify({ siteName: name, siteLogo: logo }));
|
||||||
}).catch(() => { });
|
}).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) => {
|
const handleContactMouseDown = (e: React.MouseEvent) => {
|
||||||
@@ -674,6 +846,9 @@ const AppLayout: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
||||||
|
{/* 资源存储容量展示(来自 getUser.resourceCapacity) */}
|
||||||
|
<StorageCard data={resourceCapacity} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -768,6 +943,9 @@ const AppLayout: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 资源存储容量展示(与桌面端共用 StorageCard) */}
|
||||||
|
<StorageCard data={resourceCapacity} />
|
||||||
|
|
||||||
{topLevelItems.map(item => {
|
{topLevelItems.map(item => {
|
||||||
const menuType = item.menu_type ?? item.menuType;
|
const menuType = item.menu_type ?? item.menuType;
|
||||||
const hasChildren = childMap[item.id] && childMap[item.id].length > 0;
|
const hasChildren = childMap[item.id] && childMap[item.id].length > 0;
|
||||||
|
|||||||
+564
-158
@@ -3,20 +3,26 @@
|
|||||||
:root {
|
:root {
|
||||||
--font-sans: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
--font-sans: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||||
--nav-bg: #f8f9fb;
|
--nav-bg: #f8f9fb;
|
||||||
--nav-surface: rgba(0,0,0,0.02);
|
--nav-surface: rgba(0, 0, 0, 0.02);
|
||||||
--nav-border: #e5e7eb;
|
--nav-border: #e5e7eb;
|
||||||
--nav-text: #1f2937;
|
--nav-text: #1f2937;
|
||||||
--nav-text-muted: #6b7280;
|
--nav-text-muted: #6b7280;
|
||||||
--nav-hover: rgba(0,0,0,0.04);
|
--nav-hover: rgba(0, 0, 0, 0.04);
|
||||||
--nav-active: rgba(99,102,241,0.08);
|
--nav-active: rgba(99, 102, 241, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after { box-sizing: border-box; }
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
html, body {
|
html,
|
||||||
margin: 0; padding: 0;
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
@@ -24,23 +30,68 @@ html, body {
|
|||||||
color: #1a1a2e;
|
color: #1a1a2e;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
}
|
}
|
||||||
#root { min-height: 100vh; }
|
|
||||||
|
|
||||||
|
#root {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Scrollbar ─────────────────────────── */
|
/* ── Scrollbar ─────────────────────────── */
|
||||||
::-webkit-scrollbar { width: 5px; height: 5px; }
|
::-webkit-scrollbar {
|
||||||
::-webkit-scrollbar-track { background: transparent; }
|
width: 5px;
|
||||||
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
|
height: 5px;
|
||||||
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #d1d5db;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #9ca3af;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Electric Border Animation ─────────── */
|
/* ── Electric Border Animation ─────────── */
|
||||||
@keyframes electric-pulse {
|
@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 {
|
@keyframes electric-flow {
|
||||||
0% { background-position: 0% 50%; }
|
0% {
|
||||||
50% { background-position: 100% 50%; }
|
background-position: 0% 50%;
|
||||||
100% { 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 {
|
.electric-border-card {
|
||||||
@@ -51,16 +102,14 @@ html, body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
inset: -2px;
|
inset: -2px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: linear-gradient(
|
background: linear-gradient(90deg,
|
||||||
90deg,
|
#6366f1,
|
||||||
#6366f1,
|
#8b5cf6,
|
||||||
#8b5cf6,
|
#a855f7,
|
||||||
#a855f7,
|
#6366f1,
|
||||||
#6366f1,
|
#8b5cf6,
|
||||||
#8b5cf6,
|
#a855f7,
|
||||||
#a855f7,
|
#6366f1);
|
||||||
#6366f1
|
|
||||||
);
|
|
||||||
background-size: 300% 100%;
|
background-size: 300% 100%;
|
||||||
animation: electric-flow 3s linear infinite, electric-pulse 2s ease-in-out infinite;
|
animation: electric-flow 3s linear infinite, electric-pulse 2s ease-in-out infinite;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
@@ -85,6 +134,7 @@ html, body {
|
|||||||
0% {
|
0% {
|
||||||
background-position: -200% center;
|
background-position: -200% center;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
background-position: 200% center;
|
background-position: 200% center;
|
||||||
}
|
}
|
||||||
@@ -97,16 +147,14 @@ html, body {
|
|||||||
.shiny-text {
|
.shiny-text {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
background: linear-gradient(
|
background: linear-gradient(90deg,
|
||||||
90deg,
|
#6366f1 0%,
|
||||||
#6366f1 0%,
|
#8b5cf6 20%,
|
||||||
#8b5cf6 20%,
|
#a855f7 40%,
|
||||||
#a855f7 40%,
|
#c084fc 50%,
|
||||||
#c084fc 50%,
|
#a855f7 60%,
|
||||||
#a855f7 60%,
|
#8b5cf6 80%,
|
||||||
#8b5cf6 80%,
|
#6366f1 100%);
|
||||||
#6366f1 100%
|
|
||||||
);
|
|
||||||
background-size: 200% auto;
|
background-size: 200% auto;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
@@ -118,92 +166,225 @@ html, body {
|
|||||||
|
|
||||||
/* ── Keyframe Animations ───────────────── */
|
/* ── Keyframe Animations ───────────────── */
|
||||||
@keyframes fadeInUp {
|
@keyframes fadeInUp {
|
||||||
from { opacity: 0; transform: translateY(20px); }
|
from {
|
||||||
to { opacity: 1; transform: translateY(0); }
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInLeft {
|
@keyframes fadeInLeft {
|
||||||
from { opacity: 0; transform: translateX(-20px); }
|
from {
|
||||||
to { opacity: 1; transform: translateX(0); }
|
opacity: 0;
|
||||||
|
transform: translateX(-20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInRight {
|
@keyframes fadeInRight {
|
||||||
from { opacity: 0; transform: translateX(20px); }
|
from {
|
||||||
to { opacity: 1; transform: translateX(0); }
|
opacity: 0;
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes float1 {
|
@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 {
|
@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 {
|
@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 {
|
@keyframes slideInCard {
|
||||||
from { opacity: 0; transform: translateY(14px) scale(0.97); }
|
from {
|
||||||
to { opacity: 1; transform: translateY(0) scale(1); }
|
opacity: 0;
|
||||||
|
transform: translateY(14px) scale(0.97);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0) scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spinSlow {
|
@keyframes spinSlow {
|
||||||
from { transform: rotate(0deg); }
|
from {
|
||||||
to { transform: rotate(360deg); }
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.animate-fadeInUp { animation: fadeInUp 0.45s ease-out both; }
|
.animate-fadeInUp {
|
||||||
.animate-fadeInLeft { animation: fadeInLeft 0.55s ease-out both; }
|
animation: fadeInUp 0.45s 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; }
|
|
||||||
|
|
||||||
.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; }
|
.animate-fadeInRight {
|
||||||
.stagger-children > *:nth-child(2) { animation-delay: 0.10s; }
|
animation: fadeInRight 0.55s ease-out both;
|
||||||
.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; }
|
.animate-slideInCard {
|
||||||
.stagger-children > *:nth-child(6) { animation-delay: 0.34s; }
|
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 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;
|
border-radius: 10px !important;
|
||||||
transition: all 0.25s ease !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 {
|
.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;
|
border-color: #6366f1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-btn {
|
.ant-btn {
|
||||||
border-radius: 10px !important;
|
border-radius: 10px !important;
|
||||||
transition: all 0.25s ease !important;
|
transition: all 0.25s ease !important;
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
}
|
}
|
||||||
.ant-btn:hover { transform: none; }
|
|
||||||
.ant-btn:active { transform: translateY(0); }
|
.ant-btn:hover {
|
||||||
.ant-card { border-radius: 16px !important; transition: all 0.3s ease !important; }
|
transform: none;
|
||||||
.ant-modal-content { border-radius: 20px !important; overflow: hidden; }
|
}
|
||||||
.ant-tag { font-size: 12px; border-radius: 8px !important; }
|
|
||||||
|
.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 hover ───────────────── */
|
||||||
.recharge-card {
|
.recharge-card {
|
||||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recharge-card:hover {
|
.recharge-card:hover {
|
||||||
transform: translateY(-8px) scale(1.02) !important;
|
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 ────────────────────── */
|
||||||
.homepage-tabs .ant-tabs-nav {
|
.homepage-tabs .ant-tabs-nav {
|
||||||
margin-bottom: 8px !important;
|
margin-bottom: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-tab {
|
.homepage-tabs .ant-tabs-tab {
|
||||||
padding: 8px 16px !important;
|
padding: 8px 16px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
@@ -211,13 +392,16 @@ html, body {
|
|||||||
color: #6b7280 !important;
|
color: #6b7280 !important;
|
||||||
transition: all 0.25s !important;
|
transition: all 0.25s !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-tab:hover {
|
.homepage-tabs .ant-tabs-tab:hover {
|
||||||
color: #6366f1 !important;
|
color: #6366f1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-tab-active .ant-tabs-tab-btn {
|
.homepage-tabs .ant-tabs-tab-active .ant-tabs-tab-btn {
|
||||||
color: #6366f1 !important;
|
color: #6366f1 !important;
|
||||||
font-weight: 600 !important;
|
font-weight: 600 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-ink-bar {
|
.homepage-tabs .ant-tabs-ink-bar {
|
||||||
background: linear-gradient(90deg, #6366f1, #a855f7) !important;
|
background: linear-gradient(90deg, #6366f1, #a855f7) !important;
|
||||||
height: 3px !important;
|
height: 3px !important;
|
||||||
@@ -230,108 +414,249 @@ html, body {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-card:hover {
|
.project-card:hover {
|
||||||
transform: translateY(-4px) !important;
|
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;
|
border-color: #6366f1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Mobile Bottom Nav ─────────────────── */
|
/* ── Mobile Bottom Nav ─────────────────── */
|
||||||
.mobile-bottom-nav {
|
.mobile-bottom-nav {
|
||||||
display: none;
|
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;
|
height: 60px;
|
||||||
background: rgba(255,255,255,0.95);
|
background: rgba(255, 255, 255, 0.95);
|
||||||
backdrop-filter: blur(24px);
|
backdrop-filter: blur(24px);
|
||||||
border-top: 1px solid rgba(0,0,0,0.05);
|
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
box-shadow: 0 -4px 20px rgba(0,0,0,0.06);
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-bottom-nav .nav-item {
|
.mobile-bottom-nav .nav-item {
|
||||||
flex: 1; display: flex; flex-direction: column;
|
flex: 1;
|
||||||
align-items: center; justify-content: center; gap: 2px;
|
display: flex;
|
||||||
cursor: pointer; transition: all 0.2s;
|
flex-direction: column;
|
||||||
color: #8b8fa3; font-size: 9px; font-weight: 400;
|
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;
|
letter-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-bottom-nav .nav-item.active {
|
.mobile-bottom-nav .nav-item.active {
|
||||||
color: #08080c;
|
color: #08080c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-bottom-nav .nav-item .nav-icon {
|
.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 {
|
.mobile-bottom-nav .nav-item.active .nav-icon {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Responsive Breakpoints ────────────── */
|
/* ── Responsive Breakpoints ────────────── */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.desktop-sidebar { display: none !important; }
|
.desktop-sidebar {
|
||||||
.desktop-content { margin-left: 0 !important; padding: 16px !important; padding-bottom: 80px !important; overflow-x: hidden !important; }
|
display: none !important;
|
||||||
.desktop-sidebar-toggle-zone { display: none !important; }
|
}
|
||||||
.mobile-bottom-nav { display: flex !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 */
|
/* Prevent horizontal overflow globally */
|
||||||
html, body { overflow-x: hidden !important; }
|
html,
|
||||||
|
body {
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mobile-hide { display: none !important; }
|
.mobile-hide {
|
||||||
.mobile-full { width: 100% !important; max-width: 100% !important; }
|
display: none !important;
|
||||||
.mobile-stack { flex-direction: column !important; }
|
}
|
||||||
.mobile-p-16 { padding: 16px !important; }
|
|
||||||
.mobile-gap-12 { gap: 12px !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 */
|
||||||
.login-page { flex-direction: column !important; }
|
.login-page {
|
||||||
.login-left { display: none !important; }
|
flex-direction: column !important;
|
||||||
.login-right { padding: 24px 16px !important; }
|
}
|
||||||
.login-card { width: 100% !important; }
|
|
||||||
|
.login-left {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-right {
|
||||||
|
padding: 24px 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Project list */
|
/* Project list */
|
||||||
.project-item { flex-direction: column !important; align-items: flex-start !important; }
|
.project-item {
|
||||||
.project-item .project-actions { margin-left: 0 !important; margin-top: 12px; width: 100%; justify-content: flex-end; }
|
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 */
|
/* 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 */
|
/* Operation flow bar */
|
||||||
.gen-flow-bar { flex-direction: column !important; gap: 14px !important; padding: 16px !important; }
|
.gen-flow-bar {
|
||||||
.gen-flow-divider { display: none !important; }
|
flex-direction: column !important;
|
||||||
|
gap: 14px !important;
|
||||||
|
padding: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gen-flow-divider {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Config form params row */
|
/* 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 */
|
/* 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 */
|
/* Prompt rows */
|
||||||
.gen-prompt-row { flex-direction: column !important; }
|
.gen-prompt-row {
|
||||||
.gen-prompt-row > * { width: 100% !important; }
|
flex-direction: column !important;
|
||||||
.gen-params { flex-wrap: wrap !important; gap: 8px !important; }
|
}
|
||||||
.gen-params > div { flex: 1 1 45% !important; min-width: 0; }
|
|
||||||
|
.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 */
|
/* Expanded detail left+right stacks */
|
||||||
.gen-detail-row { flex-direction: column !important; }
|
.gen-detail-row {
|
||||||
.gen-detail-row > * { width: 100% !important; min-width: 0 !important; flex: 1 1 auto !important; }
|
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 stacks */
|
||||||
.record-filter-bar { flex-direction: column !important; }
|
.record-filter-bar {
|
||||||
.record-filter-bar .ant-space { flex-wrap: wrap !important; }
|
flex-direction: column !important;
|
||||||
.record-filter-bar .ant-select { width: 100% !important; }
|
}
|
||||||
|
|
||||||
|
.record-filter-bar .ant-space {
|
||||||
|
flex-wrap: wrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-filter-bar .ant-select {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Record summary row stacks */
|
/* Record summary row stacks */
|
||||||
.record-item { flex-direction: column !important; align-items: flex-start !important; gap: 8px !important; overflow: hidden !important; }
|
.record-item {
|
||||||
.record-item .record-actions { width: 100% !important; justify-content: flex-end; }
|
flex-direction: column !important;
|
||||||
.record-item > span[style*="textOverflow"] { white-space: normal !important; overflow: visible !important; text-overflow: unset !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 */
|
/* Hide less important meta on mobile */
|
||||||
.mobile-meta { display: none !important; }
|
.mobile-meta {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Credits page */
|
/* Credits page */
|
||||||
.credits-balance { flex-direction: column !important; }
|
.credits-balance {
|
||||||
.recharge-grid { flex-direction: column !important; }
|
flex-direction: column !important;
|
||||||
.recharge-grid > * { width: 100% !important; }
|
}
|
||||||
|
|
||||||
|
.recharge-grid {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recharge-grid>* {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Video player fits mobile */
|
/* Video player fits mobile */
|
||||||
video { max-width: 100% !important; }
|
video {
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* InitialReplication page */
|
/* InitialReplication page */
|
||||||
.replication-container {
|
.replication-container {
|
||||||
@@ -340,17 +665,20 @@ html, body {
|
|||||||
padding: 16px !important;
|
padding: 16px !important;
|
||||||
height: calc(100vh - 64px) !important;
|
height: calc(100vh - 64px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-preview {
|
.replication-preview {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 30vh !important;
|
height: 30vh !important;
|
||||||
border-radius: 12px !important;
|
border-radius: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-form {
|
.replication-form {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
max-height: calc(70vh - 32px) !important;
|
max-height: calc(70vh - 32px) !important;
|
||||||
border-radius: 12px !important;
|
border-radius: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-form-content {
|
.replication-form-content {
|
||||||
padding: 16px !important;
|
padding: 16px !important;
|
||||||
max-height: calc(70vh - 64px) !important;
|
max-height: calc(70vh - 64px) !important;
|
||||||
@@ -358,56 +686,92 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── Date Display ──────────────────────── */
|
/* ── 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) ────────────── */
|
/* ── Small Mobile Breakpoint (max-width: 480px) ────────────── */
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
|
|
||||||
/* Base styles */
|
/* Base styles */
|
||||||
html, body { font-size: 14px !important; }
|
html,
|
||||||
|
body {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Login page */
|
/* Login page */
|
||||||
.login-card { width: 100% !important; }
|
.login-card {
|
||||||
.login-right { padding: 16px !important; }
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-right {
|
||||||
|
padding: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Header adjustments */
|
/* Header adjustments */
|
||||||
.gen-header { padding: 12px 14px !important; }
|
.gen-header {
|
||||||
|
padding: 12px 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Form elements */
|
/* Form elements */
|
||||||
.gen-form-row { gap: 8px !important; }
|
.gen-form-row {
|
||||||
|
gap: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Button adjustments */
|
/* 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 */
|
/* Input adjustments */
|
||||||
.ant-input, .ant-input-affix-wrapper, .ant-select-selector {
|
.ant-input,
|
||||||
height: 36px !important;
|
.ant-input-affix-wrapper,
|
||||||
|
.ant-select-selector {
|
||||||
|
height: 36px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card padding */
|
/* Card padding */
|
||||||
.ant-card { padding: 12px !important; }
|
.ant-card {
|
||||||
|
padding: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mobile bottom nav adjustments */
|
/* Mobile bottom nav adjustments */
|
||||||
.mobile-bottom-nav { height: 56px !important; }
|
.mobile-bottom-nav {
|
||||||
.mobile-bottom-nav .nav-item .nav-icon { font-size: 18px !important; }
|
height: 56px !important;
|
||||||
.mobile-bottom-nav .nav-item { font-size: 9px !important; gap: 2px !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 */
|
/* InitialReplication page - Small Mobile */
|
||||||
.replication-container {
|
.replication-container {
|
||||||
padding: 12px !important;
|
padding: 12px !important;
|
||||||
gap: 12px !important;
|
gap: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-preview {
|
.replication-preview {
|
||||||
height: 25vh !important;
|
height: 25vh !important;
|
||||||
border-radius: 10px !important;
|
border-radius: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-form-content {
|
.replication-form-content {
|
||||||
padding: 12px !important;
|
padding: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-form-content .ant-btn {
|
.replication-form-content .ant-btn {
|
||||||
height: 36px !important;
|
height: 36px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replication-form-content .ant-input,
|
.replication-form-content .ant-input,
|
||||||
.replication-form-content .ant-input-affix-wrapper {
|
.replication-form-content .ant-input-affix-wrapper {
|
||||||
height: 36px !important;
|
height: 36px !important;
|
||||||
@@ -415,30 +779,56 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Video and image containers */
|
/* Video and image containers */
|
||||||
video, img {
|
video,
|
||||||
max-height: 160px !important;
|
img {
|
||||||
|
max-height: 160px !important;
|
||||||
border-radius: 6px !important;
|
border-radius: 6px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Upload areas */
|
/* Upload areas */
|
||||||
.upload-area { padding: 12px !important; }
|
.upload-area {
|
||||||
|
padding: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Spacing adjustments */
|
/* Spacing adjustments */
|
||||||
.mobile-p-16 { padding: 12px !important; }
|
.mobile-p-16 {
|
||||||
.mobile-gap-12 { gap: 8px !important; }
|
padding: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-gap-12 {
|
||||||
|
gap: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Font size adjustments */
|
/* Font size adjustments */
|
||||||
h1 { font-size: 18px !important; }
|
h1 {
|
||||||
h2 { font-size: 16px !important; }
|
font-size: 18px !important;
|
||||||
h3 { font-size: 14px !important; }
|
}
|
||||||
p { font-size: 12px !important; }
|
|
||||||
|
h2 {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Button text */
|
/* Button text */
|
||||||
.btn-text-sm { font-size: 12px !important; }
|
.btn-text-sm {
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Margin adjustments */
|
/* Margin adjustments */
|
||||||
.mobile-mb-8 { margin-bottom: 8px !important; }
|
.mobile-mb-8 {
|
||||||
.mobile-mb-12 { margin-bottom: 12px !important; }
|
margin-bottom: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-mb-12 {
|
||||||
|
margin-bottom: 12px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Tablet Breakpoint (769px to 1024px) ────────────── */
|
/* ── Tablet Breakpoint (769px to 1024px) ────────────── */
|
||||||
@@ -450,33 +840,49 @@ html, body {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Card max-width */
|
/* Card max-width */
|
||||||
.ant-card { max-width: calc(50% - 8px) !important; }
|
.ant-card {
|
||||||
|
max-width: calc(50% - 8px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Font adjustments */
|
/* Font adjustments */
|
||||||
html, body { font-size: 15px !important; }
|
html,
|
||||||
|
body {
|
||||||
|
font-size: 15px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Large Desktop Breakpoint (min-width: 1200px) ────────────── */
|
/* ── Large Desktop Breakpoint (min-width: 1200px) ────────────── */
|
||||||
@media (min-width: 1200px) {
|
@media (min-width: 1200px) {
|
||||||
|
|
||||||
/* Max width container */
|
/* 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 */
|
||||||
.card-grid { grid-template-columns: repeat(3, 1fr) !important; }
|
.card-grid {
|
||||||
|
grid-template-columns: repeat(3, 1fr) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── HomePage Tabs ────────────── */
|
/* ── HomePage Tabs ────────────── */
|
||||||
.homepage-tabs .ant-tabs-nav { margin-bottom: 0; }
|
.homepage-tabs .ant-tabs-nav {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-tab {
|
.homepage-tabs .ant-tabs-tab {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 8px 20px;
|
padding: 8px 20px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-tab-active {
|
.homepage-tabs .ant-tabs-tab-active {
|
||||||
color: #6366f1;
|
color: #6366f1;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage-tabs .ant-tabs-ink-bar {
|
.homepage-tabs .ant-tabs-ink-bar {
|
||||||
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
||||||
}
|
}
|
||||||
@@ -8,127 +8,326 @@ import {
|
|||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
HeartOutlined,
|
HeartOutlined,
|
||||||
|
EyeOutlined,
|
||||||
|
ArrowRightOutlined,
|
||||||
|
CrownOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
const CreativePlazaPage: React.FC = () => {
|
const CreativePlazaPage: React.FC = () => {
|
||||||
const handleUnlock = () => {
|
const handleUnlock = () => {
|
||||||
message.info('请联系客服开通');
|
message.info('请联系客服开通会员');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 顶部特性卡片
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
icon: <ThunderboltOutlined style={{ fontSize: 28, color: '#8b5cf6' }} />,
|
icon: <ThunderboltOutlined style={{ fontSize: 26, color: '#8b5cf6' }} />,
|
||||||
title: 'AI智能生成',
|
title: 'AI 智能生成',
|
||||||
description: '先进的AI技术,一键生成高质量视频内容',
|
description: '先进 AI 技术一键产出高质量视频内容',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <PlayCircleOutlined style={{ fontSize: 28, color: '#ec4899' }} />,
|
icon: <PlayCircleOutlined style={{ fontSize: 26, color: '#ec4899' }} />,
|
||||||
title: '多格式输出',
|
title: '多格式输出',
|
||||||
description: '支持多种视频格式,满足不同场景需求',
|
description: '支持多种视频格式,满足不同场景需求',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <CheckCircleOutlined style={{ fontSize: 28, color: '#10b981' }} />,
|
icon: <CheckCircleOutlined style={{ fontSize: 26, color: '#10b981' }} />,
|
||||||
title: '品质保证',
|
title: '品质保证',
|
||||||
description: '专业级画质,细节清晰,色彩鲜艳',
|
description: '专业级画质,细节清晰,色彩鲜艳',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <HeartOutlined style={{ fontSize: 28, color: '#f59e0b' }} />,
|
icon: <HeartOutlined style={{ fontSize: 26, color: '#f59e0b' }} />,
|
||||||
title: '创意无限',
|
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 (
|
return (
|
||||||
<div style={{ padding: '20px 0' }}>
|
<div className="content_box">
|
||||||
<div style={{ marginBottom: 32 }}>
|
{/* 顶部 Hero 区域 */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
|
<div
|
||||||
<div style={{
|
className="animate-fadeInUp"
|
||||||
width: 48,
|
style={{
|
||||||
height: 48,
|
padding: '28px 32px',
|
||||||
borderRadius: 14,
|
borderRadius: 16,
|
||||||
background: 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)',
|
background: 'linear-gradient(135deg, #f5f3ff 0%, #ede9fe 50%, #fce7f3 100%)',
|
||||||
display: 'flex',
|
border: '1px solid rgba(139, 92, 246, 0.12)',
|
||||||
alignItems: 'center',
|
marginBottom: 24,
|
||||||
justifyContent: 'center',
|
position: 'relative',
|
||||||
boxShadow: '0 4px 16px rgba(139,92,246,0.3)',
|
overflow: 'hidden',
|
||||||
}}>
|
}}
|
||||||
<GiftOutlined style={{ fontSize: 22, color: '#fff' }} />
|
>
|
||||||
|
<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>
|
||||||
<div>
|
<div>
|
||||||
<Typography.Title level={2} style={{ margin: 0, color: '#1e293b', fontWeight: 700 }}>
|
<div className="shiny-text-container" style={{ marginBottom: 4 }}>
|
||||||
创意素材案例
|
<span className="shiny-text" style={{ fontSize: 26, fontWeight: 700 }}>
|
||||||
<span style={{ color: '#6366f1', fontSize: 14, fontWeight: 400, marginLeft: 8 }}>
|
创意素材案例
|
||||||
探索AI创作无限可能
|
|
||||||
</span>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
<Typography.Text style={{ color: '#64748b' }}>
|
<Typography.Text style={{ color: '#64748b', fontSize: 14, lineHeight: 1.7 }}>
|
||||||
精选AI生成的优秀素材案例,展示AI创作的无限潜力与创意灵感
|
精选 AI 生成的优秀素材案例,展示 AI 创作的无限潜力与创意灵感
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</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) => (
|
{features.map((feature, index) => (
|
||||||
<Card
|
<Card
|
||||||
key={index}
|
key={index}
|
||||||
bordered={false}
|
bordered={false}
|
||||||
|
hoverable
|
||||||
|
className="project-card"
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
background: 'linear-gradient(135deg, rgba(139,92,246,0.04) 0%, rgba(99,102,241,0.04) 100%)',
|
background: '#fff',
|
||||||
border: '1px solid rgba(139,92,246,0.1)',
|
border: '1px solid #e2e8f0',
|
||||||
padding: 20,
|
padding: '4px 0',
|
||||||
}}
|
}}
|
||||||
|
styles={{ body: { padding: 20 } }}
|
||||||
>
|
>
|
||||||
<div style={{ textAlign: 'center' }}>
|
<div style={{ textAlign: 'left' }}>
|
||||||
<div style={{ marginBottom: 16 }}>{feature.icon}</div>
|
<div
|
||||||
<Typography.Title level={4} style={{ marginBottom: 8, color: '#1e293b' }}>
|
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}
|
{feature.title}
|
||||||
</Typography.Title>
|
</div>
|
||||||
<Typography.Text style={{ color: '#64748b', fontSize: 13 }}>
|
<div style={{ fontSize: 13, color: '#64748b', lineHeight: 1.6 }}>
|
||||||
{feature.description}
|
{feature.description}
|
||||||
</Typography.Text>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
{/* 精选案例展示区域 */}
|
||||||
<Typography.Title level={4} style={{ margin: 0, color: '#1e293b' }}>
|
<div
|
||||||
<StarOutlined style={{ marginRight: 8, color: '#f59e0b' }} />
|
className="animate-fadeInUp"
|
||||||
精选案例展示
|
|
||||||
</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}
|
|
||||||
style={{
|
style={{
|
||||||
|
padding: '24px 28px',
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
background: '#fafafa',
|
background: '#fff',
|
||||||
padding: 40,
|
// border: '1px solid #e2e8f0',
|
||||||
textAlign: 'center',
|
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>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CreativePlazaPage;
|
export default CreativePlazaPage;
|
||||||
|
|||||||
@@ -111,11 +111,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
const [conversations, setConversations] = useState<Conversation[]>([
|
const [conversations, setConversations] = useState<Conversation[]>([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 从 store 读取生成配置状态(包括输入框内容)
|
||||||
|
|
||||||
const [inputValue, setInputValue] = useState<string>('');
|
|
||||||
|
|
||||||
// 从 store 读取生成配置状态
|
|
||||||
const {
|
const {
|
||||||
mediaType,
|
mediaType,
|
||||||
countType,
|
countType,
|
||||||
@@ -128,6 +124,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
videoResolution,
|
videoResolution,
|
||||||
engineOptions,
|
engineOptions,
|
||||||
enginesele,
|
enginesele,
|
||||||
|
inputValue,
|
||||||
setMediaType,
|
setMediaType,
|
||||||
setCountType,
|
setCountType,
|
||||||
setSelectedRatio,
|
setSelectedRatio,
|
||||||
@@ -139,6 +136,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
setVideoResolution,
|
setVideoResolution,
|
||||||
setEngineOptions,
|
setEngineOptions,
|
||||||
setEnginesele,
|
setEnginesele,
|
||||||
|
setInputValue,
|
||||||
} = useAppStore();
|
} = useAppStore();
|
||||||
|
|
||||||
const [uploading, setUploading] = useState<boolean>(false);
|
const [uploading, setUploading] = useState<boolean>(false);
|
||||||
@@ -2223,6 +2221,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
<span style={{ fontSize: 12, color: '#9ca3af' }}>秒</span>
|
<span style={{ fontSize: 12, color: '#9ca3af' }}>秒</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 选择分辨率 */}
|
{/* 选择分辨率 */}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ const HomePage: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
getmedit(5).then((res) => {
|
getmedit(5).then((res) => {
|
||||||
console.log('getmedit:', res);
|
|
||||||
for (let item in res) {
|
for (let item in res) {
|
||||||
res[item].forEach(element => {
|
res[item].forEach(element => {
|
||||||
// 给每条 element 标记它所属的模块(item 是接口返回的 key)
|
// 给每条 element 标记它所属的模块(item 是接口返回的 key)
|
||||||
@@ -56,13 +55,11 @@ const HomePage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
// 最终再打印一次汇总(state 异步更新,这里打印的是本次追加的累计长度)
|
// 最终再打印一次汇总(state 异步更新,这里打印的是本次追加的累计长度)
|
||||||
setMockVideos(prev => {
|
setMockVideos(prev => {
|
||||||
console.log('mockVideos 最终条数:', prev.length);
|
|
||||||
return prev;
|
return prev;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('HomePage fetch error:', err);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchAll();
|
fetchAll();
|
||||||
@@ -72,7 +69,7 @@ const HomePage: React.FC = () => {
|
|||||||
setActiveTab(key);
|
setActiveTab(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const aiEntries = [
|
const aiEntries = [
|
||||||
{
|
{
|
||||||
@@ -120,21 +117,43 @@ const HomePage: React.FC = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div className="content_box">
|
||||||
margin: '-24px -32px -32px',
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||||
borderRadius: 20,
|
<h3>首页工作台</h3>
|
||||||
height: 'calc(100vh - 34px)',
|
<p
|
||||||
overflow: 'auto',
|
style={{
|
||||||
scrollbarWidth: 'none',
|
cursor: 'pointer',
|
||||||
padding: '0 28px 32px',
|
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={{
|
<div className="animate-fadeInUp" style={{
|
||||||
padding: '24px 28px',
|
padding: '24px 28px',
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
background: 'linear-gradient(135deg, #f0f9ff 0%, #faf5ff 50%, #fef3c7 100%)',
|
background: 'linear-gradient(135deg, #f0f9ff 0%, #faf5ff 50%, #fef3c7 100%)',
|
||||||
border: '1px solid rgba(99,102,241,0.10)',
|
border: '1px solid rgba(99,102,241,0.10)',
|
||||||
margin: '24px 0 20px',
|
margin: '0 0 20px',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}}>
|
}}>
|
||||||
@@ -151,7 +170,7 @@ const HomePage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div >
|
{/* <div >
|
||||||
<span style={{
|
<span style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
fontSize: 12, color: '#1a50bbff', letterSpacing: 0.3,
|
fontSize: 12, color: '#1a50bbff', letterSpacing: 0.3,
|
||||||
@@ -159,11 +178,11 @@ const HomePage: React.FC = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate('/authorization')
|
navigate('/authorization')
|
||||||
}}
|
}}
|
||||||
>一键授权
|
>如需进行账户素材推送 一键推送
|
||||||
<ArrowRightOutlined style={{ marginLeft: 8, transform: 'rotate(0deg)' }} />
|
<ArrowRightOutlined style={{ marginLeft: 8, transform: 'rotate(0deg)' }} />
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -553,7 +572,7 @@ const HomePage: React.FC = () => {
|
|||||||
近期作品
|
近期作品
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{/* Tab切换 */}
|
{/* Tab切换 */}
|
||||||
<div style={{ marginBottom: 20 }}>
|
<div style={{ marginBottom: 20 }}>
|
||||||
@@ -679,17 +698,8 @@ const HomePage: React.FC = () => {
|
|||||||
<div style={{
|
<div style={{
|
||||||
padding: '10px 12px',
|
padding: '10px 12px',
|
||||||
background: '#f8fafc',
|
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={{
|
<div style={{
|
||||||
marginTop: 6,
|
marginTop: 6,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -739,7 +749,7 @@ const HomePage: React.FC = () => {
|
|||||||
|
|
||||||
|
|
||||||
{/* ========== 素材案例区域 ========== */}
|
{/* ========== 素材案例区域 ========== */}
|
||||||
<div className="animate-fadeInUp" style={{
|
{/* <div className="animate-fadeInUp" style={{
|
||||||
padding: '24px 28px',
|
padding: '24px 28px',
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
background: '#fff',
|
background: '#fff',
|
||||||
@@ -800,7 +810,7 @@ const HomePage: React.FC = () => {
|
|||||||
alt={`素材案例 ${index + 1}`}
|
alt={`素材案例 ${index + 1}`}
|
||||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||||
/>
|
/>
|
||||||
{/* 案例悬停遮罩(由父级 hover 触发) */}
|
案例悬停遮罩(由父级 hover 触发)
|
||||||
<div
|
<div
|
||||||
className="case-overlay"
|
className="case-overlay"
|
||||||
style={{
|
style={{
|
||||||
@@ -824,7 +834,7 @@ const HomePage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ function InitialInfo() {
|
|||||||
// 引擎和视频参数相关状态
|
// 引擎和视频参数相关状态
|
||||||
const [enginesele, setEnginesele] = useState<any>({});
|
const [enginesele, setEnginesele] = useState<any>({});
|
||||||
const [countType, setCountType] = useState('');
|
const [countType, setCountType] = useState('');
|
||||||
|
// 图片引擎 id:取自 getEngine().engine.image[0].id
|
||||||
|
const [imageEngineId, setImageEngineId] = useState<string>('');
|
||||||
const [showEngineModal, setShowEngineModal] = useState(false);
|
const [showEngineModal, setShowEngineModal] = useState(false);
|
||||||
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
||||||
const [videoDuration, setVideoDuration] = useState(5);
|
const [videoDuration, setVideoDuration] = useState(5);
|
||||||
@@ -160,6 +162,10 @@ function InitialInfo() {
|
|||||||
durations: firstEngine.supportedDurations || [5, 8, 10, 12, 15],
|
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) => {
|
.catch((error: any) => {
|
||||||
});
|
});
|
||||||
@@ -335,7 +341,7 @@ function InitialInfo() {
|
|||||||
|
|
||||||
const createimage = (stepId: number) => {
|
const createimage = (stepId: number) => {
|
||||||
let params = {
|
let params = {
|
||||||
engine_id: "0019e3dac0b795b925b",
|
engine_id: imageEngineId,
|
||||||
image_proportion: "1:1",
|
image_proportion: "1:1",
|
||||||
image_px: "2048x2048",
|
image_px: "2048x2048",
|
||||||
image_size: "2K"
|
image_size: "2K"
|
||||||
@@ -349,7 +355,7 @@ function InitialInfo() {
|
|||||||
const newcreateimage = () => {
|
const newcreateimage = () => {
|
||||||
// console.log('下一步:', stepId);
|
// console.log('下一步:', stepId);
|
||||||
let params = {
|
let params = {
|
||||||
engine_id: "0019e3dac0b795b925b",
|
engine_id: imageEngineId,
|
||||||
image_proportion: "1:1",
|
image_proportion: "1:1",
|
||||||
image_px: "2048x2048",
|
image_px: "2048x2048",
|
||||||
image_size: "2K"
|
image_size: "2K"
|
||||||
|
|||||||
@@ -852,6 +852,7 @@ const GenerateConver: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Upload
|
<Upload
|
||||||
|
style={{ width: '100%' }}
|
||||||
beforeUpload={beforeVideoUpload}
|
beforeUpload={beforeVideoUpload}
|
||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
accept="video/mp4,video/quicktime,.mp4,.mov"
|
accept="video/mp4,video/quicktime,.mp4,.mov"
|
||||||
@@ -967,6 +968,8 @@ const GenerateConver: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Upload
|
<Upload
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
|
||||||
beforeUpload={beforeImageUpload}
|
beforeUpload={beforeImageUpload}
|
||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
accept="image/jpeg,image/jpg,image/png,.jpg,.jpeg,.png"
|
accept="image/jpeg,image/jpg,image/png,.jpg,.jpeg,.png"
|
||||||
|
|||||||
@@ -1,115 +1,655 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, Card, message, Typography } from 'antd';
|
import { Button, message, Typography } from 'antd';
|
||||||
import {
|
import {
|
||||||
StarOutlined,
|
|
||||||
CrownOutlined,
|
|
||||||
LockOutlined,
|
|
||||||
ThunderboltOutlined,
|
|
||||||
GiftOutlined,
|
|
||||||
BarChartOutlined,
|
BarChartOutlined,
|
||||||
FireOutlined,
|
FireOutlined,
|
||||||
TrophyOutlined,
|
TrophyOutlined,
|
||||||
|
LockOutlined,
|
||||||
|
ArrowRightOutlined,
|
||||||
|
PlayCircleOutlined,
|
||||||
|
EyeOutlined,
|
||||||
|
LikeOutlined,
|
||||||
|
CommentOutlined,
|
||||||
|
ShareAltOutlined,
|
||||||
|
RiseOutlined,
|
||||||
|
ThunderboltOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
const PopularPage: React.FC = () => {
|
const PopularPage: React.FC = () => {
|
||||||
const handleUnlock = () => {
|
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 (
|
return (
|
||||||
<div style={{ padding: '20px 0' }}>
|
<div className="content_box">
|
||||||
<div style={{ marginBottom: 32 }}>
|
{/* Hero 区域 - 橙金主题(区别创意素材案例的紫粉) */}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 12 }}>
|
<div
|
||||||
<div style={{
|
className="animate-fadeInUp"
|
||||||
width: 48,
|
style={{
|
||||||
height: 48,
|
padding: '28px 32px',
|
||||||
borderRadius: 14,
|
borderRadius: 16,
|
||||||
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
background: 'linear-gradient(135deg, #fffbeb 0%, #fef3c7 50%, #fed7aa 100%)',
|
||||||
display: 'flex',
|
border: '1px solid rgba(245, 158, 11, 0.18)',
|
||||||
alignItems: 'center',
|
marginBottom: 24,
|
||||||
justifyContent: 'center',
|
position: 'relative',
|
||||||
boxShadow: '0 4px 16px rgba(245,158,11,0.3)',
|
overflow: 'hidden',
|
||||||
}}>
|
}}
|
||||||
<BarChartOutlined style={{ fontSize: 22, color: '#fff' }} />
|
>
|
||||||
|
<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>
|
||||||
<div>
|
<div>
|
||||||
<Typography.Title level={2} style={{ margin: 0, color: '#1e293b', fontWeight: 700 }}>
|
<div className="shiny-text-container" style={{ marginBottom: 4 }}>
|
||||||
行业爆款大盘
|
<span
|
||||||
<span style={{ color: '#6366f1', fontSize: 14, fontWeight: 400, marginLeft: 8 }}>
|
className="shiny-text"
|
||||||
发现热门素材趋势
|
style={{
|
||||||
|
fontSize: 26,
|
||||||
|
fontWeight: 700,
|
||||||
|
backgroundImage:
|
||||||
|
'linear-gradient(90deg, #f59e0b 0%, #d97706 30%, #ea580c 50%, #d97706 70%, #f59e0b 100%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
行业爆款大盘
|
||||||
</span>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
<Typography.Text style={{ color: '#64748b' }}>
|
<Typography.Text style={{ color: '#78716c', fontSize: 14, lineHeight: 1.7 }}>
|
||||||
实时追踪各行业爆款素材,把握创作风向,打造热门内容
|
实时追踪各行业爆款素材,把握创作风向,打造热门内容
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card
|
{/* 4 个 KPI 统计卡片 */}
|
||||||
bordered={false}
|
{/* <div
|
||||||
|
className="animate-fadeInUp stagger-children"
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 20,
|
display: 'grid',
|
||||||
background: 'linear-gradient(135deg, rgba(245,158,11,0.04) 0%, rgba(217,119,6,0.04) 100%)',
|
gridTemplateColumns: 'repeat(4, 1fr)',
|
||||||
border: '1px solid rgba(245,158,11,0.1)',
|
gap: 16,
|
||||||
padding: 10,
|
marginBottom: 24,
|
||||||
marginBottom: 32,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography.Title level={4} style={{ marginBottom: 20, color: '#1e293b' }}>
|
{stats.map((item, index) => (
|
||||||
<FireOutlined style={{ marginRight: 8, color: '#f59e0b' }} />
|
<div
|
||||||
行业热度排行
|
key={index}
|
||||||
</Typography.Title>
|
className="project-card"
|
||||||
<Card
|
style={{
|
||||||
bordered={false}
|
padding: 20,
|
||||||
style={{
|
borderRadius: 16,
|
||||||
borderRadius: 16,
|
background: '#fff',
|
||||||
background: '#fafafa',
|
border: '1px solid #e2e8f0',
|
||||||
padding: 40,
|
}}
|
||||||
textAlign: 'center',
|
>
|
||||||
}}
|
<div
|
||||||
>
|
style={{
|
||||||
<div style={{ color: '#94a3b8', fontSize: 14 }}>
|
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>
|
</div>
|
||||||
</Card>
|
))}
|
||||||
</Card>
|
</div> */}
|
||||||
|
{/* 行业热度排行 */}
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
|
<div style={{ position: 'relative' }}>
|
||||||
<Typography.Title level={4} style={{ margin: 0, color: '#1e293b' }}>
|
{/* <div
|
||||||
<TrophyOutlined style={{ marginRight: 8, color: '#6366f1' }} />
|
className="animate-fadeInUp"
|
||||||
爆款素材榜单
|
|
||||||
</Typography.Title>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
size="middle"
|
|
||||||
onClick={handleUnlock}
|
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 10,
|
padding: '24px 28px',
|
||||||
background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
|
borderRadius: 16,
|
||||||
border: 'none',
|
background: '#fff',
|
||||||
|
border: '1px solid #e2e8f0',
|
||||||
|
marginBottom: 24,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<LockOutlined style={{ marginRight: 6 }} />
|
<div
|
||||||
立即解锁全部
|
style={{
|
||||||
</Button>
|
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>
|
</div>
|
||||||
|
|
||||||
<Card
|
|
||||||
bordered={false}
|
|
||||||
style={{
|
|
||||||
borderRadius: 16,
|
|
||||||
background: '#fafafa',
|
|
||||||
padding: 40,
|
|
||||||
textAlign: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ color: '#94a3b8', fontSize: 14 }}>
|
|
||||||
敬请期待更多爆款素材
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PopularPage;
|
export default PopularPage;
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ function RemoveInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('轮询获取拆镜列表失败:', error);
|
|
||||||
}
|
}
|
||||||
}, 30000); // 30秒轮询
|
}, 30000); // 30秒轮询
|
||||||
}
|
}
|
||||||
@@ -155,7 +154,6 @@ function RemoveInfo() {
|
|||||||
if (!taskDetail) return;
|
if (!taskDetail) return;
|
||||||
|
|
||||||
if (taskDetail.analysisStatus === 'processing') {
|
if (taskDetail.analysisStatus === 'processing') {
|
||||||
console.log("开始轮询");
|
|
||||||
|
|
||||||
analysisPollingRef.current = window.setInterval(async () => {
|
analysisPollingRef.current = window.setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -236,7 +234,6 @@ function RemoveInfo() {
|
|||||||
material_image_url: buildAssetUrl(productImage),
|
material_image_url: buildAssetUrl(productImage),
|
||||||
idempotency_key: `replication_${Date.now()}`,
|
idempotency_key: `replication_${Date.now()}`,
|
||||||
};
|
};
|
||||||
console.log(currentSegment,params);
|
|
||||||
|
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -245,10 +242,8 @@ function RemoveInfo() {
|
|||||||
message.success('视频生成任务创建成功');
|
message.success('视频生成任务创建成功');
|
||||||
handleCloseDrawer();
|
handleCloseDrawer();
|
||||||
Removelist(creatID).then((res: any) => {
|
Removelist(creatID).then((res: any) => {
|
||||||
console.log('123123123123',res);
|
|
||||||
|
|
||||||
const targetItem = res.items.find((item: any) => item.id === currentSegment);
|
const targetItem = res.items.find((item: any) => item.id === currentSegment);
|
||||||
console.log(targetItem);
|
|
||||||
message.loading('创建中...', 3);
|
message.loading('创建中...', 3);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -355,7 +350,6 @@ function RemoveInfo() {
|
|||||||
render: (_: any, record: any) => (
|
render: (_: any, record: any) => (
|
||||||
<div style={{ position: 'relative', width: 120, height: 80, borderRadius: 6, overflow: 'hidden', background: '#f1f5f9', cursor: 'pointer' }}
|
<div style={{ position: 'relative', width: 120, height: 80, borderRadius: 6, overflow: 'hidden', background: '#f1f5f9', cursor: 'pointer' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log('video clicked:', record.segmentVideoUrl);
|
|
||||||
if (record.segmentVideoUrl) {
|
if (record.segmentVideoUrl) {
|
||||||
setPreviewVideoUrl(buildAssetUrl(record.segmentVideoUrl));
|
setPreviewVideoUrl(buildAssetUrl(record.segmentVideoUrl));
|
||||||
setPreviewModalVisible(true);
|
setPreviewModalVisible(true);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ function InitialInfo() {
|
|||||||
// 引擎和视频参数相关状态
|
// 引擎和视频参数相关状态
|
||||||
const [enginesele, setEnginesele] = useState<any>({});
|
const [enginesele, setEnginesele] = useState<any>({});
|
||||||
const [countType, setCountType] = useState('');
|
const [countType, setCountType] = useState('');
|
||||||
|
// 图片引擎 id:取自 getEngine().engine.image[0].id
|
||||||
|
const [imageEngineId, setImageEngineId] = useState<string>('');
|
||||||
const [showEngineModal, setShowEngineModal] = useState(false);
|
const [showEngineModal, setShowEngineModal] = useState(false);
|
||||||
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
||||||
const [videoDuration, setVideoDuration] = useState(5);
|
const [videoDuration, setVideoDuration] = useState(5);
|
||||||
@@ -155,6 +157,10 @@ function InitialInfo() {
|
|||||||
durations: firstEngine.supportedDurations || [5, 8, 10, 12, 15],
|
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) => {
|
.catch((error: any) => {
|
||||||
});
|
});
|
||||||
@@ -188,7 +194,6 @@ function InitialInfo() {
|
|||||||
// 获取任务详情数据
|
// 获取任务详情数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
console.log('creatID', creatID);
|
|
||||||
|
|
||||||
if (creatID) {
|
if (creatID) {
|
||||||
removeDetail(creatID).then((res: any) => {
|
removeDetail(creatID).then((res: any) => {
|
||||||
@@ -341,7 +346,7 @@ function InitialInfo() {
|
|||||||
|
|
||||||
const createimage = (stepId: number) => {
|
const createimage = (stepId: number) => {
|
||||||
let params = {
|
let params = {
|
||||||
engine_id: "0019e3dac0b795b925b",
|
engine_id: imageEngineId,
|
||||||
image_proportion: "1:1",
|
image_proportion: "1:1",
|
||||||
image_px: "2048x2048",
|
image_px: "2048x2048",
|
||||||
image_size: "2K"
|
image_size: "2K"
|
||||||
@@ -355,7 +360,7 @@ function InitialInfo() {
|
|||||||
const newcreateimage = () => {
|
const newcreateimage = () => {
|
||||||
// console.log('下一步:', stepId);
|
// console.log('下一步:', stepId);
|
||||||
let params = {
|
let params = {
|
||||||
engine_id: "0019e3dac0b795b925b",
|
engine_id: imageEngineId,
|
||||||
image_proportion: "1:1",
|
image_proportion: "1:1",
|
||||||
image_px: "2048x2048",
|
image_px: "2048x2048",
|
||||||
image_size: "2K"
|
image_size: "2K"
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ interface AppState {
|
|||||||
durations: number[];
|
durations: number[];
|
||||||
};
|
};
|
||||||
enginesele: any;
|
enginesele: any;
|
||||||
|
inputValue: string;
|
||||||
|
|
||||||
fetchProjects: () => Promise<void>;
|
fetchProjects: () => Promise<void>;
|
||||||
createProject: (name: string, industry: Industry) => Promise<Project>;
|
createProject: (name: string, industry: Industry) => Promise<Project>;
|
||||||
@@ -56,6 +57,7 @@ interface AppState {
|
|||||||
setVideoAspectRatio: (aspectRatio: string) => void;
|
setVideoAspectRatio: (aspectRatio: string) => void;
|
||||||
setVideoResolution: (resolution: string) => void;
|
setVideoResolution: (resolution: string) => void;
|
||||||
setEnginesele: (enginesele: any) => void;
|
setEnginesele: (enginesele: any) => void;
|
||||||
|
setInputValue: (inputValue: string) => void;
|
||||||
resetGenerationConfig: () => void;
|
resetGenerationConfig: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +82,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|||||||
durations: [5, 8, 10, 12, 15],
|
durations: [5, 8, 10, 12, 15],
|
||||||
},
|
},
|
||||||
enginesele: [],
|
enginesele: [],
|
||||||
|
inputValue: '',
|
||||||
|
|
||||||
fetchProjects: async () => {
|
fetchProjects: async () => {
|
||||||
set({ loading: true });
|
set({ loading: true });
|
||||||
@@ -168,6 +171,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|||||||
setVideoAspectRatio: (aspectRatio) => set({ videoAspectRatio: aspectRatio }),
|
setVideoAspectRatio: (aspectRatio) => set({ videoAspectRatio: aspectRatio }),
|
||||||
setVideoResolution: (resolution) => set({ videoResolution: resolution }),
|
setVideoResolution: (resolution) => set({ videoResolution: resolution }),
|
||||||
setEnginesele: (enginesele) => set({ enginesele }),
|
setEnginesele: (enginesele) => set({ enginesele }),
|
||||||
|
setInputValue: (inputValue) => set({ inputValue }),
|
||||||
resetGenerationConfig: () => set({
|
resetGenerationConfig: () => set({
|
||||||
mediaType: 'image',
|
mediaType: 'image',
|
||||||
countType: '请选择',
|
countType: '请选择',
|
||||||
@@ -184,5 +188,6 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|||||||
durations: [5, 8, 10, 12, 15],
|
durations: [5, 8, 10, 12, 15],
|
||||||
},
|
},
|
||||||
enginesele: [],
|
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 {
|
export interface User {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
email: string;
|
email: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
credits: number;
|
credits: number;
|
||||||
|
isAdmin?: boolean;
|
||||||
|
phone?: string;
|
||||||
allowedMenus?: string[] | null;
|
allowedMenus?: string[] | null;
|
||||||
|
mustSetPassword?: boolean;
|
||||||
|
resourceCapacity?: ResourceCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreditRecord {
|
export interface CreditRecord {
|
||||||
|
|||||||
Reference in New Issue
Block a user