import { useState } from 'react' import { Button, Drawer, Form, Input, message, Popconfirm, Space, Table, Tag, Select, Tooltip, } from 'antd' import { PlusOutlined, ApiOutlined, EditOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons' import { targetsApi, type Target } from '../api' import PageWrapper from '../components/PageWrapper' import { useResource } from '../hooks/useResource' import { colors } from '../tokens' import { formatDateTime } from '../utils/date' export default function TargetsPage() { const { data: targets, loading, reload } = useResource( () => targetsApi.list().then((r) => r.data), { tabPath: '/targets' }, ) const [drawerOpen, setDrawerOpen] = useState(false) const [editingTarget, setEditingTarget] = useState(null) const [form] = Form.useForm() const openCreate = () => { setEditingTarget(null) form.resetFields() form.setFieldsValue({ platform: 'ai_digital_employee', channel_type: 'tutu-api', }) setDrawerOpen(true) } const openEdit = (target: Target) => { setEditingTarget(target) form.setFieldsValue({ name: target.name, description: target.description, platform: target.platform, channel_type: target.channel_type, base_url: (target.channel_config as any)?.base_url || '', token: (target.channel_config as any)?.token || '', tenant: (target.channel_config as any)?.tenant || '', chat_channel_id: (target.channel_config as any)?.chat_channel_id || '', chat_contact_id: (target.channel_config as any)?.chat_contact_id || '', }) setDrawerOpen(true) } const handleSubmit = async () => { const values = await form.validateFields() const channel_config = { base_url: values.base_url, token: values.token, tenant: values.tenant, chat_channel_id: values.chat_channel_id, chat_contact_id: values.chat_contact_id, } const payload = { name: values.name, description: values.description || '', platform: values.platform, channel_type: values.channel_type, channel_config, status: 'active', } if (editingTarget) { await targetsApi.update(editingTarget.id, payload) message.success('更新成功') } else { await targetsApi.create(payload) message.success('创建成功') } setDrawerOpen(false) reload() } const handleTest = async (id: string) => { try { const res = await targetsApi.test(id) if (res.data.ok) { message.success('通道连通正常') } else { message.warning(`通道异常: ${res.data.message}`) } } catch { message.error('连通性测试失败') } } const handleDelete = async (id: string) => { await targetsApi.delete(id) message.success('已删除') reload() } const statusColor: Record = { active: 'success', inactive: 'default', error: 'error', } const columns = [ { title: '名称', dataIndex: 'name', key: 'name', width: 180, render: (v: string) => {v}, }, { title: '平台', dataIndex: 'platform', key: 'platform', width: 160, render: (p: string) => p === 'ai_digital_employee' ? 'AI 数字员工' : 'AI 助手', }, { title: '通道类型', dataIndex: 'channel_type', key: 'channel_type', width: 120 }, { title: '状态', dataIndex: 'status', key: 'status', width: 100, render: (s: string) => {s}, }, { title: '创建时间', dataIndex: 'created_at', key: 'created_at', width: 180, render: (t: string) => formatDateTime(t), }, { title: '操作', key: 'action', width: 160, fixed: 'right' as const, render: (_: any, record: Target) => ( } > {/* 表格区 — 撑满剩余高度 */}
`共 ${t} 个` }} scroll={{ y: 'calc(100vh - 200px)' }} style={{ height: '100%' }} /> setDrawerOpen(false)} width={480} extra={ } >
通道配置
) }