Browse Source

解决严谨模式警告

release/web-ui-v1.0.0
root 4 months ago
parent
commit
5a1f9a43d8
  1. 63
      src/X1.WebUI/modify.md
  2. 127
      src/X1.WebUI/src/components/testcases/FormTypeDrawer.tsx
  3. 7
      src/X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx
  4. 1
      src/X1.WebUI/src/config/core/env.config.ts
  5. 2
      src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx
  6. 2
      src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioCategoryTree.tsx
  7. 4
      src/X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx
  8. 2
      src/X1.WebUI/src/pages/testcases/TestCasesListView.tsx
  9. 2
      src/X1.WebUI/src/pages/teststeps/TestStepDrawer.tsx
  10. 3
      src/X1.WebUI/src/utils/formDataUtils.ts

63
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` 无错误输出
- ✅ **所有表单类型正常工作** - 设备注册、网络连通性、网络性能、语音通话表单
- ✅ **代码类型安全性显著提升** - 完整的类型定义和检查
- ✅ **构建成功** - 项目可以正常构建和部署

127
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<any>({});
const [formData, setFormData] = useState<FormData>({ 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({
<div className="flex items-center space-x-2">
<Checkbox
id="isDualSim"
checked={formData.isDualSim || false}
checked={(formData as DeviceRegistrationFormData).isDualSim || false}
onCheckedChange={(checked) => {
setFormData(prev => ({
setFormData((prev: FormData) => ({
...prev,
isDualSim: checked,
...(checked ? {} : {
@ -149,7 +196,7 @@ export default function FormTypeDrawer({
sim2CellId: '',
sim2RegistrationWaitTime: 5000
})
}));
} as DeviceRegistrationFormData));
}}
/>
<Label htmlFor="isDualSim"></Label>
@ -164,8 +211,8 @@ export default function FormTypeDrawer({
<Label htmlFor="sim1Plmn">PLMN *</Label>
<Input
id="sim1Plmn"
value={formData.sim1Plmn || ''}
onChange={(e) => 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"
/>
</div>
@ -173,8 +220,8 @@ export default function FormTypeDrawer({
<Label htmlFor="sim1CellId">ID</Label>
<Input
id="sim1CellId"
value={formData.sim1CellId || ''}
onChange={(e) => 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"
/>
</div>
@ -183,8 +230,8 @@ export default function FormTypeDrawer({
<Input
id="sim1RegistrationWaitTime"
type="number"
value={formData.sim1RegistrationWaitTime || 5000}
onChange={(e) => 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({
</CardContent>
</Card>
{formData.isDualSim && (
{(formData as DeviceRegistrationFormData).isDualSim && (
<Card>
<CardHeader>
<CardTitle className="text-sm">SIM卡2配置</CardTitle>
@ -202,8 +249,8 @@ export default function FormTypeDrawer({
<Label htmlFor="sim2Plmn">PLMN *</Label>
<Input
id="sim2Plmn"
value={formData.sim2Plmn || ''}
onChange={(e) => 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"
/>
</div>
@ -211,8 +258,8 @@ export default function FormTypeDrawer({
<Label htmlFor="sim2CellId">ID</Label>
<Input
id="sim2CellId"
value={formData.sim2CellId || ''}
onChange={(e) => 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"
/>
</div>
@ -221,8 +268,8 @@ export default function FormTypeDrawer({
<Input
id="sim2RegistrationWaitTime"
type="number"
value={formData.sim2RegistrationWaitTime || 5000}
onChange={(e) => 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({
<Label htmlFor="targetHost"> *</Label>
<Input
id="targetHost"
value={formData.targetHost || ''}
onChange={(e) => 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"
/>
</div>
@ -250,8 +297,8 @@ export default function FormTypeDrawer({
<Input
id="pingCount"
type="number"
value={formData.pingCount || 4}
onChange={(e) => 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({
<Input
id="timeout"
type="number"
value={formData.timeout || 5000}
onChange={(e) => 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({
<Label htmlFor="serverHost"> *</Label>
<Input
id="serverHost"
value={formData.serverHost || ''}
onChange={(e) => 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"
/>
</div>
@ -288,8 +335,8 @@ export default function FormTypeDrawer({
<Input
id="serverPort"
type="number"
value={formData.serverPort || 5201}
onChange={(e) => 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({
<Input
id="testDuration"
type="number"
value={formData.testDuration || 10}
onChange={(e) => 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({
<Label htmlFor="phoneNumber"> *</Label>
<Input
id="phoneNumber"
value={formData.phoneNumber || ''}
onChange={(e) => 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"
/>
</div>
<div>
<Label htmlFor="callType"></Label>
<Select
value={formData.callType || 'mo'}
onValueChange={(value) => setFormData(prev => ({ ...prev, callType: value }))}
value={(formData as VoiceCallFormData).callType || 'mo'}
onValueChange={(value) => setFormData((prev: FormData) => ({ ...prev, callType: value } as VoiceCallFormData))}
>
<SelectTrigger>
<SelectValue />
@ -340,8 +387,8 @@ export default function FormTypeDrawer({
<Input
id="callDuration"
type="number"
value={formData.callDuration || 30}
onChange={(e) => 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"
/>

7
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;

1
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',

2
src/X1.WebUI/src/pages/scenarios/scenario-binding/ScenarioBindingView.tsx

@ -21,7 +21,7 @@ export default function ScenarioBindingView() {
const [selectedScenario, setSelectedScenario] = useState<Scenario | null>(null);
const [selectedTestCases, setSelectedTestCases] = useState<string[]>([]);
const [testCases, setTestCases] = useState<TestCaseFlow[]>([]);
const [scenarios, setScenarios] = useState<TestScenario[]>([]);
const [, setScenarios] = useState<TestScenario[]>([]);
const [scenarioCategories, setScenarioCategories] = useState<CategoryData>({});
const [loading, setLoading] = useState(false);
const [loadingScenarios, setLoadingScenarios] = useState(false);

2
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 {

4
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';

2
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';

2
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) {

3
src/X1.WebUI/src/utils/formDataUtils.ts

@ -2,8 +2,7 @@ import {
DeviceRegistrationData,
NetworkConnectivityData,
NetworkPerformanceData,
VoiceCallData,
SimpleFormData
VoiceCallData
} from '@/types/formTypes';
/**

Loading…
Cancel
Save