新增grade(成绩统计)页面
This commit is contained in:
@@ -27,6 +27,11 @@
|
|||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
"static/chunks/main.js",
|
"static/chunks/main.js",
|
||||||
"static/chunks/pages/_error.js"
|
"static/chunks/pages/_error.js"
|
||||||
|
],
|
||||||
|
"/grade": [
|
||||||
|
"static/chunks/webpack.js",
|
||||||
|
"static/chunks/main.js",
|
||||||
|
"static/chunks/pages/grade.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ampFirstPages": []
|
"ampFirstPages": []
|
||||||
|
|||||||
BIN
.next/cache/webpack/client-development/0.pack.gz
vendored
BIN
.next/cache/webpack/client-development/0.pack.gz
vendored
Binary file not shown.
BIN
.next/cache/webpack/client-development/1.pack.gz
vendored
BIN
.next/cache/webpack/client-development/1.pack.gz
vendored
Binary file not shown.
BIN
.next/cache/webpack/client-development/index.pack.gz
vendored
BIN
.next/cache/webpack/client-development/index.pack.gz
vendored
Binary file not shown.
Binary file not shown.
BIN
.next/cache/webpack/server-development/0.pack.gz
vendored
BIN
.next/cache/webpack/server-development/0.pack.gz
vendored
Binary file not shown.
BIN
.next/cache/webpack/server-development/index.pack.gz
vendored
BIN
.next/cache/webpack/server-development/index.pack.gz
vendored
Binary file not shown.
@@ -4,5 +4,11 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"static/chunks/_pages-dir-browser_node_modules_jsplumb_dist_js_jsplumb_js.js"
|
"static/chunks/_pages-dir-browser_node_modules_jsplumb_dist_js_jsplumb_js.js"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"pages/grade.js -> xlsx": {
|
||||||
|
"id": "pages/grade.js -> xlsx",
|
||||||
|
"files": [
|
||||||
|
"static/chunks/_pages-dir-browser_node_modules_xlsx_xlsx_mjs.js"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,11 @@ globalThis.__BUILD_MANIFEST = {
|
|||||||
"static/chunks/webpack.js",
|
"static/chunks/webpack.js",
|
||||||
"static/chunks/main.js",
|
"static/chunks/main.js",
|
||||||
"static/chunks/pages/_error.js"
|
"static/chunks/pages/_error.js"
|
||||||
|
],
|
||||||
|
"/grade": [
|
||||||
|
"static/chunks/webpack.js",
|
||||||
|
"static/chunks/main.js",
|
||||||
|
"static/chunks/pages/grade.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ampFirstPages": []
|
"ampFirstPages": []
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
self.__REACT_LOADABLE_MANIFEST="{\"components/JsPlumbInit.js -> jsplumb\":{\"id\":\"components/JsPlumbInit.js -> jsplumb\",\"files\":[\"static/chunks/_pages-dir-browser_node_modules_jsplumb_dist_js_jsplumb_js.js\"]}}"
|
self.__REACT_LOADABLE_MANIFEST="{\"components/JsPlumbInit.js -> jsplumb\":{\"id\":\"components/JsPlumbInit.js -> jsplumb\",\"files\":[\"static/chunks/_pages-dir-browser_node_modules_jsplumb_dist_js_jsplumb_js.js\"]},\"pages/grade.js -> xlsx\":{\"id\":\"pages/grade.js -> xlsx\",\"files\":[\"static/chunks/_pages-dir-browser_node_modules_xlsx_xlsx_mjs.js\"]}}"
|
||||||
@@ -2,5 +2,6 @@
|
|||||||
"/_app": "pages/_app.js",
|
"/_app": "pages/_app.js",
|
||||||
"/_error": "pages/_error.js",
|
"/_error": "pages/_error.js",
|
||||||
"/_document": "pages/_document.js",
|
"/_document": "pages/_document.js",
|
||||||
"/": "pages/index.js"
|
"/": "pages/index.js",
|
||||||
|
"/grade": "pages/grade.js"
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
44
.next/trace
44
.next/trace
File diff suppressed because one or more lines are too long
BIN
public/Industry.png
Normal file
BIN
public/Industry.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 109 KiB |
@@ -338,7 +338,7 @@ export default function Cursors() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setToneStatus(null);
|
setToneStatus(null);
|
||||||
}, 1200);
|
}, 1200);
|
||||||
console.log(isConnected);
|
// console.log(isConnected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import useDeviceStore from '@/store/deviceStore';
|
import useDeviceStore from '@/store/deviceStore';
|
||||||
|
import useDisplayStore from '@/store/displayStore';
|
||||||
|
import { API_URLS } from '@/config/api';
|
||||||
|
|
||||||
const ResultTable = () => {
|
const ResultTable = () => {
|
||||||
const [records, setRecords] = useState([
|
const [records, setRecords] = useState([
|
||||||
@@ -92,8 +94,68 @@ const ResultTable = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const { getCurrentProject,getCurrentOperator, getCurrentTestConfig} = useDisplayStore();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const handleSubmit = () => {
|
const { faultScenarios, seatNumber, seatOrg,setTotalToastMessage } = useDeviceStore();
|
||||||
|
|
||||||
|
|
||||||
|
// 获取测试结果统计
|
||||||
|
const getTestResults = () => {
|
||||||
|
const currentProject = getCurrentProject();
|
||||||
|
if (!currentProject?.testResults) return { passCount: 0, failCount: 0 };
|
||||||
|
|
||||||
|
const passCount = currentProject?.testResults.filter(result => {
|
||||||
|
const copperStatus = result.CopperResultStatus;
|
||||||
|
const cfpStatus = result.CFPResultStatus;
|
||||||
|
const ofpStatus = result.ofpResultStatus;
|
||||||
|
|
||||||
|
if (copperStatus) {
|
||||||
|
return copperStatus === 'pass';
|
||||||
|
} else if (cfpStatus) {
|
||||||
|
return cfpStatus === 'pass';
|
||||||
|
} else if (ofpStatus) {
|
||||||
|
return ofpStatus === 'pass';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
const failCount = currentProject?.testResults.filter(result => {
|
||||||
|
const copperStatus = result.CopperResultStatus;
|
||||||
|
const cfpStatus = result.CFPResultStatus;
|
||||||
|
const ofpStatus = result.ofpResultStatus;
|
||||||
|
|
||||||
|
if (copperStatus) {
|
||||||
|
return copperStatus === 'fail';
|
||||||
|
} else if (cfpStatus) {
|
||||||
|
return cfpStatus === 'fail';
|
||||||
|
} else if (ofpStatus) {
|
||||||
|
return ofpStatus === 'fail';
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
|
||||||
|
return { passCount, failCount };
|
||||||
|
};
|
||||||
|
// 获取基准状态
|
||||||
|
const getRefStatus = () => {
|
||||||
|
const currentConfig = getCurrentTestConfig();
|
||||||
|
const moduleType = currentConfig?.moduleType;
|
||||||
|
if (!moduleType) return false;
|
||||||
|
|
||||||
|
const { ref } = useDisplayStore.getState();
|
||||||
|
if (moduleType === '8000') return ref.copper?.status || false;
|
||||||
|
if (moduleType === 'cfp') return ref.cfp?.status || false;
|
||||||
|
if (moduleType === 'ofp') return ref.ofp?.status || false;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentProject = getCurrentProject();
|
||||||
|
const currentOperator = getCurrentOperator();
|
||||||
|
const currentConfig = getCurrentTestConfig();
|
||||||
|
const refStatus = getRefStatus();
|
||||||
|
const { passCount, failCount } = getTestResults();
|
||||||
|
const handleSubmit = async () => {
|
||||||
// 验证表单
|
// 验证表单
|
||||||
const isValid = records.every(record => {
|
const isValid = records.every(record => {
|
||||||
if (!record.linkName.trim()) return false;
|
if (!record.linkName.trim()) return false;
|
||||||
@@ -112,9 +174,52 @@ const ResultTable = () => {
|
|||||||
|
|
||||||
// 直接使用当前的 records 更新 store
|
// 直接使用当前的 records 更新 store
|
||||||
useDeviceStore.getState().updateReports(records);
|
useDeviceStore.getState().updateReports(records);
|
||||||
alert('记录提交成功!');
|
try {
|
||||||
|
const statisticsData = {
|
||||||
|
userId: seatNumber,
|
||||||
|
org: seatOrg,
|
||||||
|
scenario: faultScenarios,
|
||||||
|
project: currentProject?.name || '',
|
||||||
|
operator: currentOperator?.name || '',
|
||||||
|
testLimit: currentConfig?.params?.limitValue || '',
|
||||||
|
refStatus,
|
||||||
|
testResultsCount: { passCount, failCount },
|
||||||
|
projects: useDisplayStore.getState().projects,
|
||||||
|
selectedIndexes:useDisplayStore.getState().selectedIndexes,
|
||||||
|
reports: records,
|
||||||
|
};
|
||||||
|
if (['Office', 'Industry', 'DataCenter'].includes(faultScenarios)) {
|
||||||
|
const response = await fetch(API_URLS.TEACHING.DATA, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
scenario: faultScenarios,
|
||||||
|
fingerprint: seatNumber,
|
||||||
|
data: statisticsData,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
try {
|
||||||
|
const err = await response.json();
|
||||||
|
console.error('数据发送失败:', err);
|
||||||
|
} catch {
|
||||||
|
console.error('数据发送失败');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTotalToastMessage('记录提交成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('数据发送异常:', e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-[#1E293B] rounded-lg p-6 text-white">
|
<div className="bg-[#1E293B] rounded-lg p-6 text-white">
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
|
|||||||
@@ -136,8 +136,8 @@ export default function Result() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newResults = testResults.map(result => {
|
const newResults = testResults.map(result => {
|
||||||
console.log(testResults);
|
// console.log(testResults);
|
||||||
console.log(result);
|
// console.log(result);
|
||||||
|
|
||||||
if (result.name === selectedResults[0]) {
|
if (result.name === selectedResults[0]) {
|
||||||
// 处理CFP模块类型的特殊重命名逻辑
|
// 处理CFP模块类型的特殊重命名逻辑
|
||||||
@@ -149,7 +149,7 @@ export default function Result() {
|
|||||||
if (oldName === result.inputname) {
|
if (oldName === result.inputname) {
|
||||||
// 查找关联结果:inputname相同但name不同的结果
|
// 查找关联结果:inputname相同但name不同的结果
|
||||||
const relatedResult = testResults.find(r => r.inputname === result.inputname && r.name !== result.name);
|
const relatedResult = testResults.find(r => r.inputname === result.inputname && r.name !== result.name);
|
||||||
console.log("找到的关联结果:", relatedResult);
|
// console.log("找到的关联结果:", relatedResult);
|
||||||
// 如果是当前选中的结果,更新name和inputname
|
// 如果是当前选中的结果,更新name和inputname
|
||||||
if (result.name === selectedResults[0]) {
|
if (result.name === selectedResults[0]) {
|
||||||
// 更新选中结果的name和inputname
|
// 更新选中结果的name和inputname
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export default function Testing() {
|
|||||||
wireOrder === 'Ethernet Two-Pair' ||
|
wireOrder === 'Ethernet Two-Pair' ||
|
||||||
wireOrder === 'M12-D Two-Pair') {
|
wireOrder === 'M12-D Two-Pair') {
|
||||||
CopperWiremapResultStatus = 'pass';
|
CopperWiremapResultStatus = 'pass';
|
||||||
console.log(CopperWiremapResultStatus);
|
// console.log(CopperWiremapResultStatus);
|
||||||
}
|
}
|
||||||
} else if (CopperWiremapStatus === 'pass-2pair') {
|
} else if (CopperWiremapStatus === 'pass-2pair') {
|
||||||
if (wireOrder === 'Ethernet Two-Pair' ||
|
if (wireOrder === 'Ethernet Two-Pair' ||
|
||||||
@@ -305,7 +305,7 @@ export default function Testing() {
|
|||||||
for (const pair of loopPairs) {
|
for (const pair of loopPairs) {
|
||||||
if (data.performance.OHM.LOOP[pair] > limitdata.LOOP) {
|
if (data.performance.OHM.LOOP[pair] > limitdata.LOOP) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("电阻fail")
|
// console.log("电阻fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ export default function Testing() {
|
|||||||
for (const pair of pairUblPairs) {
|
for (const pair of pairUblPairs) {
|
||||||
if (Math.abs(data.performance.OHM.PAIRUBL[pair]) > limitdata.PAIRUBL) {
|
if (Math.abs(data.performance.OHM.PAIRUBL[pair]) > limitdata.PAIRUBL) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("UBL fail")
|
// console.log("UBL fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,7 @@ export default function Testing() {
|
|||||||
for (const pair of p2pUblPairs) {
|
for (const pair of p2pUblPairs) {
|
||||||
if (Math.abs(data.performance.OHM.P2PUBL[pair]) > limitdata.P2PUBL) {
|
if (Math.abs(data.performance.OHM.P2PUBL[pair]) > limitdata.P2PUBL) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("P2P fail")
|
// console.log("P2P fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export default function Tools() {
|
|||||||
const handleVfl = () => {
|
const handleVfl = () => {
|
||||||
fetchConnectionMap();
|
fetchConnectionMap();
|
||||||
if (!mainVFLEnd) return;
|
if (!mainVFLEnd) return;
|
||||||
console.log(connectionStatus?.mainPaths?.['main-vfl']);
|
// console.log(connectionStatus?.mainPaths?.['main-vfl']);
|
||||||
|
|
||||||
// 在connectionMap中查找与mainVFLEnd匹配的连接
|
// 在connectionMap中查找与mainVFLEnd匹配的连接
|
||||||
let connectedPort = null;
|
let connectedPort = null;
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ export default function CopperPerformance( ) {
|
|||||||
const renderFooter = () => {
|
const renderFooter = () => {
|
||||||
const showHDTDR = estmodel === 'general' && testResult?.CopperResultStatus === 'fail' && view === 'DRAW' && curtitle === '回波损耗';
|
const showHDTDR = estmodel === 'general' && testResult?.CopperResultStatus === 'fail' && view === 'DRAW' && curtitle === '回波损耗';
|
||||||
const showHDTDX = estmodel === 'general' && testResult?.CopperResultStatus === 'fail' && view === 'DRAW' && curtitle === 'NEXT';
|
const showHDTDX = estmodel === 'general' && testResult?.CopperResultStatus === 'fail' && view === 'DRAW' && curtitle === 'NEXT';
|
||||||
console.log(estmodel, CopperResultStatus, view, curtitle, showHDTDR, showHDTDX);
|
// console.log(estmodel, CopperResultStatus, view, curtitle, showHDTDR, showHDTDX);
|
||||||
return (
|
return (
|
||||||
<div className="h-[60px] bg-[#132843] flex items-center justify-end px-8 gap-4">
|
<div className="h-[60px] bg-[#132843] flex items-center justify-end px-8 gap-4">
|
||||||
{showHDTDR && (
|
{showHDTDR && (
|
||||||
|
|||||||
@@ -136,8 +136,8 @@ export default function Result() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newResults = testResults.map(result => {
|
const newResults = testResults.map(result => {
|
||||||
console.log(testResults);
|
// console.log(testResults);
|
||||||
console.log(result);
|
// console.log(result);
|
||||||
|
|
||||||
if (result.name === selectedResults[0]) {
|
if (result.name === selectedResults[0]) {
|
||||||
// 处理CFP模块类型的特殊重命名逻辑
|
// 处理CFP模块类型的特殊重命名逻辑
|
||||||
@@ -149,7 +149,7 @@ export default function Result() {
|
|||||||
if (oldName === result.inputname) {
|
if (oldName === result.inputname) {
|
||||||
// 查找关联结果:inputname相同但name不同的结果
|
// 查找关联结果:inputname相同但name不同的结果
|
||||||
const relatedResult = testResults.find(r => r.inputname === result.inputname && r.name !== result.name);
|
const relatedResult = testResults.find(r => r.inputname === result.inputname && r.name !== result.name);
|
||||||
console.log("找到的关联结果:", relatedResult);
|
// console.log("找到的关联结果:", relatedResult);
|
||||||
// 如果是当前选中的结果,更新name和inputname
|
// 如果是当前选中的结果,更新name和inputname
|
||||||
if (result.name === selectedResults[0]) {
|
if (result.name === selectedResults[0]) {
|
||||||
// 更新选中结果的name和inputname
|
// 更新选中结果的name和inputname
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export default function Testing() {
|
|||||||
wireOrder === 'Ethernet Two-Pair' ||
|
wireOrder === 'Ethernet Two-Pair' ||
|
||||||
wireOrder === 'M12-D Two-Pair') {
|
wireOrder === 'M12-D Two-Pair') {
|
||||||
CopperWiremapResultStatus = 'pass';
|
CopperWiremapResultStatus = 'pass';
|
||||||
console.log(CopperWiremapResultStatus);
|
// console.log(CopperWiremapResultStatus);
|
||||||
}
|
}
|
||||||
} else if (CopperWiremapStatus === 'pass-2pair') {
|
} else if (CopperWiremapStatus === 'pass-2pair') {
|
||||||
if (wireOrder === 'Ethernet Two-Pair' ||
|
if (wireOrder === 'Ethernet Two-Pair' ||
|
||||||
@@ -305,7 +305,7 @@ export default function Testing() {
|
|||||||
for (const pair of loopPairs) {
|
for (const pair of loopPairs) {
|
||||||
if (data.performance.OHM.LOOP[pair] > limitdata.LOOP) {
|
if (data.performance.OHM.LOOP[pair] > limitdata.LOOP) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("电阻fail")
|
// console.log("电阻fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ export default function Testing() {
|
|||||||
for (const pair of pairUblPairs) {
|
for (const pair of pairUblPairs) {
|
||||||
if (Math.abs(data.performance.OHM.PAIRUBL[pair]) > limitdata.PAIRUBL) {
|
if (Math.abs(data.performance.OHM.PAIRUBL[pair]) > limitdata.PAIRUBL) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("UBL fail")
|
// console.log("UBL fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,7 @@ export default function Testing() {
|
|||||||
for (const pair of p2pUblPairs) {
|
for (const pair of p2pUblPairs) {
|
||||||
if (Math.abs(data.performance.OHM.P2PUBL[pair]) > limitdata.P2PUBL) {
|
if (Math.abs(data.performance.OHM.P2PUBL[pair]) > limitdata.P2PUBL) {
|
||||||
hasNegativeMargin = true;
|
hasNegativeMargin = true;
|
||||||
console.log("P2P fail")
|
// console.log("P2P fail")
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export default function Tools() {
|
|||||||
const handleVfl = () => {
|
const handleVfl = () => {
|
||||||
fetchConnectionMap();
|
fetchConnectionMap();
|
||||||
if (!mainVFLEnd) return;
|
if (!mainVFLEnd) return;
|
||||||
console.log(connectionStatus?.mainPaths?.['main-vfl']);
|
// console.log(connectionStatus?.mainPaths?.['main-vfl']);
|
||||||
|
|
||||||
// 在connectionMap中查找与mainVFLEnd匹配的连接
|
// 在connectionMap中查找与mainVFLEnd匹配的连接
|
||||||
let connectedPort = null;
|
let connectedPort = null;
|
||||||
|
|||||||
@@ -83,9 +83,14 @@ export default function IndustryTask() {
|
|||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">测试准备:</strong> 使用<span className="font-medium text-yellow-300">DSX 网络认证分析仪</span>,确保测试参数符合工业环境要求。
|
<strong className="text-gray-100">测试准备:</strong> 使用<span className="font-medium text-yellow-300">DSX 网络认证分析仪</span>,确保测试参数符合工业环境要求。
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-gray-100">认证测试:</strong> 执行<span className="font-medium text-yellow-300">GB/T </span>标准测试,重点关注<span className="font-medium text-yellow-300">串扰(Crosstalk)</span>。
|
||||||
|
</li>
|
||||||
|
{/*
|
||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">认证测试:</strong> 执行<span className="font-medium text-yellow-300">TIA 1005 </span>标准测试,重点关注<span className="font-medium text-yellow-300">串扰(Crosstalk)</span>和<span className="font-medium text-yellow-300">电磁干扰(EMI)抗性,至少需要保证E2等级</span>。
|
<strong className="text-gray-100">认证测试:</strong> 执行<span className="font-medium text-yellow-300">TIA 1005 </span>标准测试,重点关注<span className="font-medium text-yellow-300">串扰(Crosstalk)</span>和<span className="font-medium text-yellow-300">电磁干扰(EMI)抗性,至少需要保证E2等级</span>。
|
||||||
</li>
|
</li>
|
||||||
|
*/}
|
||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">数据分析:</strong> 评估测试结果,确认链路状态为<span className="font-semibold text-green-400">合格(PASS)</span>或<span className="font-semibold text-red-400">不合格(FAIL*)</span>。
|
<strong className="text-gray-100">数据分析:</strong> 评估测试结果,确认链路状态为<span className="font-semibold text-green-400">合格(PASS)</span>或<span className="font-semibold text-red-400">不合格(FAIL*)</span>。
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default function OfficeTask() {
|
|||||||
<p className="text-sm font-semibold text-cyan-400 uppercase tracking-wider">新任务单</p>
|
<p className="text-sm font-semibold text-cyan-400 uppercase tracking-wider">新任务单</p>
|
||||||
<h1 className="text-2xl md:text-3xl font-bold text-gray-100 mt-1">任务要求:网络链路认证</h1>
|
<h1 className="text-2xl md:text-3xl font-bold text-gray-100 mt-1">任务要求:网络链路认证</h1>
|
||||||
<p className="text-xs text-gray-400">任务编号: SIM-TRN-NTW-005 </p>
|
<p className="text-xs text-gray-400">任务编号: SIM-TRN-NTW-005 </p>
|
||||||
<p className="text-xs text-gray-400">地点: Innovate Solutions 公司 - 8 层西翼</p>
|
<p className="text-xs text-gray-400">地点: Joja 公司 - 8 层西翼</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 情况说明 (背景) */}
|
{/* 情况说明 (背景) */}
|
||||||
@@ -66,13 +66,13 @@ export default function OfficeTask() {
|
|||||||
<h2 className="text-xl font-semibold text-cyan-300">情况说明</h2>
|
<h2 className="text-xl font-semibold text-cyan-300">情况说明</h2>
|
||||||
|
|
||||||
<p className="text-gray-300 leading-relaxed">
|
<p className="text-gray-300 leading-relaxed">
|
||||||
Innovate Solutions 公司刚刚完成了对其 8 层西翼办公区<span className="font-medium text-yellow-300">(Room1 至 Room4)</span> 的关键改造。新的网络基础设施已部署完毕,将这些房间连接至楼层弱电间 <span className="font-medium text-yellow-300">机柜 1 (Rack1)</span>。
|
Joja 公司刚刚完成了对其 8 层西翼办公区<span className="font-medium text-yellow-300">(Room1 至 Room4)</span> 的关键改造。新的网络基础设施已部署完毕,将这些房间连接至楼层弱电间 <span className="font-medium text-yellow-300">机柜 1 (Rack1)</span>。
|
||||||
</p>
|
</p>
|
||||||
<div className=" h-100 relative">
|
<div className=" h-100 relative">
|
||||||
<Image src="/Office.png" alt="office" fill className="object-contain"/>
|
<Image src="/Office.png" alt="office" fill className="object-contain"/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-gray-300 leading-relaxed">
|
<p className="text-gray-300 leading-relaxed">
|
||||||
在这些重要链路正式启用前,集团工程部要求进行 <span className="font-semibold text-red-400">全面的物理层认证测试</span>。你的测试部署对于确保每条连接都符合严格的 <span className="font-medium text-yellow-300">TIA信道链路</span>标准。我们不能容忍任何故障链路。
|
在这些重要链路正式启用前,集团工程部要求进行 <span className="font-semibold text-red-400">全面的物理层认证测试</span>。你的测试部署对于确保每条连接都符合严格的 <span className="font-medium text-yellow-300">GB/T信道链路</span>标准。我们不能容忍任何故障链路。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -86,6 +86,9 @@ export default function OfficeTask() {
|
|||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">部署测试设备:</strong> 使用模拟的 <span className="font-medium text-yellow-300">DSX 系列线缆认证分析仪</span>。为每次测试准确配置参数。
|
<strong className="text-gray-100">部署测试设备:</strong> 使用模拟的 <span className="font-medium text-yellow-300">DSX 系列线缆认证分析仪</span>。为每次测试准确配置参数。
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-gray-100">创建测试项目:</strong> 在测试仪表中正确的创建 <span className="font-medium text-yellow-300">Joja-8F</span> 项目。
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">执行认证测试:</strong> 对所有信道链路执行 <span className="font-medium text-yellow-300">信道</span> 测试,遵循 <span className="font-medium text-yellow-300">T568B</span> 线序标准及 <span className="font-medium text-yellow-300">Cat 6 屏蔽 (F/UTP)</span> 线缆类型。
|
<strong className="text-gray-100">执行认证测试:</strong> 对所有信道链路执行 <span className="font-medium text-yellow-300">信道</span> 测试,遵循 <span className="font-medium text-yellow-300">T568B</span> 线序标准及 <span className="font-medium text-yellow-300">Cat 6 屏蔽 (F/UTP)</span> 线缆类型。
|
||||||
</li>
|
</li>
|
||||||
@@ -99,7 +102,7 @@ export default function OfficeTask() {
|
|||||||
<strong className="text-gray-100">诊断故障点:</strong> 对于任何失败的链路 (<span className='text-red-400 font-bold'>FAIL*</span>),使用测试仪的诊断功能,来精确定位故障类型和大致位置。
|
<strong className="text-gray-100">诊断故障点:</strong> 对于任何失败的链路 (<span className='text-red-400 font-bold'>FAIL*</span>),使用测试仪的诊断功能,来精确定位故障类型和大致位置。
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong className="text-gray-100">记录与报告:</strong> 使用指定格式安全保存每个测试结果:<code className="bg-gray-700 px-1.5 py-0.5 rounded text-xs text-yellow-300">[主机连接端口]-[远端连接端口]</code> (例如:<code className="bg-gray-700 px-1.5 py-0.5 rounded text-xs text-yellow-300">Room1-TO-1-Rack1-1A-1</code>)。准备一份总结报告以供汇报。
|
<strong className="text-gray-100">记录与报告:</strong> 使用指定格式安全保存每个测试结果:<code className="bg-gray-700 px-1.5 py-0.5 rounded text-xs text-yellow-300">[主机连接端口]-[远端连接端口]</code> (例如:<code className="bg-gray-700 px-1.5 py-0.5 rounded text-xs text-yellow-300">Room1-TO-1-Rack1-1A-1</code>)。填写至测试总结报告中(点击屏幕右侧箭头唤出)。
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ const API_URLS = {
|
|||||||
START: `${BASE_URL}/dsxapi/api/competition/start`,
|
START: `${BASE_URL}/dsxapi/api/competition/start`,
|
||||||
END: `${BASE_URL}/dsxapi/api/competition/end`,
|
END: `${BASE_URL}/dsxapi/api/competition/end`,
|
||||||
},
|
},
|
||||||
|
// 教学相关
|
||||||
|
TEACHING: {
|
||||||
|
DATA: `${BASE_URL}/dsxapi/api/teaching/data`,
|
||||||
|
},
|
||||||
// 管理员鉴权相关
|
// 管理员鉴权相关
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
VERIFY: `${BASE_URL}/verify-admin`,
|
VERIFY: `${BASE_URL}/verify-admin`,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Office from '@/components/scene/Office';
|
|||||||
import Industry from '@/components/scene/Industry';
|
import Industry from '@/components/scene/Industry';
|
||||||
import WorldSkill from '@/components/scene/WorldSkill';
|
import WorldSkill from '@/components/scene/WorldSkill';
|
||||||
import CompetitionPage from './competition';
|
import CompetitionPage from './competition';
|
||||||
|
import Grade from './grade';
|
||||||
import { API_URLS } from '@/config/api';
|
import { API_URLS } from '@/config/api';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ export default function AdminPage() {
|
|||||||
const [availableScenes, setAvailableScenes] = useState(['Office', 'Industry', 'WorldSkill']);
|
const [availableScenes, setAvailableScenes] = useState(['Office', 'Industry', 'WorldSkill']);
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [showhistoryModal, setShowhistoryModal] = useState(false);
|
const [showhistoryModal, setShowhistoryModal] = useState(false);
|
||||||
|
const [showgradeModal, setShowgradeModal] = useState(false);
|
||||||
const [uuid, setUuid] = useState(null);
|
const [uuid, setUuid] = useState(null);
|
||||||
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
|
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
|
||||||
const [confirmDialogMessage, setConfirmDialogMessage] = useState('');
|
const [confirmDialogMessage, setConfirmDialogMessage] = useState('');
|
||||||
@@ -420,6 +422,25 @@ export default function AdminPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 成绩模态框 */}
|
||||||
|
{showgradeModal && (
|
||||||
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
<div className="w-full h-full">
|
||||||
|
<div className='absolute top-26 right-12 z-50' >
|
||||||
|
<button
|
||||||
|
onClick={async () => {
|
||||||
|
setShowgradeModal(false)
|
||||||
|
}}
|
||||||
|
className="cursor-pointer bg-[#0ff]/20 hover:bg-[#0ff]/30 text-[#0ff] px-4 py-2 rounded transition-colors"
|
||||||
|
>
|
||||||
|
返回控制页面
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Grade isComponent={false}/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="max-w-8xl mx-auto">
|
<div className="max-w-8xl mx-auto">
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
@@ -469,6 +490,16 @@ export default function AdminPage() {
|
|||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* <button
|
||||||
|
onClick={async () => {
|
||||||
|
setShowgradeModal(true)
|
||||||
|
}}
|
||||||
|
className="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors"
|
||||||
|
>
|
||||||
|
过程评价
|
||||||
|
</button> */}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={handleInit}
|
onClick={handleInit}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
|
|||||||
1540
src/pages/grade.js
Normal file
1540
src/pages/grade.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -84,6 +84,8 @@ export default function Home() {
|
|||||||
WorldSkillScenarios,
|
WorldSkillScenarios,
|
||||||
seatNumber,
|
seatNumber,
|
||||||
updateSeatNumber,
|
updateSeatNumber,
|
||||||
|
seatOrg,
|
||||||
|
updateSeatOrg,
|
||||||
seatUUID,
|
seatUUID,
|
||||||
updateSeatUUID,
|
updateSeatUUID,
|
||||||
seatStartTime,
|
seatStartTime,
|
||||||
@@ -145,6 +147,7 @@ useEffect(() => {
|
|||||||
const urlParams = new URLSearchParams(currentUrl.split('?')[1] || '');
|
const urlParams = new URLSearchParams(currentUrl.split('?')[1] || '');
|
||||||
let faultScenariosParam = urlParams.get('faultScenarios') || '';
|
let faultScenariosParam = urlParams.get('faultScenarios') || '';
|
||||||
let estmodelParam = urlParams.get('estmodel') || '';
|
let estmodelParam = urlParams.get('estmodel') || '';
|
||||||
|
let org = urlParams.get('org') || '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
faultScenariosParam = decodeURIComponent(faultScenariosParam);
|
faultScenariosParam = decodeURIComponent(faultScenariosParam);
|
||||||
@@ -163,6 +166,9 @@ useEffect(() => {
|
|||||||
if (estmodelParam) {
|
if (estmodelParam) {
|
||||||
updateEstmodel(estmodelParam);
|
updateEstmodel(estmodelParam);
|
||||||
}
|
}
|
||||||
|
if (org) {
|
||||||
|
updateSeatOrg(org);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 鉴权失败或解析异常:阻止访问
|
// 鉴权失败或解析异常:阻止访问
|
||||||
document.body.innerHTML =
|
document.body.innerHTML =
|
||||||
@@ -198,13 +204,14 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log('data:', data);
|
||||||
const username = data?.username;
|
const username = data?.username;
|
||||||
if (!username) {
|
if (!username) {
|
||||||
throw new Error('认证成功但未返回用户名');
|
throw new Error('认证成功但未返回用户名');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鉴权成功:更新赛位号
|
// 鉴权成功:更新赛位号
|
||||||
updateSeatNumber(username);
|
updateSeatNumber(username);
|
||||||
|
// 更新组织机构
|
||||||
setIsFromUrl(true)
|
setIsFromUrl(true)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 鉴权失败或解析异常:阻止访问
|
// 鉴权失败或解析异常:阻止访问
|
||||||
@@ -217,7 +224,6 @@ useEffect(() => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 工具函数:合并类名,过滤掉假值
|
// 工具函数:合并类名,过滤掉假值
|
||||||
function classNames(...classes) {
|
function classNames(...classes) {
|
||||||
return classes.filter(Boolean).join(' ');
|
return classes.filter(Boolean).join(' ');
|
||||||
@@ -639,7 +645,7 @@ function classNames(...classes) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* 右侧按钮 */}
|
{/* 右侧按钮 */}
|
||||||
{/* {faultScenarios !== 'WorldSkill' && ( */}
|
{faultScenarios !== 'CopperAnalyzer' && (
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsRightDrawerOpen(!isRightDrawerOpen)}
|
onClick={() => setIsRightDrawerOpen(!isRightDrawerOpen)}
|
||||||
@@ -656,7 +662,7 @@ function classNames(...classes) {
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* )} */}
|
)}
|
||||||
|
|
||||||
{/* 左侧抽屉模态框 */}
|
{/* 左侧抽屉模态框 */}
|
||||||
|
|
||||||
|
|||||||
@@ -264,7 +264,10 @@ devtools(
|
|||||||
// faultScenarios: "CopperAnalyzer",
|
// faultScenarios: "CopperAnalyzer",
|
||||||
WorldSkillScenarios: "OFFICE",
|
WorldSkillScenarios: "OFFICE",
|
||||||
// 赛位号
|
// 赛位号
|
||||||
|
// seatNumber: "husky",
|
||||||
seatNumber: "",
|
seatNumber: "",
|
||||||
|
// 组织机构
|
||||||
|
seatOrg: "",
|
||||||
// 比赛ID
|
// 比赛ID
|
||||||
seatUUID: null,
|
seatUUID: null,
|
||||||
// 比赛开始时间
|
// 比赛开始时间
|
||||||
@@ -497,7 +500,12 @@ devtools(
|
|||||||
seatNumber: number
|
seatNumber: number
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
// 更新组织机构
|
||||||
|
updateSeatOrg: (org) => {
|
||||||
|
set(() => ({
|
||||||
|
seatOrg: org
|
||||||
|
}));
|
||||||
|
},
|
||||||
// 更新比赛ID
|
// 更新比赛ID
|
||||||
updateSeatUUID: (uuid) => {
|
updateSeatUUID: (uuid) => {
|
||||||
set(() => ({
|
set(() => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user