素材云批量删除
This commit is contained in:
@@ -130,5 +130,5 @@ export const api = {
|
|||||||
post: <T>(path: string, body?: unknown, auth = true, skipAuthRedirect = false) =>
|
post: <T>(path: string, body?: unknown, auth = true, skipAuthRedirect = false) =>
|
||||||
apiRequest<T>(path, { method: 'POST', body, auth, skipAuthRedirect }),
|
apiRequest<T>(path, { method: 'POST', body, auth, skipAuthRedirect }),
|
||||||
put: <T>(path: string, body?: unknown, auth = true) => apiRequest<T>(path, { method: 'PUT', body, auth }),
|
put: <T>(path: string, body?: unknown, auth = true) => apiRequest<T>(path, { method: 'PUT', body, auth }),
|
||||||
delete: <T>(path: string, auth = true) => apiRequest<T>(path, { method: 'DELETE', auth }),
|
delete: <T>(path: string, body?: unknown, auth = true) => apiRequest<T>(path, { method: 'DELETE', body, auth }),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -721,3 +721,9 @@ export async function getHomeCaseHeader(): Promise<any> {
|
|||||||
export async function getHomeCaseButton(id: string,limit:number=5): Promise<any> {
|
export async function getHomeCaseButton(id: string,limit:number=5): Promise<any> {
|
||||||
return api.get(`/home-materials?category_id=${id}&limit_per_category=${limit}&include_empty_categories=false&response_mode=grouped&page=1&page_size=20`);
|
return api.get(`/home-materials?category_id=${id}&limit_per_category=${limit}&include_empty_categories=false&response_mode=grouped&page=1&page_size=20`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function deleteResourcesMaterial(params:any): Promise<any> {
|
||||||
|
return api.delete(`/generation-ai/history/batch`, params);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1165,8 +1165,8 @@ const AIChatPage: React.FC = () => {
|
|||||||
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
||||||
}}>
|
}}>
|
||||||
<div style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 16 }}>
|
<div style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 16 }}>
|
||||||
<div style={{ width: '15%', height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: '15%', height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} /> */}
|
||||||
<div style={{ flex: 1, minWidth: 0, textAlign: 'center' }}>
|
<div style={{ flex: 1, minWidth: 0, }}>
|
||||||
<h2 style={{
|
<h2 style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
@@ -1182,7 +1182,7 @@ const AIChatPage: React.FC = () => {
|
|||||||
输入想法、剧本或上传参考,智能生成视频/图片
|
输入想法、剧本或上传参考,智能生成视频/图片
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ width: '15%', height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: '15%', height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} /> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
ReloadOutlined,
|
ReloadOutlined,
|
||||||
StarOutlined,
|
StarOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { gethistory, gethistoryItems, getOAuthList, asyncBatchUploadMaterial, updateFilename, getUploadHistory, getAllOAuthAccountList, getOpenTypeAll, getPreTestList, getDefaultPreTest } from '../api';
|
import { gethistory, gethistoryItems, getOAuthList, asyncBatchUploadMaterial, updateFilename, getUploadHistory, getAllOAuthAccountList, getOpenTypeAll, getPreTestList, getDefaultPreTest, deleteHistory, deleteResourcesMaterial } from '../api';
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
@@ -200,8 +200,8 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查下载数量限制
|
// 检查下载数量限制
|
||||||
if (selectedItems.size > 10) {
|
if (selectedItems.size > 30) {
|
||||||
message.warning('最多只能单次下载10个文件');
|
message.warning('最多只能单次下载30个文件');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +265,109 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
|
|
||||||
message.destroy('downloadProgress');
|
message.destroy('downloadProgress');
|
||||||
message.success(`下载完成,共 ${successCount} 个文件`);
|
message.success(`下载完成,共 ${successCount} 个文件`);
|
||||||
|
setIsSelectionMode(false);
|
||||||
|
setSelectedItems(new Set());
|
||||||
|
};
|
||||||
|
const handleDeleteSelected = async () => {
|
||||||
|
if (selectedItems.size === 0) {
|
||||||
|
message.warning('请先选择要删除的媒体');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedData = recordlist.flatMap((group: any) =>
|
||||||
|
group.items.filter((item: any) => selectedItems.has(getItemResourceId(item)))
|
||||||
|
);
|
||||||
|
|
||||||
|
let confirmContent: React.ReactNode = '';
|
||||||
|
if (filterType === 'shot_replicate') {
|
||||||
|
confirmContent = (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 8 }}>以下内容所连带的图片和视频都将被删除:</div>
|
||||||
|
<ul style={{ margin: 0, paddingLeft: 20 }}>
|
||||||
|
{selectedData.map((item: any, index: number) => (
|
||||||
|
<li key={index} style={{ marginBottom: 4, color: '#334155' }}>
|
||||||
|
{item.shotReplicateProjectTitle}— —{item.shotSegmentLabel}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div style={{ marginTop: 12 }}>确定删除吗?</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (filterType === 'hot_opening_replicate') {
|
||||||
|
confirmContent = (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 8 }}>爆款开头复刻中以下内容所连带的图片和视频都将被删除:</div>
|
||||||
|
<ul style={{ margin: 0, paddingLeft: 20 }}>
|
||||||
|
{selectedData.map((item: any, index: number) => (
|
||||||
|
<li key={index} style={{ marginBottom: 4, color: '#334155' }}>
|
||||||
|
{item.moduleProjectTitle}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div style={{ marginTop: 12 }}>确定删除吗?</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
confirmContent = `确定删除选中的 ${selectedItems.size} 条记录吗?`;
|
||||||
|
}
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: confirmContent,
|
||||||
|
okText: '确定删除',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: { danger: true },
|
||||||
|
onOk: async () => {
|
||||||
|
let historySource = '';
|
||||||
|
if (filterType === 'project') {
|
||||||
|
historySource = 'generation_record';
|
||||||
|
} else if (filterType === 'creation') {
|
||||||
|
historySource = 'chat_task';
|
||||||
|
} else if (filterType === 'hot_opening_replicate') {
|
||||||
|
historySource = 'hot_opening_replicate';
|
||||||
|
} else if (filterType === 'shot_replicate') {
|
||||||
|
historySource = 'shot_replicate';
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedContent: any[] = [];
|
||||||
|
recordlist.forEach((group: any) => {
|
||||||
|
group.items.forEach((item: any) => {
|
||||||
|
if (selectedItems.has(getItemResourceId(item))) {
|
||||||
|
selectedContent.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let idArr: any[] = [];
|
||||||
|
if (historySource === 'generation_record') {
|
||||||
|
idArr = selectedContent.map((item: any) => item.id);
|
||||||
|
} else if (historySource === 'chat_task') {
|
||||||
|
idArr = selectedContent.map((item: any) => item.id);
|
||||||
|
} else if (historySource === 'hot_opening_replicate') {
|
||||||
|
idArr = selectedContent.map((item: any) => item.moduleProjectId);
|
||||||
|
} else if (historySource === 'shot_replicate') {
|
||||||
|
idArr = selectedContent.map((item: any) => item.shotSegmentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
history_source: historySource,
|
||||||
|
ids: idArr,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteResourcesMaterial(params);
|
||||||
|
message.success('删除成功');
|
||||||
|
setIsSelectionMode(false);
|
||||||
|
setSelectedItems(new Set());
|
||||||
|
setPagebreak(prev => ({ ...prev, page: 1 }));
|
||||||
|
loadRecordList();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败,请重试');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const loadPreTestTemplates = async () => {
|
const loadPreTestTemplates = async () => {
|
||||||
setPreTestTemplatesLoading(true);
|
setPreTestTemplatesLoading(true);
|
||||||
@@ -565,11 +668,10 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
message.error(error.message || '文件名更新失败');
|
message.error(error.message || '文件名更新失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 日期选择器变化处理函数
|
|
||||||
const handleDateChange = (dateString: string) => {
|
const handleDateChange = (dateString: string) => {
|
||||||
setSelectedDate(dateString);
|
setSelectedDate(dateString);
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
const loadRecordList = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
let historySource = '';
|
let historySource = '';
|
||||||
if (filterType === 'project') {
|
if (filterType === 'project') {
|
||||||
@@ -615,7 +717,6 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
data.forEach(group => {
|
data.forEach(group => {
|
||||||
group.page = 1;
|
group.page = 1;
|
||||||
});
|
});
|
||||||
// 如果是第一页,替换数据;否则追加数据
|
|
||||||
if (Pagebreak.page === 1) {
|
if (Pagebreak.page === 1) {
|
||||||
setRecordList(data);
|
setRecordList(data);
|
||||||
} else {
|
} else {
|
||||||
@@ -630,6 +731,9 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
loadRecordList();
|
||||||
}, [filterType, filterMedia, Pagebreak.page, selectedDate]);
|
}, [filterType, filterMedia, Pagebreak.page, selectedDate]);
|
||||||
// 加载更多
|
// 加载更多
|
||||||
const handleLoadMore = () => {
|
const handleLoadMore = () => {
|
||||||
@@ -763,7 +867,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
icon={<StarOutlined />}
|
icon={<StarOutlined />}
|
||||||
>
|
>
|
||||||
爆款开头复刻
|
爆款复刻
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type={filterType === 'shot_replicate' ? 'primary' : 'default'}
|
type={filterType === 'shot_replicate' ? 'primary' : 'default'}
|
||||||
@@ -818,6 +922,12 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
>
|
>
|
||||||
取消选择
|
取消选择
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => handleDeleteSelected()}
|
||||||
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #bf0b0a 0%, #ff8165 100%)', border: 'none', boxShadow: '0 4px 16px rgba(191, 11, 10, 0.35)', fontWeight: 600, padding: '8px 24px', color: '#fff' }}
|
||||||
|
>
|
||||||
|
删除 ({selectedItems.size})
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => handleDownloadSelected()}
|
onClick={() => handleDownloadSelected()}
|
||||||
style={{
|
style={{
|
||||||
@@ -1335,7 +1445,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
onCancel={handleClosePreview}
|
onCancel={handleClosePreview}
|
||||||
width={1200}
|
width={1200}
|
||||||
footer={
|
footer={
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, padding: '16px 24px', background: 'rgba(255,255,255,0.6)', borderTop: '1px solid rgba(99, 102, 241, 0.08)' }}>
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12, padding: '16px 24px', background: '#fff', borderTop: '1px solid #f1f5f9' }}>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<DownloadOutlined />}
|
icon={<DownloadOutlined />}
|
||||||
@@ -1351,53 +1461,131 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}}
|
}}
|
||||||
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)' }}
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', boxShadow: '0 4px 16px rgba(99, 102, 241, 0.35)', fontWeight: 600, padding: '8px 24px' }}
|
||||||
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
||||||
>
|
>
|
||||||
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? '资源已过期' : '下载'}
|
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? '资源已过期' : '下载'}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<DeleteOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
let deleteId = '';
|
||||||
|
let confirmContent: React.ReactNode = '';
|
||||||
|
|
||||||
|
if (filterType === 'shot_replicate') {
|
||||||
|
deleteId = previewItem.shotSegmentId;
|
||||||
|
confirmContent = (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 8 }}>以下内容所连带的图片和视频都将被删除:</div>
|
||||||
|
<ul style={{ margin: 0, paddingLeft: 20 }}>
|
||||||
|
<li style={{ marginBottom: 4, color: '#334155' }}>
|
||||||
|
{previewItem.shotReplicateProjectTitle}— —{previewItem.shotSegmentLabel}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div style={{ marginTop: 12 }}>确定删除吗?</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (filterType === 'hot_opening_replicate') {
|
||||||
|
deleteId = previewItem.moduleProjectId;
|
||||||
|
confirmContent = (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 8 }}>爆款开头复刻中以下内容所连带的图片和视频都将被删除:</div>
|
||||||
|
<ul style={{ margin: 0, paddingLeft: 20 }}>
|
||||||
|
<li style={{ marginBottom: 4, color: '#334155' }}>
|
||||||
|
{previewItem.moduleProjectTitle}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div style={{ marginTop: 12 }}>确定删除吗?</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
deleteId = previewItem.id;
|
||||||
|
confirmContent = '确定删除该记录吗?';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deleteId) {
|
||||||
|
message.warning('无法获取删除ID');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: confirmContent,
|
||||||
|
okText: '确定删除',
|
||||||
|
cancelText: '取消',
|
||||||
|
okButtonProps: { danger: true },
|
||||||
|
onOk: async () => {
|
||||||
|
let historySource = '';
|
||||||
|
if (filterType === 'project') {
|
||||||
|
historySource = 'generation_record';
|
||||||
|
} else if (filterType === 'creation') {
|
||||||
|
historySource = 'chat_task';
|
||||||
|
} else if (filterType === 'hot_opening_replicate') {
|
||||||
|
historySource = 'hot_opening_replicate';
|
||||||
|
} else if (filterType === 'shot_replicate') {
|
||||||
|
historySource = 'shot_replicate';
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
history_source: historySource,
|
||||||
|
ids: [deleteId],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteResourcesMaterial(params); // 调用删除接口
|
||||||
|
message.success('删除成功');
|
||||||
|
handleClosePreview();
|
||||||
|
setPagebreak(prev => ({ ...prev, page: 1 }));
|
||||||
|
loadRecordList();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('删除失败,请重试');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
style={{ borderRadius: 8, background: 'linear-gradient(135deg, #bf0b0a 0%, #ff8165 100%)', border: 'none', boxShadow: '0 4px 16px rgba(191, 11, 10, 0.35)', fontWeight: 600, padding: '8px 24px' }}
|
||||||
|
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSinglePushToMedia}
|
onClick={handleSinglePushToMedia}
|
||||||
style={{ borderRadius: 8 }}
|
style={{ borderRadius: 8, background: '#f8f9fc', border: '1px solid #e2e8f0', color: '#64748b', fontWeight: 600, padding: '8px 24px' }}
|
||||||
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
disabled={isMediaExpired(previewItem.videoUrl || previewItem.imageUrl)}
|
||||||
>
|
>
|
||||||
推送媒体后台
|
推送媒体后台
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
style={{ borderRadius: 20 }}
|
style={{ borderRadius: 16, overflow: 'hidden' }}
|
||||||
styles={{
|
styles={{
|
||||||
body: { height: 460, display: 'flex', flexDirection: 'column', padding: 0 },
|
body: { height: 500, display: 'flex', flexDirection: 'column', padding: 0 },
|
||||||
header: { background: 'rgba(255,255,255,0.6)', backdropFilter: 'blur(10px)', borderBottom: '1px solid rgba(99, 102, 241, 0.08)', padding: '16px 24px' },
|
header: { background: '#fff', borderBottom: '1px solid #f1f5f9', padding: '16px 24px' },
|
||||||
|
mask: { backgroundColor: 'rgba(0, 0, 0, 0.5)' },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* 内容区域 */}
|
|
||||||
<div style={{
|
<div style={{
|
||||||
flex: 1,
|
width: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexWrap: 'wrap',
|
height: '100%',
|
||||||
height: '460px',
|
background: '#f8fafc',
|
||||||
gap: 20,
|
}}>
|
||||||
|
<div style={{
|
||||||
|
width: '70%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
|
||||||
padding: 20,
|
padding: 20,
|
||||||
overflow: 'auto',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}>
|
}}>
|
||||||
{/* 媒体预览 */}
|
|
||||||
<div style={{
|
|
||||||
flex: 1,
|
|
||||||
minWidth: '280px',
|
|
||||||
maxWidth: '800px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
minHeight: '200px',
|
|
||||||
}}>
|
|
||||||
{/* 检查媒体是否过期 */}
|
|
||||||
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? (
|
{isMediaExpired(previewItem.videoUrl || previewItem.imageUrl) ? (
|
||||||
<div style={{ textAlign: 'center', padding: '40px' }}>
|
<div style={{ textAlign: 'center', padding: '40px', backgroundColor: '#fff', borderRadius: 12 }}>
|
||||||
<div style={{ fontSize: 48, marginBottom: 16 }}>⚠️</div>
|
<div style={{ fontSize: 48, marginBottom: 16 }}>⚠️</div>
|
||||||
<p style={{ fontSize: 16, color: '#ff4d4f', marginBottom: 16 }}>图片/视频资源已过期,请刷新重新加载~</p>
|
<p style={{ fontSize: 15, color: '#ef4444', fontWeight: 500, marginBottom: 8 }}>资源已过期</p>
|
||||||
|
<p style={{ fontSize: 13, color: '#94a3b8' }}>请刷新页面重新加载</p>
|
||||||
</div>
|
</div>
|
||||||
) : filterMedia === 'video' ? (
|
) : filterMedia === 'video' ? (
|
||||||
<video
|
<video
|
||||||
@@ -1407,8 +1595,8 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
autoPlay
|
autoPlay
|
||||||
style={{
|
style={{
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
maxHeight: '55vh',
|
maxHeight: '100%',
|
||||||
borderRadius: 8,
|
borderRadius: 12,
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1418,148 +1606,136 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
alt="预览"
|
alt="预览"
|
||||||
style={{
|
style={{
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
maxHeight: '55vh',
|
maxHeight: '100%',
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
borderRadius: 8
|
borderRadius: 12,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 参数信息 */}
|
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '100%',
|
width: '30%',
|
||||||
minWidth: '280px',
|
height: '100%',
|
||||||
maxWidth: '320px',
|
|
||||||
background: '#f8fafc',
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 20,
|
|
||||||
maxHeight: '55vh',
|
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
overflowX: 'hidden',
|
scrollbarWidth: 'none',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
padding: 24,
|
||||||
|
borderLeft: '1px solid #f1f5f9',
|
||||||
}}>
|
}}>
|
||||||
<Typography.Text strong style={{ fontSize: 14, color: '#475569', display: 'block', marginBottom: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 20 }}>
|
||||||
|
<div style={{ width: 2, height: 18, background: 'linear-gradient(180deg, #6366f1 0%, #8b5cf6 100%)', borderRadius: 1 }} />
|
||||||
|
<Typography.Text strong style={{ fontSize: 15, color: '#1e293b', fontWeight: 600 }}>
|
||||||
文件信息
|
文件信息
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
|
||||||
{/* ID */}
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
{/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>类型</span>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>ID</span>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{previewItem.id || '-'}
|
|
||||||
</span>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
{/* 类型 */}
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>类型</span>
|
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{filterMedia === 'video' ? '视频' : '图片'}
|
{filterMedia === 'video' ? '视频' : '图片'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
{filterType === 'hot_opening_replicate' && (
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13, flexShrink: 0, width: 40 }}>请求</span>
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 4 }}>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500, flex: 1, wordBreak: 'break-all' }}>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>类属</span>
|
||||||
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500, wordBreak: 'break-all', lineHeight: '1.5' }}>
|
||||||
|
爆款复刻——{previewItem.moduleProjectTitle}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{filterType === 'shot_replicate' && (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 4 }}>
|
||||||
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>类属</span>
|
||||||
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500, wordBreak: 'break-all', lineHeight: '1.5' }}>
|
||||||
|
{previewItem.shotReplicateProjectTitle}— —{previewItem.shotSegmentLabel}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||||
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>请求</span>
|
||||||
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500, wordBreak: 'break-all', lineHeight: '1.5' }}>
|
||||||
{previewItem.originalPrompt}
|
{previewItem.originalPrompt}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 分辨率 */}
|
|
||||||
{filterMedia === 'image' && (
|
{filterMedia === 'image' && (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>比例</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>比例</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.imageProportion}
|
{previewItem.imageProportion}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>分辨率</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>分辨率</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.imageSize}
|
{previewItem.imageSize}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>尺寸</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>尺寸</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.imagePx}
|
{previewItem.imagePx}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{filterMedia === 'video' && (
|
{filterMedia === 'video' && (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>比例</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>比例</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.aspectRatio}
|
{previewItem.aspectRatio}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>分辨率</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>分辨率</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.resolution}
|
{previewItem.resolution}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>尺寸</span>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>时长</span>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
{previewItem.imagePx}
|
|
||||||
</span>
|
|
||||||
</div> */}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 时长(视频) */}
|
|
||||||
{filterMedia === 'video' && (
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>时长</span>
|
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{`${previewItem.duration}秒` || '-'}
|
{`${previewItem.duration}秒` || '-'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 文件大小 */}
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
{/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>创建时间</span>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>文件大小</span>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{previewItem.size ? formatFileSize(previewItem.size) : '-'}
|
|
||||||
</span>
|
|
||||||
</div> */}
|
|
||||||
|
|
||||||
{/* 创建时间 */}
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>创建时间</span>
|
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{formatDateTime(previewItem.createdAt || previewItem.generatedDate)}
|
{formatDateTime(previewItem.createdAt || previewItem.generatedDate)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 生成引擎 */}
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 500 }}>生成引擎</span>
|
||||||
<span style={{ color: '#94a3b8', fontSize: 13 }}>生成引擎</span>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 600 }}>
|
||||||
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
|
||||||
{previewItem.engine || previewItem.engineName || '-'}
|
{previewItem.engine || previewItem.engineName || '-'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 分隔线 */}
|
<div style={{ borderTop: '1px solid #f1f5f9', margin: '20px 0' }} />
|
||||||
<div style={{ borderTop: '1px dashed #e2e8f0', margin: '16px 0' }} />
|
|
||||||
|
|
||||||
|
{previewItem.mediaReferences && previewItem.mediaReferences.length > 0 && !['hot_opening_replicate', 'shot_replicate'].includes(filterType) && (
|
||||||
{previewItem.mediaReferences && previewItem.mediaReferences.length > 0 && (
|
|
||||||
<>
|
<>
|
||||||
<Typography.Text strong style={{ fontSize: 14, color: '#475569', display: 'block', marginBottom: 12 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 }}>
|
||||||
|
<div style={{ width: 2, height: 18, background: 'linear-gradient(180deg, #3b82f6 0%, #60a5fa 100%)', borderRadius: 1 }} />
|
||||||
|
<Typography.Text strong style={{ fontSize: 15, color: '#1e293b', fontWeight: 600 }}>
|
||||||
依靠附件
|
依靠附件
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</div>
|
||||||
{previewItem.mediaReferences.map((item, index) => (
|
{previewItem.mediaReferences.map((item, index) => (
|
||||||
<div
|
<div
|
||||||
key={item.url}
|
key={item.url}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// 暂停视频
|
|
||||||
if (videoRef.current) {
|
if (videoRef.current) {
|
||||||
videoRef.current.pause();
|
videoRef.current.pause();
|
||||||
}
|
}
|
||||||
@@ -1569,27 +1745,32 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 8,
|
gap: 10,
|
||||||
padding: 8,
|
padding: '10px 12px',
|
||||||
borderRadius: 6,
|
borderRadius: 8,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
backgroundColor: '#f1f5f9',
|
backgroundColor: '#f8fafc',
|
||||||
marginBottom: 4,
|
marginBottom: 8,
|
||||||
transition: 'background-color 0.2s',
|
transition: 'all 0.25s ease',
|
||||||
|
border: '1px solid transparent',
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
(e.currentTarget as HTMLElement).style.backgroundColor = '#e2e8f0';
|
const el = e.currentTarget as HTMLElement;
|
||||||
|
el.style.backgroundColor = '#e0f2fe';
|
||||||
|
el.style.borderColor = '#bae6fd';
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
(e.currentTarget as HTMLElement).style.backgroundColor = '#f1f5f9';
|
const el = e.currentTarget as HTMLElement;
|
||||||
|
el.style.backgroundColor = '#f8fafc';
|
||||||
|
el.style.borderColor = 'transparent';
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.type === 'image' ? (
|
{item.type === 'image' ? (
|
||||||
<PictureOutlined style={{ color: '#3b82f6', fontSize: 14 }} />
|
<PictureOutlined style={{ color: '#3b82f6', fontSize: 16 }} />
|
||||||
) : (
|
) : (
|
||||||
<VideoCameraOutlined style={{ color: '#f59e0b', fontSize: 14 }} />
|
<VideoCameraOutlined style={{ color: '#f59e0b', fontSize: 16 }} />
|
||||||
)}
|
)}
|
||||||
<span style={{ color: '#334155', fontSize: 13 }}>
|
<span style={{ color: '#334155', fontSize: 13, fontWeight: 500 }}>
|
||||||
{item.name || `媒体${index + 1}`}
|
{item.name || `媒体${index + 1}`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -1924,7 +2105,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
const id = String(record.id);
|
const id = String(record.id);
|
||||||
const newOauthItems = [...selectedOauthItems];
|
const newOauthItems = [...selectedOauthItems];
|
||||||
newOauthItems[index] = { value: id, label: String(record.accountId)+'-'+(record.accountName || '-') };
|
newOauthItems[index] = { value: id, label: String(record.accountId) + '-' + (record.accountName || '-') };
|
||||||
setSelectedOauthItems(newOauthItems);
|
setSelectedOauthItems(newOauthItems);
|
||||||
const newOauthSelectOpens = [...oauthSelectOpens];
|
const newOauthSelectOpens = [...oauthSelectOpens];
|
||||||
newOauthSelectOpens[index] = false;
|
newOauthSelectOpens[index] = false;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ const HomePage: React.FC = () => {
|
|||||||
const aiEntries = [
|
const aiEntries = [
|
||||||
{
|
{
|
||||||
icon: <FileTextOutlined style={{ fontSize: 24, color: '#6366f1' }} />,
|
icon: <FileTextOutlined style={{ fontSize: 24, color: '#6366f1' }} />,
|
||||||
title: '爆款开头复刻',
|
title: '爆款复刻',
|
||||||
description: '上传参考视频与产品图片,一键复刻爆款视频开头',
|
description: '上传参考视频与产品图片,一键复刻爆款视频开头',
|
||||||
action: '立即创作',
|
action: '立即创作',
|
||||||
path: '/initial',
|
path: '/initial',
|
||||||
@@ -106,7 +106,7 @@ const HomePage: React.FC = () => {
|
|||||||
{
|
{
|
||||||
icon: <ScissorOutlined style={{ fontSize: 24, color: '#f97316' }} />,
|
icon: <ScissorOutlined style={{ fontSize: 24, color: '#f97316' }} />,
|
||||||
title: '拆镜复刻',
|
title: '拆镜复刻',
|
||||||
description: '一键拆解画面分镜,助力仿拍或创作',
|
description: '精细化镜头复刻工具,拆分参考视频单镜头独立复刻,提升素材原创度,规避素材同质化',
|
||||||
action: '开始混剪',
|
action: '开始混剪',
|
||||||
path: '/removelens',
|
path: '/removelens',
|
||||||
},
|
},
|
||||||
@@ -143,7 +143,7 @@ const HomePage: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="content_box">
|
<div className="content_box">
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||||
<h3>首页工作台</h3>
|
<h3>首页工作台 </h3>
|
||||||
<p
|
<p
|
||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
@@ -190,7 +190,7 @@ const HomePage: React.FC = () => {
|
|||||||
background: 'linear-gradient(180deg, #6366f1, #a855f7)',
|
background: 'linear-gradient(180deg, #6366f1, #a855f7)',
|
||||||
}} />
|
}} />
|
||||||
<div style={{ fontSize: 17, fontWeight: 700, color: '#1f2937', letterSpacing: 0.3 }}>
|
<div style={{ fontSize: 17, fontWeight: 700, color: '#1f2937', letterSpacing: 0.3 }}>
|
||||||
我的项目
|
我的项目<span style={{ color: '#a8a8a8ff', fontSize: 12 }}>(操作步骤)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ function InitialInfo() {
|
|||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
||||||
|
|
||||||
<h3 style={{ margin: 0, fontSize: 16, fontWeight: 700, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
<h3 style={{ margin: 0, fontSize: 16, fontWeight: 700, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
||||||
爆款开头复刻 - 任务详情
|
爆款复刻 - 任务详情
|
||||||
</h3>
|
</h3>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
||||||
|
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ const GenerateConver: React.FC = () => {
|
|||||||
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
||||||
}}>
|
}}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} /> */}
|
||||||
<div>
|
<div>
|
||||||
<h2 style={{
|
<h2 style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
@@ -460,15 +460,15 @@ const GenerateConver: React.FC = () => {
|
|||||||
WebkitBackgroundClip: 'text',
|
WebkitBackgroundClip: 'text',
|
||||||
WebkitTextFillColor: 'transparent',
|
WebkitTextFillColor: 'transparent',
|
||||||
backgroundClip: 'text',
|
backgroundClip: 'text',
|
||||||
textAlign: 'center',
|
// textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
爆款开头复刻
|
爆款复刻
|
||||||
</h2>
|
</h2>
|
||||||
<p style={{ fontSize: 13, color: '#64748b', margin: '4px 0 0 0' }}>
|
<p style={{ fontSize: 13, color: '#64748b', margin: '4px 0 0 0' }}>
|
||||||
上传参考视频与产品图片,一键复刻爆款视频开头
|
上传参考视频与产品图片,一键复刻爆款视频开头
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} /> */}
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -796,7 +796,7 @@ const GenerateConver: React.FC = () => {
|
|||||||
暂无生成内容
|
暂无生成内容
|
||||||
</h3>
|
</h3>
|
||||||
<p style={{ margin: 0, fontSize: 13, color: '#64748b', textAlign: 'center', padding: '0 40px', lineHeight: 1.6 }}>
|
<p style={{ margin: 0, fontSize: 13, color: '#64748b', textAlign: 'center', padding: '0 40px', lineHeight: 1.6 }}>
|
||||||
请完善素材与卖点,生成专属爆款开头复刻视频
|
请完善素材与卖点,生成专属爆款复刻视频
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ const ProjectsPage: React.FC = () => {
|
|||||||
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
||||||
}}>
|
}}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} /> */}
|
||||||
<div>
|
<div>
|
||||||
<h2 style={{
|
<h2 style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
@@ -126,7 +126,7 @@ const ProjectsPage: React.FC = () => {
|
|||||||
WebkitBackgroundClip: 'text',
|
WebkitBackgroundClip: 'text',
|
||||||
WebkitTextFillColor: 'transparent',
|
WebkitTextFillColor: 'transparent',
|
||||||
backgroundClip: 'text',
|
backgroundClip: 'text',
|
||||||
textAlign: 'center',
|
// textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
我的项目
|
我的项目
|
||||||
</h2>
|
</h2>
|
||||||
@@ -134,7 +134,7 @@ const ProjectsPage: React.FC = () => {
|
|||||||
共 {projects.length} 个项目 · 按行业分类管理
|
共 {projects.length} 个项目 · 按行业分类管理
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} /> */}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
<Button icon={<FileTextOutlined />} onClick={() => navigate('/records')} size="large" style={{
|
<Button icon={<FileTextOutlined />} onClick={() => navigate('/records')} size="large" style={{
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ export default function VideoFrameExtractor() {
|
|||||||
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
position: 'relative', overflow: 'hidden', flexWrap: 'wrap', gap: 12,
|
||||||
}}>
|
}}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent)', borderRadius: 1 }} /> */}
|
||||||
<div>
|
<div>
|
||||||
<h2 style={{
|
<h2 style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
@@ -187,15 +187,15 @@ export default function VideoFrameExtractor() {
|
|||||||
WebkitBackgroundClip: 'text',
|
WebkitBackgroundClip: 'text',
|
||||||
WebkitTextFillColor: 'transparent',
|
WebkitTextFillColor: 'transparent',
|
||||||
backgroundClip: 'text',
|
backgroundClip: 'text',
|
||||||
textAlign: 'center',
|
// textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
AI视频拆镜工作台
|
AI视频拆镜工作台
|
||||||
</h2>
|
</h2>
|
||||||
<p style={{ fontSize: 13, color: '#64748b', margin: '4px 0 0 0' }}>
|
<p style={{ fontSize: 13, color: '#64748b', margin: '4px 0 0 0' }}>
|
||||||
一键拆解画面分镜,助力仿拍或创作
|
精细化镜头复刻工具,拆分参考视频单镜头独立复刻,提升素材原创度,规避素材同质化
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} />
|
{/* <div style={{ width: 32, height: 2, background: 'linear-gradient(90deg, transparent, #8b5cf6, #6366f1, transparent)', borderRadius: 1 }} /> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Reference in New Issue
Block a user