1
This commit is contained in:
Vendored
+57
-57
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-CzqFKsZY.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-CvhbmotR.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D7ShJUt4.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -348,8 +348,9 @@ export async function deleteIndustryConfig(id: string): Promise<void> {
|
||||
await api.delete(`/admin/industry-configs/${id}`);
|
||||
}
|
||||
|
||||
export async function getVideoEngines(): Promise<any[]> {
|
||||
return api.get('/admin/video-engines');
|
||||
export async function getVideoEngines(options?: { includeDeleted?: boolean }): Promise<any[]> {
|
||||
const query = options?.includeDeleted ? '?include_deleted=true' : '';
|
||||
return api.get(`/admin/video-engines${query}`);
|
||||
}
|
||||
|
||||
export async function saveVideoEngine(engine: any): Promise<any> {
|
||||
@@ -361,8 +362,9 @@ export async function deleteVideoEngine(id: string): Promise<void> {
|
||||
await api.delete(`/admin/video-engines/${id}`);
|
||||
}
|
||||
|
||||
export async function getImageEngines(): Promise<any[]> {
|
||||
return api.get('/admin/image-engines');
|
||||
export async function getImageEngines(options?: { includeDeleted?: boolean }): Promise<any[]> {
|
||||
const query = options?.includeDeleted ? '?include_deleted=true' : '';
|
||||
return api.get(`/admin/image-engines${query}`);
|
||||
}
|
||||
|
||||
export async function saveImageEngine(engine: any): Promise<any> {
|
||||
|
||||
@@ -29,8 +29,13 @@ import {
|
||||
VideoCameraOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import dayjs from 'dayjs';
|
||||
import { getAdminGenerationAiTasks } from '../api';
|
||||
import type { GenerationAIMediaReference, GenerationAITaskOut } from '../types';
|
||||
import { getAdminGenerationAiTasks, getImageEngines, getVideoEngines } from '../api';
|
||||
import type {
|
||||
GenerationAiImageEngine,
|
||||
GenerationAIMediaReference,
|
||||
GenerationAITaskOut,
|
||||
GenerationAiVideoEngine,
|
||||
} from '../types';
|
||||
import { formatDate } from '../utils/formatDate';
|
||||
import GenerationTaskResourceGrid from '../components/generation/GenerationTaskResourceGrid';
|
||||
|
||||
@@ -240,6 +245,9 @@ const AdminGenerationAiRecords: React.FC = () => {
|
||||
const [createdRange, setCreatedRange] = useState<any>([todayStart(), todayEnd()]);
|
||||
const [queryCreatedRange, setQueryCreatedRange] = useState<any>([todayStart(), todayEnd()]);
|
||||
const [reloadKey, setReloadKey] = useState(0);
|
||||
const [engineListLoading, setEngineListLoading] = useState(false);
|
||||
const [imageEngines, setImageEngines] = useState<GenerationAiImageEngine[]>([]);
|
||||
const [videoEngines, setVideoEngines] = useState<GenerationAiVideoEngine[]>([]);
|
||||
|
||||
const [preview, setPreview] = useState<GenerationAITaskOut | null>(null);
|
||||
const [resourceState, setResourceState] = useState<PreviewResourceState>(EMPTY_RESOURCE_STATE);
|
||||
@@ -280,6 +288,64 @@ const AdminGenerationAiRecords: React.FC = () => {
|
||||
load();
|
||||
}, [load, reloadKey]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
const loadEngineOptions = async () => {
|
||||
setEngineListLoading(true);
|
||||
try {
|
||||
const [images, videos] = await Promise.all([
|
||||
getImageEngines({ includeDeleted: true }),
|
||||
getVideoEngines({ includeDeleted: true }),
|
||||
]);
|
||||
if (!cancelled) {
|
||||
setImageEngines(images || []);
|
||||
setVideoEngines(videos || []);
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (!cancelled) {
|
||||
message.error(error?.message || '加载模型引擎列表失败');
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) setEngineListLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
void loadEngineOptions();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const engineOptions = useMemo(() => {
|
||||
const toOption = (
|
||||
engine: GenerationAiImageEngine | GenerationAiVideoEngine,
|
||||
type: 'image' | 'video',
|
||||
) => {
|
||||
const deleted = Boolean(engine.deletedAt);
|
||||
const typeText = type === 'image' ? '图片' : '视频';
|
||||
const deletedText = deleted ? '[已删除]' : '';
|
||||
const detailText = [engine.name, engine.modelName, engine.provider, engine.id]
|
||||
.filter(Boolean)
|
||||
.join(' / ');
|
||||
const label = `[${typeText}]${deletedText} ${detailText}`;
|
||||
return {
|
||||
value: engine.id,
|
||||
label,
|
||||
searchText: [engine.id, engine.name, engine.modelName, engine.provider, typeText, deleted ? '已删除' : '']
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
.toLowerCase(),
|
||||
};
|
||||
};
|
||||
|
||||
const merged = [
|
||||
...imageEngines.map((engine) => toOption(engine, 'image')),
|
||||
...videoEngines.map((engine) => toOption(engine, 'video')),
|
||||
];
|
||||
return Array.from(new Map(merged.map((option) => [option.value, option])).values());
|
||||
}, [imageEngines, videoEngines]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!preview) {
|
||||
setResourceState(EMPTY_RESOURCE_STATE);
|
||||
@@ -969,21 +1035,17 @@ const AdminGenerationAiRecords: React.FC = () => {
|
||||
<Select
|
||||
allowClear
|
||||
showSearch
|
||||
loading={engineListLoading}
|
||||
placeholder="引擎筛选"
|
||||
value={filterEngineId || undefined}
|
||||
style={{ width: 180 }}
|
||||
style={{ width: 260 }}
|
||||
onChange={(v) => { setFilterEngineId(v || ''); setPage(1); setQueryEngineId(v || ''); }}
|
||||
optionFilterProp="label"
|
||||
options={Array.from(
|
||||
new Map(
|
||||
records
|
||||
.filter((r) => r.engineId)
|
||||
.map((r) => [r.engineId, {
|
||||
value: r.engineId,
|
||||
label: getEngineName(r.engineSnapshot as any) || r.engineId,
|
||||
}]),
|
||||
).values(),
|
||||
)}
|
||||
filterOption={(input, option: any) =>
|
||||
String(option?.searchText || option?.label || '')
|
||||
.toLowerCase()
|
||||
.includes(input.trim().toLowerCase())
|
||||
}
|
||||
options={engineOptions}
|
||||
/>
|
||||
<RangePicker
|
||||
value={createdRange}
|
||||
|
||||
@@ -285,6 +285,8 @@ export interface GenerationAiImageEngine {
|
||||
maxGenerationCount: number;
|
||||
multiImageMaxImages: number;
|
||||
maxReferenceImageCount: number;
|
||||
isActive?: boolean;
|
||||
deletedAt?: string | null;
|
||||
}
|
||||
|
||||
export interface GenerationAiVideoEngine {
|
||||
@@ -305,6 +307,8 @@ export interface GenerationAiVideoEngine {
|
||||
priority: number;
|
||||
multiGenerationEnabled: boolean;
|
||||
maxGenerationCount: number;
|
||||
isActive?: boolean;
|
||||
deletedAt?: string | null;
|
||||
}
|
||||
|
||||
export interface GenerationAiEnginesResponse {
|
||||
|
||||
Reference in New Issue
Block a user