Update APC

This commit is contained in:
nguentrungthat 2025-11-04 11:16:15 +07:00
parent 3b55644bc1
commit abda7c4e99
9 changed files with 1677 additions and 79 deletions

View File

@ -50,6 +50,7 @@ export default class LineConnection {
private outputBuffer: string
private isRunningScript: boolean
private connecting: boolean
private waitingScenario: boolean
constructor(config: LineConfig, socketIO: any) {
this.config = config
@ -58,6 +59,7 @@ export default class LineConnection {
this.outputBuffer = ''
this.isRunningScript = false
this.connecting = false
this.waitingScenario = false
}
connect(timeoutMs = 5000) {
@ -89,9 +91,12 @@ export default class LineConnection {
this.client.on('data', (data) => {
if (this.connecting) return
let message = data.toString()
if (this.isRunningScript) {
this.waitingScenario = true
this.outputBuffer += message
}
if (message.includes('--More--')) this.writeCommand(' ')
if (this.isRunningScript) this.outputBuffer += message
// let output = cleanData(message)
// console.log(`📨 [${this.config.port}] ${message}`)
// Handle netOutput with backspace support
@ -109,12 +114,7 @@ export default class LineConnection {
lineId: id,
data: message,
})
appendLog(
cleanData(message),
this.config.stationId,
this.config.lineNumber,
this.config.port
)
appendLog(message, this.config.stationId, this.config.lineNumber, this.config.port)
})
this.client.on('error', (err) => {
@ -235,8 +235,17 @@ export default class LineConnection {
}, script.timeout || 300000)
const runStep = async (index: number) => {
console.log('Running step', index, Date.now())
if (index >= steps.length) {
clearTimeout(timeoutTimer)
if (this.waitingScenario) {
setTimeout(() => {
this.waitingScenario = false
runStep(index)
}, 5000)
return
}
console.log('End step', Date.now())
this.isRunningScript = false
this.outputBuffer = ''
appendLog(
@ -295,7 +304,7 @@ export default class LineConnection {
this.config.port
)
let repeatCount = Number(step.repeat) || 1
const sendCommand = () => {
const sendCommand = async () => {
if (repeatCount <= 0) {
// Done → next step
stepIndex++

View File

@ -201,6 +201,7 @@ export class WebSocketIo {
// Get file stats
const stats = fs.statSync(filePath)
const fileSizeInBytes = stats.size
console.log('File size (bytes):', fileSizeInBytes)
if (fileSizeInBytes / 1024 / 1024 > 0.5) {
// File is larger than 0.5 MB
const fileId = Date.now() // Mã định danh file

View File

@ -14,6 +14,8 @@ import {
Grid,
ScrollArea,
LoadingOverlay,
Button,
Box,
} from "@mantine/core";
import type {
IDataTakeOver,

View File

@ -49,95 +49,53 @@ export const ButtonDPELP = ({
},
{
expect: "",
send: " show inventory",
send: "show inventory",
delay: "1000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show diag",
delay: "1000",
send: "show diag",
delay: "2000",
repeat: "1",
note: "",
},
{
expect: "",
send: " ",
delay: "1000",
send: "show post",
delay: "3000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show post",
delay: "1000",
send: "show env",
delay: "3000",
repeat: "1",
note: "",
},
{
expect: "",
send: " ",
delay: "1000",
send: "show license",
delay: "3000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show env",
delay: "1000",
send: "show log",
delay: "3000",
repeat: "1",
note: "",
},
{
expect: "",
send: " ",
delay: "1000",
send: "show platform",
delay: "3000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show license",
delay: "1000",
repeat: "1",
note: "",
},
{
expect: "",
send: " ",
delay: "1000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show log",
delay: "1000",
repeat: "1",
note: "",
},
{
expect: "",
send: " ",
delay: "1000",
repeat: "1",
note: "",
},
{
expect: "",
send: " show platform",
delay: "1000",
repeat: "1",
note: "",
},
// {
// expect: "",
// send: " ",
// delay: "7000",
// repeat: "15",
// note: "",
// },
];
socket?.emit(
"run_scenario",

View File

@ -84,3 +84,26 @@
width: 100px;
padding: 6px 4px;
}
.inputChatAllContainer {
width: 70%;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 0;
z-index: 1;
padding-bottom: 10px;
gap: 10px;
}
.titleAPC {
/* background-color: light-dark(var(white), var(--mantine-color-dark-7)); */
/* z-index: 100; */
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
/* border-bottom: solid rgba(201, 201, 201, 0.377) 1px;
border-top: solid rgba(201, 201, 201, 0.377) 1px; */
}

View File

@ -2,6 +2,7 @@ import {
ActionIcon,
Avatar,
Box,
Button,
CloseButton,
Flex,
Group,
@ -38,6 +39,7 @@ import {
import classes from "./Component.module.css";
import type { TStation, TUser } from "../untils/types";
import type { Socket } from "socket.io-client";
import { DrawerAPCControl, DrawerSwitchControl } from "./DrawerControl";
interface DraggableTabsProps {
tabsData: TStation[];
@ -126,6 +128,8 @@ export default function DraggableTabs({
const [isChangeTab, setIsChangeTab] = useState<boolean>(false);
const [isSetActive, setIsSetActive] = useState<boolean>(false);
const [valueInput, setValueInput] = useState<string>("");
const [openedAPC, setOpenedAPC] = useState(false);
const [openedSwitch, setOpenedSwitch] = useState(false);
// const [active, setActive] = useState<string | null>(
// tabsData?.length > 0 ? tabsData[0]?.id.toString() : null
// );
@ -232,7 +236,7 @@ export default function DraggableTabs({
w={w}
>
<Flex justify={"space-between"}>
<Flex style={{ width: "300px" }} align={"center"}>
<Flex style={{ width: "400px" }} align={"center"}>
<Input
style={{
width: "300px",
@ -259,6 +263,31 @@ export default function DraggableTabs({
/>
}
/>
<Flex gap={"xs"} ms={"md"}>
<Button
miw={"80px"}
size="xs"
fz={"sm"}
variant="filled"
onClick={() => {
setOpenedAPC(true);
}}
>
APC
</Button>
<Button
miw={"80px"}
size="xs"
fz={"sm"}
variant="filled"
color="yellow"
onClick={() => {
setOpenedSwitch(true);
}}
>
Switch
</Button>
</Flex>
</Flex>
<Tabs.List className={classes.list}>
<SortableContext
@ -367,6 +396,36 @@ export default function DraggableTabs({
{panels}
</Tabs>
{tabs.find((el) => el.id.toString() === active) && (
<DrawerAPCControl
open={openedAPC}
onClose={() => {
setOpenedAPC(false);
}}
socket={socket}
stationAPI={tabs.find((el) => el.id.toString() === active) || tabs[0]}
openedSwitch={() => {
setOpenedAPC(false);
setOpenedSwitch(true);
}}
/>
)}
{tabs.find((el) => el.id.toString() === active) && (
<DrawerSwitchControl
open={openedSwitch}
onClose={() => {
setOpenedSwitch(false);
}}
socket={socket}
stationAPI={tabs.find((el) => el.id.toString() === active) || tabs[0]}
openedAPC={() => {
setOpenedSwitch(false);
setOpenedAPC(true);
}}
/>
)}
</DndContext>
);
}

File diff suppressed because it is too large Load Diff

View File

@ -23,11 +23,9 @@ const ModalLog = ({
const highlightSystemLog = (logText: string): string => {
const colorStart = "#7fffd4";
const colorEnd = "#ffa589";
const colorPhysicalStart = "#7fffd4";
const colorPhysicalEnd = "#ffa589";
return logText
.replace(/^---scenario---.*$/gm, "") // Remove split-point lines
.replace(/^---send-command---.*$/gm, "") // Remove split-point lines
.replace(/---scenario---.*\n?/g, "") // Remove lines with ---scenario---
.replace(/\n?---send-command---.*\n?/g, "") // Remove lines with ---send-command---
.replace(
/^(---start-testing---|---end-testing---|---start-scenarios---|---end-scenarios---)(\d+)(---.*)?$/gm,
(_, prefix, timestamp, suffix = "") => {
@ -36,16 +34,6 @@ const ModalLog = ({
prefix.includes("start") ? colorStart : colorEnd
}" title="${date}">${prefix}${timestamp}${suffix}</span>`;
}
)
.replace(
/^(---start_physical_test_|---end_physical_test_)([A-Z0-9]+)_(\d+)---$/gm,
(_, prefix, sn, timestamp) => {
const date = convertTimestampToDate(timestamp);
const backgroundColor = prefix.includes("start")
? colorPhysicalStart
: colorPhysicalEnd;
return `<span style="background-color: ${backgroundColor}" title="${date}">${prefix}${sn}_${timestamp}---</span>`;
}
);
};

View File

@ -1,3 +1,5 @@
import { useCallback, useRef } from "react";
export const numberOnly = (value: string): string => {
const matched = value.match(/[\d.]+/g);
return matched ? matched.join("") : "";
@ -32,3 +34,31 @@ export const convertTimestampToDate = (timestamp: number) => {
const date = new Date(Number(timestamp));
return date.toLocaleString();
};
/**
* Custom debounce hook.
* @param callback - Function to debounce.
* @param delay - Delay in milliseconds.
* @returns A debounced version of the callback.
*/
export const useDebounce = <T extends (...args: any[]) => void>(
callback: T,
delay: number
) => {
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
const debouncedFn = useCallback(
(...args: Parameters<T>) => {
if (timer.current) {
clearTimeout(timer.current);
}
timer.current = setTimeout(() => {
callback(...args);
}, delay);
},
[callback, delay]
);
return debouncedFn;
};