diff --git a/src/api/costs.ts b/src/api/costs.ts index e63a51f..2626209 100644 --- a/src/api/costs.ts +++ b/src/api/costs.ts @@ -1,9 +1,10 @@ import { api } from '@/lib/api-client' -export interface CostItem { id: string; currency: string; amount: number; [key: string]: any } +export interface CostItem { id: string; name: string; currency: string; amount: number; purchaseDate?: string; expiryDate?: string; [key: string]: any } +export interface CostSummary { totalMonthly: number; totalYearly: number; totalOneTime: number; items: CostItem[]; byMonth: any[]; expiringSoon: any[] } export const costsAPI = { - summary() { return api.get<{ totalMonthly: number; byProvider: Record }>('/admin-api/costs/summary') }, + summary() { return api.get('/admin-api/costs/summary') }, list() { return api.get('/admin-api/costs') }, create(data: Omit & { currency?: string }) { return api.post('/admin-api/costs', data) }, update(id: string, data: Partial) { return api.patch(`/admin-api/costs/${id}`, data) }, diff --git a/src/api/index.ts b/src/api/index.ts index 32aefc4..680b1af 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -3,12 +3,12 @@ export { usersAPI } from './users' export { dashboardAPI } from './dashboard' export { auditAPI } from './audit' export { billingAPI, type BillingInfo } from './billing' -export { costsAPI } from './costs' +export { costsAPI, type CostItem, type CostSummary } from './costs' export { configAPI } from './config' -export { conversationsAPI } from './conversations' +export { conversationsAPI, type Conversation } from './conversations' export { eventsQueueAPI } from './events-queue' export { knowledgeAPI } from './knowledge' -export { serversAPI } from './servers' +export { serversAPI, type ServerInfo, type ProcessInfo, type ServerHealth, type HealthService } from './servers' export { learningAPI } from './learning' export { aiAPI } from './ai' diff --git a/src/api/servers.ts b/src/api/servers.ts index acce87a..3b1fd6e 100644 --- a/src/api/servers.ts +++ b/src/api/servers.ts @@ -1,8 +1,18 @@ import { api } from '@/lib/api-client' -export interface ServerInfo { hostname: string; cpu: number; memory: number; [key: string]: any } -export interface ServerHealth { name: string; status: string; [key: string]: any } -export interface WorkerInfo { name: string; status: string; [key: string]: any } +export interface ServerInfo { + hostname: string + cpu: { usagePercent: number; cores: number; model?: string } + memory: { percent: number; used: string; total: string } + network: { domains: string[]; privateIp?: string; publicIp?: string } + disks: { mount: string; size: string; used: string; percent: number }[] + [key: string]: any +} + +export interface ProcessInfo { pid: number; name: string; cpu: number; memory: number; desc?: string; command?: string; [key: string]: any } +export interface HealthService { serviceName: string; status: string; message?: string } +export interface ServerHealth { name: string; status: string; uptime?: string; pid?: number; services?: HealthService[]; queues?: string[]; [key: string]: any } +export interface WorkerInfo { name: string; status: string; queues?: string[]; [key: string]: any } export const serversAPI = { metrics() { return api.get<{ servers: ServerInfo[] }>('/admin-api/servers') }, diff --git a/src/pages/Billing.tsx b/src/pages/Billing.tsx index da34cc0..238ea48 100644 --- a/src/pages/Billing.tsx +++ b/src/pages/Billing.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Card, Row, Col, Statistic, Button, Tag, Space, Typography, App, Table, Modal, Form, Input, Select, DatePicker, InputNumber, Tabs } from 'antd' import { DollarOutlined, ReloadOutlined, LinkOutlined, PlusOutlined, DeleteOutlined, EditOutlined, CloudOutlined, DownloadOutlined } from '@ant-design/icons' -import { billingAPI, costsAPI, type BillingInfo } from '@/api' +import { billingAPI, costsAPI, type BillingInfo, type CostItem, type CostSummary } from '@/api' import dayjs from 'dayjs' const { Text, Title } = Typography diff --git a/src/pages/ImportMonitor.tsx b/src/pages/ImportMonitor.tsx index 021a49d..14c1c3c 100644 --- a/src/pages/ImportMonitor.tsx +++ b/src/pages/ImportMonitor.tsx @@ -30,7 +30,7 @@ export default function ImportMonitorPage() { // 知识库远程搜索(防抖) const [kbSearch, setKbSearch] = useState('') - const kbSearchTimer = useRef>() + const kbSearchTimer = useRef>(undefined) const handleKbSearch = useCallback((val: string) => { clearTimeout(kbSearchTimer.current) diff --git a/src/pages/KnowledgeBases.tsx b/src/pages/KnowledgeBases.tsx index ca1089e..c2e4501 100644 --- a/src/pages/KnowledgeBases.tsx +++ b/src/pages/KnowledgeBases.tsx @@ -30,7 +30,7 @@ function KBPage() { const [refSourceId, setRefSourceId] = useState(null) const { data: references } = useQuery({ queryKey: ['source-refs', refSourceId], - queryFn: (): Promise => knowledgeAPI.sourceReferences(refSourceId), + queryFn: (): Promise => knowledgeAPI.sourceReferences(refSourceId || ''), enabled: !!refSourceId, }) diff --git a/src/pages/KnowledgeSources.tsx b/src/pages/KnowledgeSources.tsx index c77194b..e6f088b 100644 --- a/src/pages/KnowledgeSources.tsx +++ b/src/pages/KnowledgeSources.tsx @@ -26,23 +26,6 @@ interface KnowledgeSourceItem { kbName?: string } -interface PaginatedSources { - items: KnowledgeSourceItem[] - total: number - page: number - limit: number -} - -interface KnowledgeBaseItem { - id: string - title?: string - name?: string -} - -interface PaginatedKnowledgeBases { - items: KnowledgeBaseItem[] -} - // ── Labels ── const mimeLabels: Record = { diff --git a/src/pages/ReportingAdmin.tsx b/src/pages/ReportingAdmin.tsx index 564783e..ae0af48 100644 --- a/src/pages/ReportingAdmin.tsx +++ b/src/pages/ReportingAdmin.tsx @@ -24,7 +24,7 @@ export default function ReportingAdmin() { const download = async (type: string) => { try { - const text = await reportingAPI.exportCSV(type, days) + const text = await reportingAPI.exportCSV(type, String(days)) downloadBlob(text as string, `${type}-report-${days}d.csv`) } catch { message.error('导出失败') diff --git a/src/pages/Servers.tsx b/src/pages/Servers.tsx index d8ee90f..0b406c9 100644 --- a/src/pages/Servers.tsx +++ b/src/pages/Servers.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Card, Row, Col, Progress, Table, Tag, Typography, Button, Space, Tooltip, App } from 'antd' import { CloudServerOutlined, ReloadOutlined, CopyOutlined, GlobalOutlined } from '@ant-design/icons' -import { serversAPI, type ServerInfo, type ServerHealth } from '@/api/servers' +import { serversAPI, type ServerInfo, type ProcessInfo, type ServerHealth } from '@/api/servers' const { Text, Title } = Typography @@ -28,8 +28,8 @@ function ServerCard({ server }: { server: ServerInfo }) { {/* IP & domains — fixed height */}
- - + + {server.network.domains.map(d => ( } color="blue" /> ))} @@ -186,7 +186,7 @@ function ServersContent() { {(health as ServerHealth[]).map(h => ( - {h.services.map(s => ( + {(h.services ?? []).map(s => ( {s.serviceName} · {s.message} diff --git a/src/pages/TaskAssistant.tsx b/src/pages/TaskAssistant.tsx index 78eddd3..c74448f 100644 --- a/src/pages/TaskAssistant.tsx +++ b/src/pages/TaskAssistant.tsx @@ -1,7 +1,7 @@ import { useState, useRef, useEffect, useCallback } from 'react' import { Input, Button, Typography, App, message as antMsg } from 'antd' import { PlusOutlined, ToolOutlined, DeleteOutlined, MessageOutlined, ArrowUpOutlined, CopyOutlined } from '@ant-design/icons' -import { aiAPI, conversationsAPI } from '@/api' +import { aiAPI, conversationsAPI, type Conversation } from '@/api' import { streamChat, type StreamEvent } from '@/services/ai-chat' import Markdown from '@/components/Markdown' @@ -37,7 +37,7 @@ function ChatPage() { const switchConversation = useCallback(async (id: string) => { if (streaming) { abortRef.current?.abort(); setStreaming(false); setWaitingApproval(false) } setActiveId(id); setMessages([]) - try { const records = await conversationsAPI.messages(id); setMessages(records.map(m => ({ id: m.id, role: m.role, content: m.content, timestamp: new Date(m.createdAt).getTime() }))) } catch {} + try { const records = await conversationsAPI.messages(id); setMessages(records.map(m => ({ id: m.id, role: m.role as 'user' | 'assistant', content: m.content, timestamp: new Date(m.createdAt).getTime() }))) } catch {} }, [streaming]) const handleNew = async () => { diff --git a/src/pages/learning/DailyActivityPage.tsx b/src/pages/learning/DailyActivityPage.tsx index 925f6ad..fcdf8ea 100644 --- a/src/pages/learning/DailyActivityPage.tsx +++ b/src/pages/learning/DailyActivityPage.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Table, Input, Select, Space, Button, Drawer, Descriptions, DatePicker } from 'antd'; +import { Table, Input, Space, Button, Drawer, Descriptions, DatePicker } from 'antd'; import { useQuery } from '@tanstack/react-query'; import { learningAPI } from '@/api'; import { PageWrapper } from './PageWrapper'; diff --git a/src/pages/learning/SessionPage.tsx b/src/pages/learning/SessionPage.tsx index 7a485fe..f5f8ba6 100644 --- a/src/pages/learning/SessionPage.tsx +++ b/src/pages/learning/SessionPage.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Table, Input, Select, Space, Tag, Button, Tabs, Drawer, Descriptions, DatePicker, Timeline, Typography, Popconfirm } from 'antd'; +import { Table, Input, Select, Space, Tag, Button, Drawer, Descriptions, Popconfirm } from 'antd'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { learningAPI } from '@/api'; import { sessionStatusLabels, targetTypeLabels, sessionModeLabels } from '@/constants/labels'; diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 94ea49a..c17e7e7 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -6,15 +6,15 @@ const UserManagement = lazy(() => import('@/pages/UserManagement')) const MemberManagement = lazy(() => import('@/pages/MemberManagement')) const LearningDashboard = lazy(() => import('@/pages/learning/Dashboard')) -const ReadingEventPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.ReadingEventPage }))) -const SessionPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.SessionPage }))) -const ProgressPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.ProgressPage }))) -const DailyActivityPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.DailyActivityPage }))) -const RecordPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.RecordPage }))) -const AnomalyPage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.AnomalyPage }))) -const UserTimelinePage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.UserTimelinePage }))) -const UserDiagnosePage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.UserDiagnosePage }))) -const MaterialDiagnosePage = lazy(() => import('@/pages/learning/DataPages').then(m => ({ default: m.MaterialDiagnosePage }))) +const ReadingEventPage = lazy(() => import('@/pages/learning/ReadingEventPage')) +const SessionPage = lazy(() => import('@/pages/learning/SessionPage')) +const ProgressPage = lazy(() => import('@/pages/learning/ProgressPage')) +const DailyActivityPage = lazy(() => import('@/pages/learning/DailyActivityPage')) +const RecordPage = lazy(() => import('@/pages/learning/RecordPage')) +const AnomalyPage = lazy(() => import('@/pages/learning/AnomalyPage')) +const UserTimelinePage = lazy(() => import('@/pages/learning/UserTimelinePage')) +const UserDiagnosePage = lazy(() => import('@/pages/learning/UserDiagnosePage')) +const MaterialDiagnosePage = lazy(() => import('@/pages/learning/MaterialDiagnosePage')) const ServersPage = lazy(() => import('@/pages/Servers')) const KnowledgeSourcesPage = lazy(() => import('@/pages/KnowledgeSources')) const LearningReplay = lazy(() => import('@/pages/learning/ReplayPage'))