This commit is contained in:
2026-07-09 15:16:22 +08:00
parent 2c0a51883c
commit a75b863f16
9 changed files with 219 additions and 162 deletions
File diff suppressed because one or more lines are too long
+36 -36
View File
@@ -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: '请输入项目组名称' }]}>
+6 -6
View File
@@ -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
+30 -1
View File
@@ -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