1
This commit is contained in:
+94
-94
File diff suppressed because one or more lines are too long
Vendored
+36
-36
@@ -1,37 +1,37 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script>
|
||||
(function() {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
try {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
if (info.siteLogo) {
|
||||
var link = document.querySelector('link[rel="icon"]');
|
||||
if (link) {
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script type="module" crossorigin src="/assets/index-DOtHKxdv.js"></script>
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<title>民众智创</title>
|
||||
<script>
|
||||
(function() {
|
||||
var cached = localStorage.getItem('siteInfo');
|
||||
if (cached) {
|
||||
try {
|
||||
var info = JSON.parse(cached);
|
||||
if (info.siteName) {
|
||||
document.title = info.siteName;
|
||||
}
|
||||
if (info.siteLogo) {
|
||||
var link = document.querySelector('link[rel="icon"]');
|
||||
if (link) {
|
||||
link.href = info.siteLogo;
|
||||
link.type = 'image/png';
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script type="module" crossorigin src="/assets/index-CNAElJYI.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-JhRVnnL-.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -63,12 +63,12 @@ const PrivatePortraitLibraryPanel: React.FC = () => {
|
||||
const items = useMemo(() => [
|
||||
{
|
||||
key: 'real_person',
|
||||
label: '真人素材',
|
||||
label: '真人素材库',
|
||||
children: <RealPersonLibraryPanel />,
|
||||
},
|
||||
{
|
||||
key: 'aigc_virtual',
|
||||
label: '虚拟素材',
|
||||
label: '虚拟素材库',
|
||||
children: <VirtualMaterialPanel />,
|
||||
},
|
||||
], []);
|
||||
@@ -85,11 +85,11 @@ const PrivatePortraitLibraryPanel: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16 }}>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
{/* <div style={{ marginBottom: 16 }}>
|
||||
<Title level={4} style={{ margin: 0 }}>私域素材库</Title>
|
||||
<Text type="secondary">统一管理真人素材和虚拟素材。真人项目组需先完成人脸认证,虚拟项目组会同步创建火山 AIGC Asset Group。</Text>
|
||||
</div>
|
||||
<Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
|
||||
<Text type="secondary">统一管理真人素材和虚拟素材。真人素材需先完成人脸认证后才可上传素材,虚拟素材如需使用需先上传。</Text>
|
||||
</div> */}
|
||||
{/* <Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
|
||||
<Col xs={24} md={8}>
|
||||
<Card style={{ borderRadius: 16, background: 'linear-gradient(135deg,#f5f3ff,#fff)' }}>
|
||||
<Text type="secondary">素材总额度</Text>
|
||||
@@ -103,7 +103,7 @@ const PrivatePortraitLibraryPanel: React.FC = () => {
|
||||
<div style={{ fontSize: 24, fontWeight: 700, color: '#1e293b', marginTop: 8 }}>{projects.length}</div>
|
||||
<Paragraph style={{ margin: '8px 0 0', color: '#64748b' }}>
|
||||
{activeKey === 'aigc_virtual'
|
||||
? '虚拟人像项目会同步创建火山 AIGC Asset Group。'
|
||||
? '虚拟素材如需使用需先上传'
|
||||
: '真人项目组需完成人脸认证后才可上传素材。'}
|
||||
</Paragraph>
|
||||
</Card>
|
||||
@@ -112,15 +112,18 @@ const PrivatePortraitLibraryPanel: React.FC = () => {
|
||||
<Card style={{ borderRadius: 16 }}>
|
||||
<Text type="secondary">当前项目素材</Text>
|
||||
<div style={{ fontSize: 24, fontWeight: 700, color: '#1e293b', marginTop: 8 }}>{selectedProject?.assetCount || 0}</div>
|
||||
<Paragraph style={{ margin: '8px 0 0', color: '#64748b' }}>仅 Active 状态素材可在 AI 创作中引用。</Paragraph>
|
||||
<Paragraph style={{ margin: '8px 0 0', color: '#64748b' }}>仅 入库成功 状态素材可在 AI 创作中引用。</Paragraph>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Row> */}
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
onChange={handleTabChange}
|
||||
items={items}
|
||||
destroyInactiveTabPane={false}
|
||||
tabBarExtraContent={
|
||||
<div style={{ fontSize: 14, fontWeight: 700, color: '#4f46e5', marginTop: 8 }}>{quotaText}。真人/虚拟共用,图片/视频共用;音频暂不开放。</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -124,18 +124,13 @@ const RealPersonLibraryPanel: React.FC = () => {
|
||||
<Row gutter={16}>
|
||||
<Col xs={24} lg={7}>
|
||||
<Card
|
||||
title={<span>真人素材项目组</span>}
|
||||
extra={(
|
||||
<Space size={8}>
|
||||
{/* <Button icon={<ReloadOutlined />} onClick={loadProjects} loading={loading} size="small">刷新</Button> */}
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)} size="small">新建项目组</Button>
|
||||
</Space>
|
||||
)}
|
||||
// title="真人素材项目组"
|
||||
extra={<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)}>创建项目组</Button>}
|
||||
style={{ borderRadius: 16, minHeight: 520 }}
|
||||
>
|
||||
<Spin spinning={loading}>
|
||||
{projects.length === 0 ? (
|
||||
<Empty description="暂无项目组" />
|
||||
<Empty description="暂无真人项目组" />
|
||||
) : (
|
||||
<PrivatePortraitProjectList items={projects} selectedId={selected?.id} onSelect={setSelected} />
|
||||
)}
|
||||
|
||||
@@ -386,13 +386,17 @@ const VirtualMaterialPanel: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col xs={24} lg={7}>
|
||||
<div >
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>虚拟素材库</Typography.Title>
|
||||
<Typography.Text type="secondary">可提前上传虚拟人像素材,后续生成视频时可直接使用。</Typography.Text>
|
||||
</div>
|
||||
<Row gutter={[10, 10]}>
|
||||
<Col xs={24} lg={5} >
|
||||
<Card
|
||||
title="虚拟人像项目组"
|
||||
extra={<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)}>创建项目组</Button>}
|
||||
style={{ borderRadius: 16, minHeight: 520 }}
|
||||
// title="虚拟人像项目组"
|
||||
extra={<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)}>创建项目组</Button>}
|
||||
style={{ borderRadius: 16, minHeight: 520, margin: '0 auto', maxWidth: 1200}}
|
||||
>
|
||||
<Spin spinning={projectLoading}>
|
||||
{projects.length === 0 ? (
|
||||
@@ -435,7 +439,7 @@ const VirtualMaterialPanel: React.FC = () => {
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={17}>
|
||||
<Col xs={24} lg={19}>
|
||||
<Card
|
||||
title={selectedProject ? selectedProject.name : '素材资产'}
|
||||
extra={(
|
||||
@@ -519,7 +523,7 @@ const VirtualMaterialPanel: React.FC = () => {
|
||||
onCancel={() => setCreateOpen(false)}
|
||||
onOk={handleCreateProject}
|
||||
confirmLoading={creatingProject}
|
||||
okText="创建并同步火山 Asset Group"
|
||||
okText="创建项目组"
|
||||
>
|
||||
<Form form={createForm} layout="vertical">
|
||||
<Form.Item name="name" label="项目组名称" rules={[{ required: true, message: '请输入项目组名称' }]}>
|
||||
|
||||
@@ -1480,9 +1480,9 @@ const AIChatPage: React.FC = () => {
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
|
||||
setUploading(true);
|
||||
|
||||
for (const file of files) {
|
||||
setUploading(true);
|
||||
|
||||
const result = await doUpload(file);
|
||||
|
||||
if (result) {
|
||||
@@ -1494,10 +1494,10 @@ const AIChatPage: React.FC = () => {
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
|
||||
setUploading(false);
|
||||
}
|
||||
|
||||
setUploading(false);
|
||||
|
||||
if (successCount > 0) {
|
||||
antdMessage.success(`成功上传${successCount}个文件${failCount > 0 ? `,${failCount}个文件上传失败` : ''}`);
|
||||
}
|
||||
@@ -1806,9 +1806,9 @@ const AIChatPage: React.FC = () => {
|
||||
// ==================== 渲染 ====================
|
||||
|
||||
const isFirstLastFrameComposer = mediaType === 'video' && referenceMode === 'first_last_frame';
|
||||
const composerCanSend = isFirstLastFrameComposer
|
||||
const composerCanSend = !uploading && (isFirstLastFrameComposer
|
||||
? Boolean(inputValue.trim() || firstFrame)
|
||||
: Boolean(inputValue.trim() || currentMedia.length > 0);
|
||||
: Boolean(inputValue.trim() || currentMedia.length > 0));
|
||||
const composerModeLabel = mediaType === 'image'
|
||||
? '图片生成'
|
||||
: isFirstLastFrameComposer
|
||||
|
||||
@@ -68,6 +68,7 @@ const GeneratedRecord: React.FC = () => {
|
||||
const [previewItem, setPreviewItem] = useState<any>(null);
|
||||
const videoRef = React.createRef<HTMLVideoElement>();
|
||||
const [selectedDate, setSelectedDate] = useState<string>('');
|
||||
const [searchKeyword, setSearchKeyword] = useState<string>('');
|
||||
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
@@ -778,11 +779,17 @@ const GeneratedRecord: React.FC = () => {
|
||||
if (historySource) {
|
||||
parameters = `?gen_type=${filterMedia}&history_source=${historySource}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`;
|
||||
}
|
||||
if (searchKeyword && searchKeyword.trim()) {
|
||||
parameters += `&keyword=${encodeURIComponent(searchKeyword.trim())}`;
|
||||
}
|
||||
if (selectedDate) {
|
||||
let parameters = `${selectedDate}?gen_type=${filterMedia}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`;
|
||||
if (historySource) {
|
||||
parameters = `${selectedDate}?gen_type=${filterMedia}&history_source=${historySource}&page=${Pagebreak.page}&page_size=${Pagebreak.pageSize}`;
|
||||
}
|
||||
if (searchKeyword && searchKeyword.trim()) {
|
||||
parameters += `&keyword=${encodeURIComponent(searchKeyword.trim())}`;
|
||||
}
|
||||
gethistoryItems(parameters).then((res: any) => {
|
||||
const data = Array.isArray(res) ? res : (res?.items || []);
|
||||
let recordList = [{
|
||||
@@ -885,6 +892,9 @@ const GeneratedRecord: React.FC = () => {
|
||||
if (historySource) {
|
||||
parameters = `${time}?gen_type=${filterMedia}&history_source=${historySource}&page=${addpage}&page_size=${Pagebreak.pageSize}`;
|
||||
}
|
||||
if (searchKeyword && searchKeyword.trim()) {
|
||||
parameters += `&keyword=${encodeURIComponent(searchKeyword.trim())}`;
|
||||
}
|
||||
try {
|
||||
const res: any = await gethistoryItems(parameters);
|
||||
const newItems: any[] = res.items || [];
|
||||
@@ -909,12 +919,13 @@ const GeneratedRecord: React.FC = () => {
|
||||
});
|
||||
}
|
||||
};
|
||||
// 当筛选条件改变时,重置页码
|
||||
// 当筛选条件改变时,重置页码和搜索关键词
|
||||
useEffect(() => {
|
||||
setPagebreak(prev => ({
|
||||
...prev,
|
||||
page: 1
|
||||
}));
|
||||
setSearchKeyword('');
|
||||
}, [filterType, filterMedia]);
|
||||
return (
|
||||
<div className="content_box" >
|
||||
@@ -1218,6 +1229,24 @@ const GeneratedRecord: React.FC = () => {
|
||||
清除
|
||||
</Button>
|
||||
)}
|
||||
<Input.Search
|
||||
placeholder="搜索提示词"
|
||||
allowClear
|
||||
value={searchKeyword}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
setSearchKeyword(val);
|
||||
if (!val) {
|
||||
setPagebreak(prev => ({ ...prev, page: 1 }));
|
||||
loadRecordList();
|
||||
}
|
||||
}}
|
||||
onSearch={() => {
|
||||
setPagebreak(prev => ({ ...prev, page: 1 }));
|
||||
loadRecordList();
|
||||
}}
|
||||
style={{ width: 240, borderRadius: 8 }}
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user