fix: 修复 CI 构建 49 个 TypeScript 错误
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 10s
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 10s
- routes/index.tsx: DataPages → 独立文件 import - 导出 CostItem、CostSummary、Conversation、HealthService 类型 - ServerInfo、ProcessInfo、ServerHealth 类型补全嵌套字段 - 修复 useRef 缺初始值、string|null、unused imports 等 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8663ceba66
commit
f291f39049
@ -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<string, number> }>('/admin-api/costs/summary') },
|
||||
summary() { return api.get<CostSummary>('/admin-api/costs/summary') },
|
||||
list() { return api.get<CostItem[]>('/admin-api/costs') },
|
||||
create(data: Omit<CostItem, 'id' | 'currency'> & { currency?: string }) { return api.post<CostItem>('/admin-api/costs', data) },
|
||||
update(id: string, data: Partial<CostItem>) { return api.patch<CostItem>(`/admin-api/costs/${id}`, data) },
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
@ -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') },
|
||||
|
||||
@ -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
|
||||
|
||||
@ -30,7 +30,7 @@ export default function ImportMonitorPage() {
|
||||
|
||||
// 知识库远程搜索(防抖)
|
||||
const [kbSearch, setKbSearch] = useState('')
|
||||
const kbSearchTimer = useRef<ReturnType<typeof setTimeout>>()
|
||||
const kbSearchTimer = useRef<ReturnType<typeof setTimeout>>(undefined)
|
||||
|
||||
const handleKbSearch = useCallback((val: string) => {
|
||||
clearTimeout(kbSearchTimer.current)
|
||||
|
||||
@ -30,7 +30,7 @@ function KBPage() {
|
||||
const [refSourceId, setRefSourceId] = useState<string | null>(null)
|
||||
const { data: references } = useQuery({
|
||||
queryKey: ['source-refs', refSourceId],
|
||||
queryFn: (): Promise<any> => knowledgeAPI.sourceReferences(refSourceId),
|
||||
queryFn: (): Promise<any> => knowledgeAPI.sourceReferences(refSourceId || ''),
|
||||
enabled: !!refSourceId,
|
||||
})
|
||||
|
||||
|
||||
@ -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<string, string> = {
|
||||
|
||||
@ -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('导出失败')
|
||||
|
||||
@ -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 */}
|
||||
<div style={{ marginBottom: 12, height: 54, overflow: 'hidden' }}>
|
||||
<Space wrap size={[4, 4]}>
|
||||
<CopyTag text={server.network.publicIp} icon="🌐 " color="cyan" />
|
||||
<CopyTag text={server.network.privateIp} icon="🔒 " />
|
||||
<CopyTag text={server.network.publicIp || ''} icon="🌐 " color="cyan" />
|
||||
<CopyTag text={server.network.privateIp || ''} icon="🔒 " />
|
||||
{server.network.domains.map(d => (
|
||||
<CopyTag key={d} text={d} icon={<GlobalOutlined style={{ marginRight: 2 }} />} color="blue" />
|
||||
))}
|
||||
@ -186,7 +186,7 @@ function ServersContent() {
|
||||
{(health as ServerHealth[]).map(h => (
|
||||
<Card key={h.serverName} title={h.serverName} size="small" style={{ marginBottom: 8 }}>
|
||||
<Space wrap>
|
||||
{h.services.map(s => (
|
||||
{(h.services ?? []).map(s => (
|
||||
<Tag key={s.serviceName} color={s.status === 'healthy' ? 'green' : 'red'}>
|
||||
{s.serviceName} · {s.message}
|
||||
</Tag>
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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'))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user