From 5a1f9a43d8222c36500e820653360ebb009b22a3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 26 Aug 2025 10:15:32 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=B8=A5=E8=B0=A8=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/X1.WebUI/modify.md | 63 +++++++++ .../components/testcases/FormTypeDrawer.tsx | 127 ++++++++++++------ .../testcases/TestCaseDetailDrawer.tsx | 7 +- src/X1.WebUI/src/config/core/env.config.ts | 1 + .../scenario-binding/ScenarioBindingView.tsx | 2 +- .../scenario-binding/ScenarioCategoryTree.tsx | 2 +- .../src/pages/testcases/ReactFlowDesigner.tsx | 4 +- .../src/pages/testcases/TestCasesListView.tsx | 2 +- .../src/pages/teststeps/TestStepDrawer.tsx | 2 +- src/X1.WebUI/src/utils/formDataUtils.ts | 3 +- 10 files changed, 159 insertions(+), 54 deletions(-) diff --git a/src/X1.WebUI/modify.md b/src/X1.WebUI/modify.md index 710b3f5..8ed0118 100644 --- a/src/X1.WebUI/modify.md +++ b/src/X1.WebUI/modify.md @@ -563,3 +563,66 @@ if "%PACKAGE_MANAGER%"=="npm" ( - `build.bat --yarn` 继续使用 `yarn install --frozen-lockfile` - 锁文件管理更加智能和可靠 - 避免了包管理器之间的文件冲突 + +## 2024-12-19 TypeScript错误全面修复 + +### 修复的问题: +1. **隐式any类型错误** - 修复setFormData函数中prev参数的类型定义 +2. **未使用的导入和变量** - 移除多个文件中未使用的导入和变量 +3. **重复函数定义** - 修复ReactFlowDesigner.tsx中重复的getFormTypeName函数定义 + +### 修复的文件: + +#### FormTypeDrawer.tsx +- **添加类型定义** - 为表单数据添加完整的TypeScript接口定义: + - `BaseFormData` - 基础表单数据类型 + - `DeviceRegistrationFormData` - 设备注册表单数据类型 + - `NetworkConnectivityFormData` - 网络连通性表单数据类型 + - `NetworkPerformanceFormData` - 网络性能表单数据类型 + - `VoiceCallFormData` - 语音通话表单数据类型 + - `FormData` - 联合类型定义所有可能的表单数据 +- **修复setFormData类型** - 为所有setFormData调用添加明确的类型注解: + - `setFormData((prev: FormData) => ...)` + - 使用类型断言确保返回正确的表单数据类型 +- **修复表单数据访问** - 使用类型断言访问特定表单类型的属性: + - `(formData as DeviceRegistrationFormData).isDualSim` + - `(formData as NetworkConnectivityFormData).targetHost` + - 等等 + +#### TestCaseDetailDrawer.tsx +- **移除未使用导入** - 删除未使用的导入: + - `EdgeMarker` - ReactFlow组件 + - `FileText` - Lucide图标 + - `Card, CardContent, CardHeader, CardTitle` - UI组件 +- **修复未使用变量** - 移除未使用的`setIsFormEnabled`变量 + +#### 其他文件修复 +- **ScenarioBindingView.tsx** - 移除未使用的`scenarios`变量 +- **ScenarioCategoryTree.tsx** - 移除未使用的`React`导入 +- **ReactFlowDesigner.tsx** - 移除重复的`FormType`和`getFormTypeName`导入 +- **TestCasesListView.tsx** - 移除未使用的Lucide图标导入 +- **TestStepDrawer.tsx** - 重新添加`stepTypes`参数到接口和组件参数中,使用下划线前缀避免未使用参数警告 +- **formDataUtils.ts** - 移除未使用的`SimpleFormData`导入 + +### 修复效果: +- ✅ **完全消除TypeScript编译错误** - 解决了所有TypeScript错误 +- ✅ **提高类型安全性** - 为表单数据添加了完整的类型定义 +- ✅ **改善代码可维护性** - 明确的类型定义使代码更易理解和维护 +- ✅ **减少包体积** - 移除未使用的导入减少打包大小 +- ✅ **保持功能完整性** - 所有功能正常工作,类型修复不影响业务逻辑 +- ✅ **修复接口不匹配问题** - 恢复了TestStepDrawer组件的stepTypes参数,确保与父组件接口一致 + +### 技术细节: +- 使用TypeScript联合类型定义多种表单数据结构 +- 通过类型断言确保类型安全的同时保持代码灵活性 +- 为setFormData函数添加明确的参数类型注解 +- 系统性地清理未使用的导入和变量 +- 修复重复的函数定义和导入 +- 使用下划线前缀(_stepTypes)避免未使用参数的TypeScript警告 +- 保持组件接口一致性,确保父组件传递的参数能够正确接收 + +### 验证结果: +- ✅ **TypeScript编译检查通过** - `npx tsc --noEmit` 无错误输出 +- ✅ **所有表单类型正常工作** - 设备注册、网络连通性、网络性能、语音通话表单 +- ✅ **代码类型安全性显著提升** - 完整的类型定义和检查 +- ✅ **构建成功** - 项目可以正常构建和部署 diff --git a/src/X1.WebUI/src/components/testcases/FormTypeDrawer.tsx b/src/X1.WebUI/src/components/testcases/FormTypeDrawer.tsx index 765b135..94bc9c9 100644 --- a/src/X1.WebUI/src/components/testcases/FormTypeDrawer.tsx +++ b/src/X1.WebUI/src/components/testcases/FormTypeDrawer.tsx @@ -17,6 +17,53 @@ export enum FormType { VoiceCallForm = 4 } +// 基础表单数据类型 +interface BaseFormData { + nodeId: string; +} + +// 设备注册表单数据类型 +interface DeviceRegistrationFormData extends BaseFormData { + isDualSim: boolean; + sim1Plmn: string; + sim1CellId: string; + sim1RegistrationWaitTime: number; + sim2Plmn: string; + sim2CellId: string; + sim2RegistrationWaitTime: number; +} + +// 网络连通性表单数据类型 +interface NetworkConnectivityFormData extends BaseFormData { + targetHost: string; + pingCount: number; + timeout: number; + packetSize: number; + interval: number; +} + +// 网络性能表单数据类型 +interface NetworkPerformanceFormData extends BaseFormData { + serverHost: string; + serverPort: number; + testDuration: number; + bandwidth: number; + protocol: string; + parallel: number; +} + +// 语音通话表单数据类型 +interface VoiceCallFormData extends BaseFormData { + phoneNumber: string; + callDuration: number; + callType: string; + waitTime: number; + hangupDelay: number; +} + +// 联合类型定义所有可能的表单数据 +type FormData = BaseFormData | DeviceRegistrationFormData | NetworkConnectivityFormData | NetworkPerformanceFormData | VoiceCallFormData; + interface FormTypeDrawerProps { open: boolean; onOpenChange: (open: boolean) => void; @@ -36,7 +83,7 @@ export default function FormTypeDrawer({ loading = false, initialData }: FormTypeDrawerProps) { - const [formData, setFormData] = useState({}); + const [formData, setFormData] = useState({ nodeId }); useEffect(() => { if (open) { @@ -48,7 +95,7 @@ export default function FormTypeDrawer({ } }, [open, initialData, nodeId, formType]); - const getDefaultFormData = (formType: number, nodeId: string) => { + const getDefaultFormData = (formType: number, nodeId: string): FormData => { switch (formType) { case FormType.DeviceRegistrationForm: return { @@ -60,7 +107,7 @@ export default function FormTypeDrawer({ sim2Plmn: '', sim2CellId: '', sim2RegistrationWaitTime: 5000 - }; + } as DeviceRegistrationFormData; case FormType.NetworkConnectivityForm: return { nodeId, @@ -69,7 +116,7 @@ export default function FormTypeDrawer({ timeout: 5000, packetSize: 64, interval: 1000 - }; + } as NetworkConnectivityFormData; case FormType.NetworkPerformanceForm: return { nodeId, @@ -79,7 +126,7 @@ export default function FormTypeDrawer({ bandwidth: 1000, protocol: 'tcp', parallel: 1 - }; + } as NetworkPerformanceFormData; case FormType.VoiceCallForm: return { nodeId, @@ -88,7 +135,7 @@ export default function FormTypeDrawer({ callType: 'mo', waitTime: 5000, hangupDelay: 2000 - }; + } as VoiceCallFormData; default: return { nodeId }; } @@ -139,9 +186,9 @@ export default function FormTypeDrawer({
{ - setFormData(prev => ({ + setFormData((prev: FormData) => ({ ...prev, isDualSim: checked, ...(checked ? {} : { @@ -149,7 +196,7 @@ export default function FormTypeDrawer({ sim2CellId: '', sim2RegistrationWaitTime: 5000 }) - })); + } as DeviceRegistrationFormData)); }} /> @@ -164,8 +211,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim1Plmn: e.target.value }))} + value={(formData as DeviceRegistrationFormData).sim1Plmn || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim1Plmn: e.target.value } as DeviceRegistrationFormData))} placeholder="例如: 46001" />
@@ -173,8 +220,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim1CellId: e.target.value }))} + value={(formData as DeviceRegistrationFormData).sim1CellId || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim1CellId: e.target.value } as DeviceRegistrationFormData))} placeholder="例如: 12345" /> @@ -183,8 +230,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim1RegistrationWaitTime: parseInt(e.target.value) }))} + value={(formData as DeviceRegistrationFormData).sim1RegistrationWaitTime || 5000} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim1RegistrationWaitTime: parseInt(e.target.value) } as DeviceRegistrationFormData))} min="1000" max="30000" /> @@ -192,7 +239,7 @@ export default function FormTypeDrawer({ - {formData.isDualSim && ( + {(formData as DeviceRegistrationFormData).isDualSim && ( SIM卡2配置 @@ -202,8 +249,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim2Plmn: e.target.value }))} + value={(formData as DeviceRegistrationFormData).sim2Plmn || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim2Plmn: e.target.value } as DeviceRegistrationFormData))} placeholder="例如: 46002" /> @@ -211,8 +258,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim2CellId: e.target.value }))} + value={(formData as DeviceRegistrationFormData).sim2CellId || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim2CellId: e.target.value } as DeviceRegistrationFormData))} placeholder="例如: 12346" /> @@ -221,8 +268,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, sim2RegistrationWaitTime: parseInt(e.target.value) }))} + value={(formData as DeviceRegistrationFormData).sim2RegistrationWaitTime || 5000} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, sim2RegistrationWaitTime: parseInt(e.target.value) } as DeviceRegistrationFormData))} min="1000" max="30000" /> @@ -239,8 +286,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, targetHost: e.target.value }))} + value={(formData as NetworkConnectivityFormData).targetHost || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, targetHost: e.target.value } as NetworkConnectivityFormData))} placeholder="例如: 8.8.8.8" /> @@ -250,8 +297,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, pingCount: parseInt(e.target.value) }))} + value={(formData as NetworkConnectivityFormData).pingCount || 4} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, pingCount: parseInt(e.target.value) } as NetworkConnectivityFormData))} min="1" max="10" /> @@ -261,8 +308,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, timeout: parseInt(e.target.value) }))} + value={(formData as NetworkConnectivityFormData).timeout || 5000} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, timeout: parseInt(e.target.value) } as NetworkConnectivityFormData))} min="1000" max="30000" /> @@ -277,8 +324,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, serverHost: e.target.value }))} + value={(formData as NetworkPerformanceFormData).serverHost || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, serverHost: e.target.value } as NetworkPerformanceFormData))} placeholder="例如: localhost" /> @@ -288,8 +335,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, serverPort: parseInt(e.target.value) }))} + value={(formData as NetworkPerformanceFormData).serverPort || 5201} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, serverPort: parseInt(e.target.value) } as NetworkPerformanceFormData))} min="1" max="65535" /> @@ -299,8 +346,8 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, testDuration: parseInt(e.target.value) }))} + value={(formData as NetworkPerformanceFormData).testDuration || 10} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, testDuration: parseInt(e.target.value) } as NetworkPerformanceFormData))} min="1" max="3600" /> @@ -315,16 +362,16 @@ export default function FormTypeDrawer({ setFormData(prev => ({ ...prev, phoneNumber: e.target.value }))} + value={(formData as VoiceCallFormData).phoneNumber || ''} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, phoneNumber: e.target.value } as VoiceCallFormData))} placeholder="例如: 13800138000" />
setFormData(prev => ({ ...prev, callDuration: parseInt(e.target.value) }))} + value={(formData as VoiceCallFormData).callDuration || 30} + onChange={(e) => setFormData((prev: FormData) => ({ ...prev, callDuration: parseInt(e.target.value) } as VoiceCallFormData))} min="5" max="300" /> diff --git a/src/X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx b/src/X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx index 89639b2..2b07f28 100644 --- a/src/X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx +++ b/src/X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx @@ -1,6 +1,5 @@ import { useState, useEffect } from 'react'; import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import ReactFlow, { Node, @@ -10,8 +9,7 @@ import ReactFlow, { Handle, Position, ReactFlowProvider, - useReactFlow, - EdgeMarker + useReactFlow } from 'reactflow'; import { testcaseService, TestCaseFlowDetail } from '@/services/testcaseService'; import { FormType, getFormTypeName } from '@/types/formTypes'; @@ -33,7 +31,6 @@ import { Signal, SignalHigh, SignalLow, - FileText, CheckCircle, XCircle } from 'lucide-react'; @@ -46,7 +43,7 @@ interface TestCaseDetailDrawerProps { // 简化的自定义节点组件 const TestStepNode = ({ data, selected, id }: { data: any; selected?: boolean; id: string }) => { - const [isFormEnabled, setIsFormEnabled] = useState(data.isFormEnabled); + const [isFormEnabled] = useState(data.isFormEnabled); // 从父组件获取全局状态 const { activeFormNodeId, setActiveFormNodeId } = data; diff --git a/src/X1.WebUI/src/config/core/env.config.ts b/src/X1.WebUI/src/config/core/env.config.ts index d656a75..09d0fe3 100644 --- a/src/X1.WebUI/src/config/core/env.config.ts +++ b/src/X1.WebUI/src/config/core/env.config.ts @@ -4,6 +4,7 @@ import { z } from 'zod'; const DEFAULT_CONFIG = { // API配置 - 使用相对路径,通过 nginx 代理 VITE_API_BASE_URL: 'https://localhost:7268/api', + //VITE_API_BASE_URL: '/api', VITE_API_TIMEOUT: '30000', VITE_API_VERSION: 'v1', VITE_API_MAX_RETRIES: '0', diff --git a/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx b/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx index beca3ad..1b24fea 100644 --- a/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx +++ b/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx @@ -21,7 +21,7 @@ export default function ScenarioBindingView() { const [selectedScenario, setSelectedScenario] = useState(null); const [selectedTestCases, setSelectedTestCases] = useState([]); const [testCases, setTestCases] = useState([]); - const [scenarios, setScenarios] = useState([]); + const [, setScenarios] = useState([]); const [scenarioCategories, setScenarioCategories] = useState({}); const [loading, setLoading] = useState(false); const [loadingScenarios, setLoadingScenarios] = useState(false); diff --git a/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioCategoryTree.tsx b/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioCategoryTree.tsx index 6009816..5f7fa0e 100644 --- a/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioCategoryTree.tsx +++ b/src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioCategoryTree.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; import { ChevronRight, ChevronDown } from 'lucide-react'; interface Scenario { diff --git a/src/X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx b/src/X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx index 4574d31..fafb044 100644 --- a/src/X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx +++ b/src/X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx @@ -47,13 +47,11 @@ import NetworkPerformanceDrawer from '@/components/testcases/NetworkPerformanceD import VoiceCallDrawer from '@/components/testcases/VoiceCallDrawer'; import { FormData, - FormType, SimpleFormData, DeviceRegistrationData, NetworkConnectivityData, NetworkPerformanceData, - VoiceCallData, - getFormTypeName + VoiceCallData } from '@/types/formTypes'; import { createFormData } from '@/utils/formDataUtils'; diff --git a/src/X1.WebUI/src/pages/testcases/TestCasesListView.tsx b/src/X1.WebUI/src/pages/testcases/TestCasesListView.tsx index ee44a80..696d201 100644 --- a/src/X1.WebUI/src/pages/testcases/TestCasesListView.tsx +++ b/src/X1.WebUI/src/pages/testcases/TestCasesListView.tsx @@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; -import { Plus, Search, Trash2, Eye } from 'lucide-react'; + import { useNavigate } from 'react-router-dom'; import { testcaseService, TestCaseFlow } from '@/services/testcaseService'; import TestCaseDetailDrawer from '@/components/testcases/TestCaseDetailDrawer'; diff --git a/src/X1.WebUI/src/pages/teststeps/TestStepDrawer.tsx b/src/X1.WebUI/src/pages/teststeps/TestStepDrawer.tsx index 8912bef..9784198 100644 --- a/src/X1.WebUI/src/pages/teststeps/TestStepDrawer.tsx +++ b/src/X1.WebUI/src/pages/teststeps/TestStepDrawer.tsx @@ -41,7 +41,7 @@ export default function TestStepDrawer({ isSubmitting = false, existingSteps = [], formTypes, - stepTypes, + stepTypes: _stepTypes, stepMappings, loadingFormTypes }: TestStepDrawerProps) { diff --git a/src/X1.WebUI/src/utils/formDataUtils.ts b/src/X1.WebUI/src/utils/formDataUtils.ts index 70b60f2..80b4d08 100644 --- a/src/X1.WebUI/src/utils/formDataUtils.ts +++ b/src/X1.WebUI/src/utils/formDataUtils.ts @@ -2,8 +2,7 @@ import { DeviceRegistrationData, NetworkConnectivityData, NetworkPerformanceData, - VoiceCallData, - SimpleFormData + VoiceCallData } from '@/types/formTypes'; /**