import React, { useEffect, useState } from 'react'; import { Button, Card, Form, Input, message, Modal, Popconfirm, Select, Space, Switch, Table, Tag, Typography, } from 'antd'; import { PlayCircleOutlined, PlusOutlined, EditOutlined, DeleteOutlined, } from '@ant-design/icons'; import { getVideoEngines, saveVideoEngine, deleteVideoEngine } from '../api'; interface VideoEngine { id: string; name: string; provider: string; apiBase: string; apiKey: string; modelName: string; supportedRatios: string[]; supportedResolutions: string[]; supportedDurations: number[]; isActive: boolean; priority: number; } function parseJsonArray(val: unknown): any[] { if (Array.isArray(val)) return val; if (typeof val === 'string') { try { return JSON.parse(val); } catch { return []; } } return []; } const AdminVideoEngines: React.FC = () => { const [engines, setEngines] = useState([]); const [loading, setLoading] = useState(false); const [modal, setModal] = useState<{ open: boolean; engine: VideoEngine | null }>({ open: false, engine: null }); const [form] = Form.useForm(); const load = async () => { setLoading(true); try { const data = await getVideoEngines(); setEngines(data.map((e: any) => ({ ...e, supportedRatios: parseJsonArray(e.supportedRatios), supportedResolutions: parseJsonArray(e.supportedResolutions), supportedDurations: parseJsonArray(e.supportedDurations), }))); } catch { message.error('加载视频引擎失败'); } finally { setLoading(false); } }; useEffect(() => { load(); }, []); const handleSave = async () => { try { const values = await form.validateFields(); const payload = { name: values.name, provider: values.provider, api_base: values.apiBase, api_key: values.apiKey, model_name: values.modelName, supported_ratios: JSON.stringify(values.supportedRatios || []), supported_resolutions: JSON.stringify(values.supportedResolutions || []), supported_durations: JSON.stringify(values.supportedDurations || []), is_active: values.isActive ?? true, priority: values.priority ?? 0, }; if (modal.engine) { await saveVideoEngine({ id: modal.engine.id, ...payload }); message.success('已更新'); } else { await saveVideoEngine(payload); message.success('已添加'); } setModal({ open: false, engine: null }); form.resetFields(); load(); } catch (e: any) { if (e?.errorFields) return; message.error(e?.message || '保存失败'); } }; const handleDelete = async (id: string) => { try { await deleteVideoEngine(id); message.success('已删除'); load(); } catch { message.error('删除失败'); } }; const openEdit = (engine?: VideoEngine) => { setModal({ open: true, engine: engine || null }); if (engine) { form.setFieldsValue(engine); } else { form.resetFields(); form.setFieldsValue({ isActive: true, priority: 0, supportedRatios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'], supportedResolutions: ['480p', '720p', '1080p'], supportedDurations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], }); } }; const columns = [ { title: '引擎名称', key: 'name', width: 180, render: (_: any, r: VideoEngine) => (
{r.name}
{r.provider}
), }, { title: '支持比例', dataIndex: 'supportedRatios', width: 200, render: (ratios: string[]) => {ratios.map(r => {r})}, }, { title: '支持分辨率', dataIndex: 'supportedResolutions', width: 150, render: (res: string[]) => {res.map(r => {r})}, }, { title: '支持时长', dataIndex: 'supportedDurations', width: 120, render: (d: number[]) => {d?.length ? `${Math.min(...d)}-${Math.max(...d)}s` : '-'}, }, { title: '状态', dataIndex: 'isActive', width: 80, render: (v: boolean) => {v ? '启用' : '停用'}, }, { title: '操作', key: 'action', width: 150, fixed: 'right' as const, render: (_: any, r: VideoEngine) => ( handleDelete(r.id)}> ), }, ]; return (
视频引擎配置 {engines.length} 个引擎
{modal.engine ? '编辑引擎' : '添加引擎'}} open={modal.open} onOk={handleSave} onCancel={() => { setModal({ open: false, engine: null }); form.resetFields(); }} okText="保存" cancelText="取消" width={620} >
); }; export default AdminVideoEngines;