commit 496f0754fd4e031f7fa227db32697ef9fc48d2f4 Author: qinjian Date: Wed Aug 20 09:48:52 2025 +0800 代码迁移 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..574fa24 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 3 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d54b58 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.env +npm-debug.log +.DS_Store +*.log +.idea/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..21306ea --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +registry=https://registry.npmmirror.com +@peace/:registry=https://nexus.ngaiot.com/repository/fs-npm +@fs/attachment:registry=https://nexus.ngaiot.com/repository/fs-npm \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c95f840 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,97 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "开发模式", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "npm", + "skipFiles": [ + "/**" + ], + "runtimeArgs": [ + "run", + "start", + "--", + "--inspect-brk" + ], + "console": "integratedTerminal", + "env": { + /* + 参数都写在这里 省事儿 + 修改后需重启 + */ + "NODE_ENV": "development", + "PORT": "5000", + // + "FS_QINIU_DOMAIN": "https://resources-test.anxinyun.cn", + "FS_QINIU_ACTION": "https://up-z0.qiniup.com", + "FS_QINIU_ASSETS_DIR": "temp_v5", + // + "FS_SOCKET_URL": "ws://localhost:4000", + // + "API": "http://localhost:4000", + // TCP代理配置 + "TCP_HOST": "10.8.30.179", + "TCP_PORT": "2230", + } + }, + { + "type": "node", + "request": "launch", + "name": "本地构建", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "npm", + "skipFiles": [ + "/**" + ], + "runtimeArgs": [ + "run", + "build", + // "--", + // "--inspect-brk" + ], + "console": "integratedTerminal", + "env": {} + }, + { + "type": "node", + "request": "launch", + "name": "生产模式", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "npm", + "skipFiles": [ + "/**" + ], + "runtimeArgs": [ + "run", + "start", + "--", + "--inspect-brk" + ], + "console": "integratedTerminal", + "env": { + /* + 参数都写在这里 省事儿 + 修改后需重启 + */ + "NODE_ENV": "production", + "PORT": "5100", + /* ... */ + "FS_QINIU_DOMAIN": "https://resources-test.anxinyun.cn", + "FS_QINIU_ACTION": "https://up-z0.qiniup.com", + "FS_QINIU_ASSETS_DIR": "temp_v5", + // + "FS_SOCKET_URL": "ws://localhost:4000", + // + "API": "http://localhost:4000", + "TCP_HOST": "127.0.0.1", + "TCP_PORT": "2230", + } + }, + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5be3c7c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.tabSize": 3 +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..16e9325 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM node:20.18-alpine AS build-stage +WORKDIR /app +COPY package*.json ./ +COPY .npmrc ./ +RUN npm install --loglevel=http +COPY . . +RUN npm run build + +FROM node:20.18-alpine AS prod-stage +WORKDIR /app +COPY package*.json ./ +COPY .npmrc ./ +COPY config.cjs ./ +COPY server ./server +RUN npm install --loglevel=http +COPY --from=build-stage /app/dist ./dist +ENV NODE_ENV=production +ENV PORT=8080 +EXPOSE 8080 +EXPOSE 8081 +CMD ["npm", "start"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bc3f0f --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# 无源标靶上位机 + +## Docker +### 构建镜像 + +```bash +docker build -t passive-targeting-web . +``` +### 运行容器 + +```bash +docker run -d -p 8080:8080 -p 8081:8081 --name passive-targeting-web passive-targeting-web +``` diff --git a/client/assets/favicon.ico b/client/assets/favicon.ico new file mode 100644 index 0000000..13e35d8 Binary files /dev/null and b/client/assets/favicon.ico differ diff --git a/client/assets/img/auth_bg.png b/client/assets/img/auth_bg.png new file mode 100644 index 0000000..af1719a Binary files /dev/null and b/client/assets/img/auth_bg.png differ diff --git a/client/assets/img/fs_logo.png b/client/assets/img/fs_logo.png new file mode 100644 index 0000000..3016c79 Binary files /dev/null and b/client/assets/img/fs_logo.png differ diff --git a/client/assets/img/fs_logo_banner.png b/client/assets/img/fs_logo_banner.png new file mode 100644 index 0000000..29daecb Binary files /dev/null and b/client/assets/img/fs_logo_banner.png differ diff --git a/client/assets/img/wuyuanbiaoba_template_images/temp_target1.jpg b/client/assets/img/wuyuanbiaoba_template_images/temp_target1.jpg new file mode 100644 index 0000000..5cd6c18 Binary files /dev/null and b/client/assets/img/wuyuanbiaoba_template_images/temp_target1.jpg differ diff --git a/client/assets/script/peace.js b/client/assets/script/peace.js new file mode 100644 index 0000000..80d5ca3 --- /dev/null +++ b/client/assets/script/peace.js @@ -0,0 +1,7 @@ +console.log(` + ,----. ,------. ,------. ,---. ,-----.,------. +' , | | .--. '| .---' / O \\ ' .--./| .---' +| | / | '--' || \`--, | .-. || | | \`--, +' '--'| | | --' |\`-- -. | | | |' '--'\\\| \`---. + \`----' \`--' \`----- '·--''--·\`-----' \`-----' + `); diff --git a/client/entry/client.jsx b/client/entry/client.jsx new file mode 100644 index 0000000..a2ebc53 --- /dev/null +++ b/client/entry/client.jsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from '../index' + +ReactDOM.hydrateRoot( + document.getElementById('root'), + // + + // +) diff --git a/client/entry/server.jsx b/client/entry/server.jsx new file mode 100644 index 0000000..b2a64a5 --- /dev/null +++ b/client/entry/server.jsx @@ -0,0 +1,12 @@ +import React from 'react' +import ReactDOMServer from 'react-dom/server' +import App from '../index' + +export function render ({ path }) { + const html = ReactDOMServer.renderToString( + + + + ) + return { html } +} diff --git a/client/index.jsx b/client/index.jsx new file mode 100644 index 0000000..24d4ee5 --- /dev/null +++ b/client/index.jsx @@ -0,0 +1,14 @@ +import App from "./src/app"; +import { ConfigProvider } from "antd"; +import zhCN from 'antd/locale/zh_CN'; + +export default () => { + return ( + + + + ) +} diff --git a/client/src/app.jsx b/client/src/app.jsx new file mode 100644 index 0000000..f349351 --- /dev/null +++ b/client/src/app.jsx @@ -0,0 +1,13 @@ +"use strict"; +import { useEffect, useState } from "react"; +import Layout from "./layout/index"; +import Auth from "./sections/auth"; +import Home from "./sections/home"; +import Wuyuanbiaoba from "./sections/wuyuanbiaoba"; +import "./app.less"; +const App = () => { + return +}; +export default App; diff --git a/client/src/app.less b/client/src/app.less new file mode 100644 index 0000000..c54988c --- /dev/null +++ b/client/src/app.less @@ -0,0 +1,36 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + user-select: none; +} + +// 美化滚动条 +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + width: 6px; + background: rgba(#101f1c, 0.1); + -webkit-border-radius: 1em; + -moz-border-radius: 1em; + border-radius: 1em; + /* 通过 margin 设置轨道与元素的距离 */ + margin: 6px; +} + +::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.5); + background-clip: padding-box; + min-height: 28px; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em; + transition: background-color 0.3s; + cursor: pointer; +} + +::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.3); +} diff --git a/client/src/components/errorBoundary.jsx b/client/src/components/errorBoundary.jsx new file mode 100644 index 0000000..0c90a0f --- /dev/null +++ b/client/src/components/errorBoundary.jsx @@ -0,0 +1,35 @@ +import React, { Component } from 'react'; +import { Result, Button } from 'antd'; + +class ErrorBoundary extends Component { + constructor(props) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError (error) { + // 更新 state 使下一次渲染能够显示降级后的 UI + return { hasError: true }; + } + + componentDidCatch (error, errorInfo) { + // 可以将错误日志上报给服务器 + } + + render () { + const { errorRender } = this.props; + if (this.state.hasError) { + // 可以自定义降级后的 UI 并渲染 + return errorRender || this.state.navigate(-1)}>返回上一页} + />; + } + + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/client/src/components/index.js b/client/src/components/index.js new file mode 100644 index 0000000..8312d62 --- /dev/null +++ b/client/src/components/index.js @@ -0,0 +1,7 @@ +// import Upload from "./upload"; +import ErrorBoundary from "./errorBoundary"; + +export { + // Upload, + ErrorBoundary, +}; diff --git a/client/src/components/upload.jsx b/client/src/components/upload.jsx new file mode 100644 index 0000000..a9f8c6b --- /dev/null +++ b/client/src/components/upload.jsx @@ -0,0 +1,150 @@ +import React, { useState, useMemo, useEffect } from 'react'; +import { useDispatch, useSelector } from "react-redux"; +import { UploadOutlined } from '@ant-design/icons'; +import { Button, Upload, Spin, message, Image } from 'antd'; +import moment from 'moment'; +import request from "superagent"; + +const Images = ['png', 'jpg', 'svg', 'jpeg'] + +export default function upload (props) { + const { value = null, onChange = () => { }, maxCount, maxSize = 3, types = [], disabled = false, xunruanDecode, ...uploadOption } = props; + const { FS_QINIU_DOMAIN, FS_QINIU_ACTION, FS_QINIU_ASSETS_DIR } = window.env; + /** + * fileList: [] # 参考 + * types: ['jpg'] # 限定文件类型 + * maxSize: 1024 # 限定文件大小 M + */ + const [messageApi, contextHolder] = message.useMessage(); + const actions = useSelector(state => state.global.actions); + const qiniuToken = useSelector(state => state.qiniuToken); + const dispatch = useDispatch(); + // + const [fileList_, setFileList_] = useState([]); + const [previewImg, setPreviewImg] = useState(null); + + useEffect(() => { + if (!qiniuToken?.data) { + dispatch(actions.qiniuToken()) + } + }, []) + + const uploadProps = { + name: "file", + action: FS_QINIU_ACTION, + fileList: (value || fileList_).map((df, index) => { + return { + ...df, + uid: df.uid || -index, + status: df.status || 'done', + name: df?.url?.split('/').pop() ?? df.name, + url: df.url ? + df.url.startsWith('http') ? df.url + : `${FS_QINIU_DOMAIN}/${df?.url}` + : df.thumbUrl, + } + }), + // disabled: disabled || (maxCount && fileList_.length >= maxCount), + data: (file) => { + return { + token: qiniuToken.data, + /** key 表现为文件名 */ + key: `${FS_QINIU_ASSETS_DIR}/${moment().format('YYYYMMDDHHmmss')}/${file.name}`, + } + }, + beforeUpload: (file) => { + return new Promise((resolve, reject) => { + if (maxCount && (value || fileList_).length >= maxCount) { + messageApi.warning(`最多选择${maxCount}个文件上传`) + return Upload.LIST_IGNORE + } + if (file.name.length > 60) { + messageApi.warning(`文件名过长(大于60字符),请修改后上传`); + return Upload.LIST_IGNORE + } + if (file.size > maxSize * 1024 * 1024) { + messageApi.warning(`文件须小于 ${maxSize} M`); + return Upload.LIST_IGNORE + } + let fileNameArr = file.name.split('.') + let postfix = '' + if (fileNameArr.length > 1) { + postfix = fileNameArr[fileNameArr.length - 1] + postfix.toLowerCase() + } + if (types.length && (!types.includes(postfix) || !postfix)) { + messageApi.warning(`请上传 ${types.join(',')} 类型的文件`); + return Upload.LIST_IGNORE + } + return resolve() + }) + }, + customRequest: xunruanDecode ? async (p) => { + const { file, filename, onSuccess, onError } = p + try { + // 讯软解密 + const formData = new FormData(); + formData.append("file", file); + const decodeRes = await request.post("/xunruan/decryption",).send(formData); + onSuccess({ + ...decodeRes.text + }) + } catch (error) { + console.error(error); + onError({}) + } + } : undefined, + + + onChange: (files) => { + let fileList = files?.fileList?.map(f => { + return { + ...f, + url: f.response?.key ?? f?.url ?? f.thumbUrl + } + }) + setFileList_(fileList); + onChange(fileList) + }, + onPreview: (file) => { + const url = file?.url || `${FS_QINIU_DOMAIN} / ${file?.response.key}` + let postfix = url.split('.').pop(); + postfix = postfix.toLowerCase(); + if (url.indexOf("pdf") !== -1 || url.indexOf("csv") !== -1) { + window.open(url) + } else if (Images.includes(postfix)) { + setPreviewImg(url); + } else { + window.open(`https://view.officeapps.live.com/op/view.aspx?src=${url}`) + } + }, + // maxCount: maxCount, + ...uploadOption + } + + return ( + + {contextHolder} + + {props.children || + + + + + ); +} diff --git a/client/src/sections/auth/container/login.less b/client/src/sections/auth/container/login.less new file mode 100644 index 0000000..9ab9e6c --- /dev/null +++ b/client/src/sections/auth/container/login.less @@ -0,0 +1,4 @@ +.login { + background: url("@assets/img/auth_bg.png") no-repeat fixed 0 0; + background-size: cover; +} diff --git a/client/src/sections/auth/index.js b/client/src/sections/auth/index.js new file mode 100644 index 0000000..7e5ca8a --- /dev/null +++ b/client/src/sections/auth/index.js @@ -0,0 +1,6 @@ +import route from './router'; +import actions from './actions'; +export default { + route: route, + actions: actions, +}; diff --git a/client/src/sections/auth/router.js b/client/src/sections/auth/router.js new file mode 100644 index 0000000..5ae468d --- /dev/null +++ b/client/src/sections/auth/router.js @@ -0,0 +1,9 @@ +import Login from './container/login' +export default { + type: 'outer', + route: { + key: 'signin', + path: "/signin", + component: Login + } +}; \ No newline at end of file diff --git a/client/src/sections/home/actions/index.js b/client/src/sections/home/actions/index.js new file mode 100644 index 0000000..6610467 --- /dev/null +++ b/client/src/sections/home/actions/index.js @@ -0,0 +1,11 @@ +import { basicAction } from "@u" +import qiniu from './qiniu' +/** + * @param {url} 请求地址(必选项) + * @param {option} 携带参数({}) + * const func = basicAction.get(url, option); + */ + +export default { + ...qiniu, +} \ No newline at end of file diff --git a/client/src/sections/home/actions/qiniu.js b/client/src/sections/home/actions/qiniu.js new file mode 100644 index 0000000..ed37dfd --- /dev/null +++ b/client/src/sections/home/actions/qiniu.js @@ -0,0 +1,7 @@ +import { basicAction, apiTable } from "@u" + +const qiniuToken = basicAction.get(apiTable.qiniuToken, { + tip: false, +}); + +export default { qiniuToken } \ No newline at end of file diff --git a/client/src/sections/home/container/index.jsx b/client/src/sections/home/container/index.jsx new file mode 100644 index 0000000..eb8c45c --- /dev/null +++ b/client/src/sections/home/container/index.jsx @@ -0,0 +1,45 @@ +import { useDispatch, useSelector } from "react-redux"; +// import { Upload } from '@comps' +import { apiRequest } from '@u' +import { Form } from "antd"; +import { useEffect } from "react"; + + +export default function Index () { + const global = useSelector(state => state.global); //仓库方法 + const dispatch = useDispatch(); + const { FS_QINIU_DOMAIN, FS_QINIU_ASSETS_DIR, FS_SOCKET_URL } = window.env; + + useEffect(() => { + var ws = new WebSocket(FS_SOCKET_URL) + ws.onopen = function () { } + ws.onmessage = function (e) { } + }, []) + + return ( +
+

Welcome @peace

+
+ {/* + { + console.log(fileList) + }} + > + 上传文件 + + */} +
+
+ ); +} diff --git a/client/src/sections/home/index.js b/client/src/sections/home/index.js new file mode 100644 index 0000000..b411001 --- /dev/null +++ b/client/src/sections/home/index.js @@ -0,0 +1,7 @@ +import route from './router' +import actions from './actions' + +export default { + route: route, + actions: actions, +} diff --git a/client/src/sections/home/router.jsx b/client/src/sections/home/router.jsx new file mode 100644 index 0000000..f82a2bf --- /dev/null +++ b/client/src/sections/home/router.jsx @@ -0,0 +1,24 @@ +import { HomeOutlined, ApartmentOutlined, } from "@ant-design/icons"; +import Index from "./container"; + +export default { + type: "inner", + route: { + key: "home", + path: "home", + // component: Index, + label: "Home", // 导航栏显示的名称 + icon: , + nav: true, // 是否显示在左侧 Sider 导航栏 + children: [ + { + key: "child", + path: "child", + component: Index, + label: "Child", + icon: , + nav: true, + }, + ], + }, +}; diff --git a/client/src/sections/wuyuanbiaoba/actions/index.js b/client/src/sections/wuyuanbiaoba/actions/index.js new file mode 100644 index 0000000..37e8ffb --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/actions/index.js @@ -0,0 +1,9 @@ +// 导出WebSocket相关功能 +export { + WebSocketProvider, + useWebSocket, + useWebSocketSubscription, + useWebSocketMessage +} from './websocket.jsx'; + +export default {}; diff --git a/client/src/sections/wuyuanbiaoba/actions/websocket.jsx b/client/src/sections/wuyuanbiaoba/actions/websocket.jsx new file mode 100644 index 0000000..f2d379d --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/actions/websocket.jsx @@ -0,0 +1,464 @@ +/** + * WebSocket Hook - TCP代理连接管理 + * + * 提供WebSocket连接的统一管理,用于与TCP代理服务器进行通信 + * + * 数据格式规范: + * ```json + * { + * "_from": "dev|setup|...", // 数据来源: dev=设备, setup=上位机 + * "cmd": "getBase|setConfig|...", // 具体命令 + * "values": {} // 命令参数或数据 + * } + * ``` + * + * 使用方法: + * + * 1. 在根组件中使用WebSocketProvider包装: + * ```jsx + * import { WebSocketProvider } from './actions/websocket.jsx'; + * + * const App = () => { + * return ( + * + * + * + * ); + * }; + * ``` + * + * 2. 基本使用: + * ```jsx + * import { useWebSocket } from './actions/websocket.jsx'; + * + * const MyComponent = () => { + * const { isConnected, sendMessage, lastMessage } = useWebSocket(); + * + * const handleSendCommand = () => { + * sendMessage(JSON.stringify({ + * _from: 'setup', + * cmd: 'setConfig', + * values: { x: 100, y: 200 } + * })); + * }; + * + * return ( + *
+ * + *
最新消息: {JSON.stringify(lastMessage)}
+ *
+ * ); + * }; + * ``` + * + * 3. 订阅特定来源和命令的消息: + * ```jsx + * import { useWebSocketSubscription } from './actions/websocket.jsx'; + * + * const DeviceDataComponent = () => { + * 只监听设备发送的基础数据 + * const baseData = useWebSocketSubscription('dev', 'getBase'); + * + * 监听所有设备消息 + * const allDeviceData = useWebSocketSubscription('dev'); + * + * 监听特定命令(任何来源) + * const configData = useWebSocketSubscription(null, 'setConfig'); + * + * return ( + *
+ *

设备基础数据:

+ *
{JSON.stringify(baseData, null, 2)}
+ *
+ * ); + * }; + * ``` + * + * 4. 自定义消息处理: + * ```jsx + * import { useWebSocketMessage } from './actions/websocket.jsx'; + * + * const CustomHandler = () => { + * useWebSocketMessage(({ _from, cmd, values, timestamp }) => { + * if (_from === 'dev' && cmd === 'alarm') { + * 处理设备告警 + * handleDeviceAlarm(values); + * } + * }); + * + * return
监听中...
; + * }; + * ``` + * + * API说明: + * - isConnected: boolean - 连接状态 + * - connectionStatus: string - 连接状态('connecting'|'connected'|'disconnected'|'error') + * - sendMessage: (message: string) => boolean - 发送消息 + * - lastMessage: object - 最后接收的消息 + * - messageHistory: array - 消息历史 + * - subscribe: (from, cmd, callback) => unsubscribe - 订阅消息 + * - useWebSocketSubscription: (from, cmd) => data - 订阅Hook + * - useWebSocketMessage: (callback) => void - 消息监听Hook + * + * 特性: + * - 基于 _from 和 cmd 的发布订阅模式 + * - 自动连接和重连(最多5次) + * - 消息类型过滤和路由 + * - 多组件共享同一WebSocket连接 + * - 完整的连接生命周期管理 + */ + +import React, { + createContext, + useContext, + useEffect, + useRef, + useState, + useCallback, +} from "react"; + +// 创建WebSocket Context +const WebSocketContext = createContext(); + +// WebSocket Provider组件 +export const WebSocketProvider = ({ children }) => { + const [isConnected, setIsConnected] = useState(false); + const [connectionStatus, setConnectionStatus] = useState("disconnected"); + const [lastMessage, setLastMessage] = useState(null); // 最后接收的消息 + const [messageHistory, setMessageHistory] = useState([]); // 消息历史 + const socketRef = useRef(null); + const reconnectTimeoutRef = useRef(null); + const reconnectAttemptsRef = useRef(0); + const subscriptionsRef = useRef(new Map()); // 订阅器存储 + const maxReconnectAttempts = 5; + const reconnectInterval = 3000; // 3秒 + const maxHistoryLength = 100; // 最大历史消息数量 + + // 动态获取WebSocket连接地址,支持局域网访问 + const getWebSocketUrl = () => { + const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; + const host = window.location.hostname; + const port = Number(window.location.port) + 1 || 8081; + return `${protocol}//${host}:${port}/tcp-proxy`; + }; + + const websocketUrl = getWebSocketUrl(); + + // 生成订阅key + const getSubscriptionKey = (from, cmd) => { + if (from && cmd) return `${from}:${cmd}`; + if (from) return `${from}:*`; + if (cmd) return `*:${cmd}`; + return "*:*"; + }; + + // 订阅消息 + const subscribe = useCallback((from, cmd, callback) => { + const key = getSubscriptionKey(from, cmd); + + if (!subscriptionsRef.current.has(key)) { + subscriptionsRef.current.set(key, new Set()); + } + + subscriptionsRef.current.get(key).add(callback); + + // 返回取消订阅函数 + return () => { + const callbacks = subscriptionsRef.current.get(key); + if (callbacks) { + callbacks.delete(callback); + if (callbacks.size === 0) { + subscriptionsRef.current.delete(key); + } + } + }; + }, []); + + // 通知订阅者 + const notifySubscribers = useCallback((messageData) => { + const { _from, cmd } = messageData; + + // 可能匹配的订阅key列表 + const keysToCheck = [ + getSubscriptionKey(_from, cmd), // 精确匹配 + getSubscriptionKey(_from, null), // 匹配来源 + getSubscriptionKey(null, cmd), // 匹配命令 + getSubscriptionKey(null, null), // 匹配所有 + ]; + + keysToCheck.forEach((key) => { + const callbacks = subscriptionsRef.current.get(key); + if (callbacks) { + callbacks.forEach((callback) => { + try { + callback(messageData); + } catch (error) { + console.error("订阅回调执行错误:", error); + } + }); + } + }); + }, []); + + // 处理接收到的消息 + const handleMessage = useCallback( + (data) => { + const timestamp = Date.now(); + let parsedData = null; + + try { + parsedData = JSON.parse(data); + + // 验证数据格式 + if (!parsedData._from || !parsedData.cmd) { + console.warn("收到格式不正确的消息:", parsedData); + return; + } + + // console.log(`收到消息 [${parsedData._from}:${parsedData.cmd}]:`, parsedData); + } catch (error) { + console.error("解析WebSocket消息失败:", error, data); + return; + } + + const messageData = { + id: `msg_${timestamp}`, + timestamp, + rawData: data, + ...parsedData, + }; + + // 更新最后消息和历史 + setLastMessage(messageData); + setMessageHistory((prev) => { + const newHistory = [messageData, ...prev]; + return newHistory.slice(0, maxHistoryLength); + }); + + // 通知订阅者 + notifySubscribers(messageData); + }, + [notifySubscribers] + ); + + // 发送消息 + const sendMessage = useCallback((message) => { + if (socketRef.current?.readyState === WebSocket.OPEN) { + try { + socketRef.current.send(message); + // console.log('发送WebSocket消息:', message); + return true; + } catch (error) { + console.error("发送WebSocket消息失败:", error); + return false; + } + } else { + console.warn("WebSocket未连接,无法发送消息"); + return false; + } + }, []); + + // 连接WebSocket + const connect = useCallback(() => { + if (socketRef.current?.readyState === WebSocket.OPEN) { + return; // 已经连接 + } + + setConnectionStatus("connecting"); + console.log("尝试连接WebSocket:", websocketUrl); + + try { + socketRef.current = new WebSocket(websocketUrl); + + socketRef.current.onopen = () => { + console.log("WebSocket连接已建立"); + setIsConnected(true); + setConnectionStatus("connected"); + reconnectAttemptsRef.current = 0; + + // 发送初始消息或心跳 + // sendMessage(JSON.stringify({ + // _from: 'setup', + // cmd: 'init', + // values: { timestamp: Date.now() } + // })); + }; + + socketRef.current.onmessage = (event) => { + try { + const data = + typeof event.data === "string" ? event.data : event.data; + + // 这里可以处理接收到的消息,比如更新全局状态 + // 或者触发自定义事件 + handleMessage(data); + } catch (error) { + console.error("处理WebSocket消息错误:", error); + } + }; + + socketRef.current.onclose = (event) => { + console.log("WebSocket连接已关闭:", event.code, event.reason); + setIsConnected(false); + setConnectionStatus("disconnected"); + + // 自动重连逻辑 + if (reconnectAttemptsRef.current < maxReconnectAttempts) { + reconnectAttemptsRef.current++; + console.log( + `尝试重连 ${reconnectAttemptsRef.current}/${maxReconnectAttempts}` + ); + reconnectTimeoutRef.current = setTimeout(() => { + connect(); + }, reconnectInterval); + } else { + console.log("达到最大重连次数,停止重连"); + setConnectionStatus("error"); + } + }; + + socketRef.current.onerror = (error) => { + console.error("WebSocket错误:", error); + setConnectionStatus("error"); + }; + } catch (error) { + console.error("创建WebSocket连接失败:", error); + setConnectionStatus("error"); + } + }, [handleMessage, sendMessage]); + + // 断开连接 + const disconnect = useCallback(() => { + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + } + + if (socketRef.current) { + socketRef.current.close(1000, "用户主动断开"); + socketRef.current = null; + } + + setIsConnected(false); + setConnectionStatus("disconnected"); + reconnectAttemptsRef.current = 0; + }, []); + + // 获取特定来源和命令的消息历史 + const getMessages = useCallback( + (from, cmd) => { + return messageHistory.filter((msg) => { + if (from && cmd) return msg._from === from && msg.cmd === cmd; + if (from) return msg._from === from; + if (cmd) return msg.cmd === cmd; + return true; + }); + }, + [messageHistory] + ); + + // 清空消息历史 + const clearMessageHistory = useCallback(() => { + setMessageHistory([]); + setLastMessage(null); + }, []); + + // 组件挂载时自动连接 + useEffect(() => { + connect(); + + // 组件卸载时清理 + return () => { + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + } + if (socketRef.current) { + socketRef.current.close(); + } + }; + }, [connect]); + + // 提供给子组件的值 + const value = { + // 连接状态 + isConnected, + connectionStatus, + + // 连接控制 + connect, + disconnect, + sendMessage, + + // 数据访问 + lastMessage, + messageHistory, + getMessages, + clearMessageHistory, + + // 订阅功能 + subscribe, + + // 原始socket + socket: socketRef.current, + }; + + return ( + + {children} + + ); +}; + +// 自定义Hook,方便子组件使用 +export const useWebSocket = () => { + const context = useContext(WebSocketContext); + if (!context) { + throw new Error("useWebSocket必须在WebSocketProvider内部使用"); + } + return context; +}; + +// 订阅特定来源和命令的消息Hook +export const useWebSocketSubscription = (from = null, cmd = null) => { + const { subscribe, getMessages } = useWebSocket(); + const [data, setData] = useState([]); + const [latestMessage, setLatestMessage] = useState(null); + + useEffect(() => { + // 获取历史消息 + const history = getMessages(from, cmd); + setData(history); + setLatestMessage(history[0] || null); + + // 订阅新消息 + const unsubscribe = subscribe(from, cmd, (messageData) => { + setLatestMessage(messageData); + setData((prev) => [messageData, ...prev.slice(0, 99)]); // 保持最多100条 + }); + + return unsubscribe; + }, [subscribe, getMessages, from, cmd]); + + return { + data, // 所有匹配的消息 + latest: latestMessage, // 最新的消息 + values: latestMessage?.values || null, // 最新消息的values字段 + }; +}; + +// 通用消息监听Hook +export const useWebSocketMessage = (callback) => { + const { subscribe } = useWebSocket(); + + useEffect(() => { + if (!callback) return; + + // 监听所有消息 + const unsubscribe = subscribe(null, null, callback); + return unsubscribe; + }, [subscribe, callback]); +}; + +// 默认导出 +export default WebSocketContext; diff --git a/client/src/sections/wuyuanbiaoba/components/CameraView.jsx b/client/src/sections/wuyuanbiaoba/components/CameraView.jsx new file mode 100644 index 0000000..6e1adb7 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/CameraView.jsx @@ -0,0 +1,1209 @@ +import React, { useRef, useEffect, useState, useCallback } from "react"; +import { useWebSocket } from "../actions/websocket.jsx"; +import { useTargetStorage } from "../hooks/useTargetStorage.js"; +const CameraView = ({ + selectedTargetId, + onClearSelection, + onRectangleClick, + selectedTemplate, +}) => { + const imgRef = useRef(null); + const canvasRef = useRef(null); + const videoInnerRef = useRef(null); + const containerRef = useRef(null); + + // 缩放和平移相关状态 + const [scale, setScale] = useState(1.0); + const [translateX, setTranslateX] = useState(0); + const [translateY, setTranslateY] = useState(0); + const [videoNaturalWidth, setVideoNaturalWidth] = useState(1920); + const [videoNaturalHeight, setVideoNaturalHeight] = useState(1080); + const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); + + // 交互状态 + const [drawing, setDrawing] = useState(false); + const [dragging, setDragging] = useState(false); + const [startPos, setStartPos] = useState({ x: 0, y: 0 }); + const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 }); + const [mouseDownTime, setMouseDownTime] = useState(0); // 记录鼠标按下的时间 + const [mouseDownPos, setMouseDownPos] = useState({ x: 0, y: 0 }); // 记录鼠标按下的位置 + + // 矩形列表管理 - 最多5个矩形 + const [rectangles, setRectangles] = useState([]); + const [selectedRectIndex, setSelectedRectIndex] = useState(-1); + const [isDraggingRect, setIsDraggingRect] = useState(false); + const [dragStartPos, setDragStartPos] = useState({ x: 0, y: 0 }); + const [dragRectOffset, setDragRectOffset] = useState({ x: 0, y: 0 }); // 鼠标在矩形内的偏移 + const [currentDrawingRect, setCurrentDrawingRect] = useState(null); + const [hoveredRectIndex, setHoveredRectIndex] = useState(-1); + const [isSaving, setIsSaving] = useState(false); // 保存状态管理 + + // 使用WebSocket连接 + const { isConnected, sendMessage } = useWebSocket(); + + // 使用标靶数据管理Hook + const { targets, loading, refreshTargets } = useTargetStorage(); + + const minScale = 0.2; + const maxScale = 4.0; + const scaleStep = 0.1; + const maxRectangles = 5; + + // 摄像头流地址 + const streamUrl = import.meta.env.MODE === 'development'? 'http://10.8.30.179:2240/video_flow' :"http://127.0.0.1:2240/video_flow"; + + // 应用变换 + const applyTransform = () => { + if (videoInnerRef.current) { + videoInnerRef.current.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`; + videoInnerRef.current.style.transformOrigin = "0 0"; + } + + // 重新绘制所有矩形 + redrawAllRectangles(); + }; + + // 调整画布大小 + const resizeCanvas = () => { + if (canvasRef.current && containerRef.current) { + const container = containerRef.current; + const rect = container.getBoundingClientRect(); + const canvas = canvasRef.current; + + canvas.width = rect.width; + canvas.height = rect.height; + canvas.style.width = rect.width + "px"; + canvas.style.height = rect.height + "px"; + + console.log("resizeCanvas: 画布大小已调整", { + width: rect.width, + height: rect.height, + }); + + // 延迟调用applyTransform,确保画布已经完全设置好 + setTimeout(() => { + applyTransform(); + }, 10); + } + }; + + // 图片加载完成 + const handleImageLoad = () => { + if (imgRef.current) { + const img = imgRef.current; + if (img.naturalWidth && img.naturalHeight) { + setVideoNaturalWidth(img.naturalWidth); + setVideoNaturalHeight(img.naturalHeight); + console.log( + `handleImageLoad: 视频原始分辨率: ${img.naturalWidth}x${img.naturalHeight}` + ); + } + resizeCanvas(); + // 视频加载完成后,确保重新绘制矩形框 + setTimeout(() => { + console.log("handleImageLoad: 延迟重绘矩形框"); + redrawAllRectangles(); + }, 200); + } + }; + + // 鼠标按下 + const handleMouseDown = (e) => { + const container = containerRef.current; + const rect = container.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + // 记录鼠标按下的时间和位置 + setMouseDownTime(Date.now()); + setMouseDownPos({ x: mouseX, y: mouseY }); + + if (e.altKey && e.button === 0) { + // Alt + 左键拖拽进行平移 + setDragging(true); + setLastMousePos({ x: mouseX, y: mouseY }); + e.preventDefault(); + } else if (!e.altKey && e.button === 0) { + // 检查是否点击在已存在的矩形上 + const rectIndex = findRectangleAtPoint(mouseX, mouseY); + + if (rectIndex !== -1) { + // 点击在已存在的矩形上,开始拖拽 + setSelectedRectIndex(rectIndex); + setIsDraggingRect(true); + setDragStartPos({ x: mouseX, y: mouseY }); + + // 计算鼠标在矩形内的相对位置 + const rect = rectangles[rectIndex]; + const rectScreenPos = videoToScreenCoordinates( + rect.x, + rect.y, + rect.width, + rect.height + ); + if (rectScreenPos) { + setDragRectOffset({ + x: mouseX - rectScreenPos.x, + y: mouseY - rectScreenPos.y, + }); + } + + redrawAllRectangles(); + } else { + // 点击在空白区域,开始绘制新矩形(如果没有达到上限) + if (rectangles.length < maxRectangles) { + setSelectedRectIndex(-1); + setStartPos({ x: mouseX, y: mouseY }); + setDrawing(true); + setCurrentDrawingRect(null); + } + } + e.preventDefault(); + } + }; // 鼠标移动 + const handleMouseMove = (e) => { + const container = containerRef.current; + const rect = container.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + // 更新鼠标位置显示 + if (!drawing && !dragging && !isDraggingRect) { + updateMousePosition(mouseX, mouseY); + // 检测鼠标是否悬停在矩形上 + const rectIndex = findRectangleAtPoint(mouseX, mouseY); + setHoveredRectIndex(rectIndex); + } + + if (dragging) { + // 拖拽平移 + const deltaX = mouseX - lastMousePos.x; + const deltaY = mouseY - lastMousePos.y; + setTranslateX((prev) => prev + deltaX); + setTranslateY((prev) => prev + deltaY); + setLastMousePos({ x: mouseX, y: mouseY }); + } else if (drawing) { + // 绘制新矩形预览 + drawNewRectanglePreview(startPos.x, startPos.y, mouseX, mouseY); + } else if (isDraggingRect && selectedRectIndex !== -1) { + // 拖拽已存在的矩形 + dragExistingRectangle(mouseX, mouseY); + } + }; + + // 鼠标松开 + const handleMouseUp = (e) => { + const currentTime = Date.now(); + const timeDiff = currentTime - mouseDownTime; + const container = containerRef.current; + const rect = container.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + // 计算鼠标移动距离 + const mouseMoveDistance = Math.sqrt( + Math.pow(mouseX - mouseDownPos.x, 2) + + Math.pow(mouseY - mouseDownPos.y, 2) + ); + + // 检查是否是单击操作:时间短且移动距离小 + const isClick = timeDiff < 300 && mouseMoveDistance < 5; + + if (dragging) { + setDragging(false); + } else if (drawing) { + setDrawing(false); + + // 完成新矩形的绘制 + finishDrawingRectangle(startPos.x, startPos.y, mouseX, mouseY); + setCurrentDrawingRect(null); + } else if (isDraggingRect) { + if (isClick && onRectangleClick) { + // 找到被点击的矩形 + const rectIndex = findRectangleAtPoint(mouseX, mouseY); + if (rectIndex !== -1) { + const clickedRectangle = rectangles[rectIndex]; + // 通过矩形ID找到对应的标靶数据 + const targetData = targets.find( + (target) => target.id === clickedRectangle.id + ); + if (targetData) { + console.log("点击矩形框,弹出标靶详情:", targetData); + onRectangleClick(targetData); + } + } + } + + setIsDraggingRect(false); + setSelectedRectIndex(-1); // 取消选中状态 + + // 只有在非单击情况下才清除选中高亮状态 + if (onClearSelection && !isClick) { + onClearSelection(); + } + } + }; + + // 绘制新矩形预览 + const drawNewRectanglePreview = (startX, startY, endX, endY) => { + const x = Math.min(startX, endX); + const y = Math.min(startY, endY); + const w = Math.abs(endX - startX); + const h = Math.abs(endY - startY); + + if (w < 5 || h < 5) return; // 太小的矩形不显示 + + // 转换为视频坐标系的矩形 + const videoRect = screenToVideoCoordinates(x, y, w, h); + if (videoRect) { + setCurrentDrawingRect(videoRect); + redrawAllRectangles(); + } + }; + + // 完成新矩形的绘制 + const finishDrawingRectangle = (startX, startY, endX, endY) => { + const x = Math.min(startX, endX); + const y = Math.min(startY, endY); + const w = Math.abs(endX - startX); + const h = Math.abs(endY - startY); + + if (w < 10 || h < 10) return; // 太小的矩形不保存 + + const videoRect = screenToVideoCoordinates(x, y, w, h); + if (videoRect && rectangles.length < maxRectangles) { + // 根据选中的模板预设参数 + const templateParams = selectedTemplate + ? { + // 从模板中获取参数 + name: selectedTemplate.name || `target${rectangles.length + 1}`, + radius: selectedTemplate.physicalRadius || 40.0, + isReferencePoint: selectedTemplate.isBaseline || false, + gradientThreshold: + selectedTemplate.gradientThresholdValue || 100, + anchorThreshold: selectedTemplate.anchorThresholdValue || 80, + gaussianBlurThreshold: selectedTemplate.gaussianBlur || 3, + binaryThreshold: selectedTemplate.binaryThreshold || 120, + hasAdvancedConfig: true, + } + : { + // 默认参数 + name: `target${rectangles.length + 1}`, + radius: 40.0, + isReferencePoint: false, + gradientThreshold: 100, + anchorThreshold: 80, + gaussianBlurThreshold: 3, + binaryThreshold: 120, + hasAdvancedConfig: false, + }; + + const newRect = { + id: Date.now(), // 使用时间戳作为唯一ID + key: Date.now().toString(), + ...videoRect, + ...templateParams, + // 保存矩形区域信息用于服务端 + rectangleArea: { + x: videoRect.x, + y: videoRect.y, + w: videoRect.width, + h: videoRect.height, + width: videoRect.width, + height: videoRect.height, + }, + }; + + setRectangles((prev) => [...prev, newRect]); + + console.log("新建矩形:", newRect); + if (selectedTemplate) { + console.log("使用模板参数:", selectedTemplate); + } else { + console.log("使用默认参数"); + } + logRectangleData(); + } + }; // 拖拽已存在的矩形 + const dragExistingRectangle = (mouseX, mouseY) => { + if (selectedRectIndex === -1) return; + + // 计算矩形应该在的屏幕位置(考虑鼠标在矩形内的偏移) + const targetScreenX = mouseX - dragRectOffset.x; + const targetScreenY = mouseY - dragRectOffset.y; + + // 转换为视频坐标 + const rect = rectangles[selectedRectIndex]; + const videoCoords = screenToVideoCoordinates( + targetScreenX, + targetScreenY, + 0, + 0 + ); + + if (videoCoords) { + setRectangles((prev) => { + const newRects = [...prev]; + + // 计算新位置,确保不超出视频边界 + const newX = Math.max( + 0, + Math.min(videoNaturalWidth - rect.width, videoCoords.x) + ); + const newY = Math.max( + 0, + Math.min(videoNaturalHeight - rect.height, videoCoords.y) + ); + + newRects[selectedRectIndex] = { + ...rect, + x: newX, + y: newY, + }; + + return newRects; + }); + } + }; + + // 屏幕坐标转换为视频坐标 + const screenToVideoCoordinates = (screenX, screenY, screenW, screenH) => { + // 转换为视频内容坐标系(考虑当前的变换) + const videoX = (screenX - translateX) / scale; + const videoY = (screenY - translateY) / scale; + const videoW = screenW / scale; + const videoH = screenH / scale; + + // 计算视频显示区域 + const canvas = canvasRef.current; + if (!canvas) return null; + + const displayW = canvas.width; + const displayH = canvas.height; + const videoAR = videoNaturalWidth / videoNaturalHeight; + const displayAR = displayW / displayH; + + let drawW, drawH, offsetX, offsetY; + if (videoAR > displayAR) { + drawW = displayW; + drawH = displayW / videoAR; + offsetX = 0; + offsetY = (displayH - drawH) / 2; + } else { + drawH = displayH; + drawW = displayH * videoAR; + offsetX = (displayW - drawW) / 2; + offsetY = 0; + } + + // 转换为基于原始视频分辨率的绝对坐标 + const videoScaleX = videoNaturalWidth / drawW; + const videoScaleY = videoNaturalHeight / drawH; + + const absX = Math.round((videoX - offsetX) * videoScaleX); + const absY = Math.round((videoY - offsetY) * videoScaleY); + const absW = Math.round(videoW * videoScaleX); + const absH = Math.round(videoH * videoScaleY); + + // 限制在视频范围内 + const finalRect = { + x: Math.max(0, Math.min(videoNaturalWidth - 1, absX)), + y: Math.max(0, Math.min(videoNaturalHeight - 1, absY)), + width: Math.max(1, Math.min(videoNaturalWidth - absX, absW)), + height: Math.max(1, Math.min(videoNaturalHeight - absY, absH)), + }; + + return finalRect; + }; + + // 视频坐标转换为屏幕坐标 + const videoToScreenCoordinates = (videoX, videoY, videoW, videoH) => { + const canvas = canvasRef.current; + if (!canvas) return null; + + const displayW = canvas.width; + const displayH = canvas.height; + const videoAR = videoNaturalWidth / videoNaturalHeight; + const displayAR = displayW / displayH; + + let drawW, drawH, offsetX, offsetY; + if (videoAR > displayAR) { + drawW = displayW; + drawH = displayW / videoAR; + offsetX = 0; + offsetY = (displayH - drawH) / 2; + } else { + drawH = displayH; + drawW = displayH * videoAR; + offsetX = (displayW - drawW) / 2; + offsetY = 0; + } + + // 将视频坐标转换为显示坐标 + const displayScaleX = drawW / videoNaturalWidth; + const displayScaleY = drawH / videoNaturalHeight; + + const displayX = offsetX + videoX * displayScaleX; + const displayY = offsetY + videoY * displayScaleY; + const displayWidth = videoW * displayScaleX; + const displayHeight = videoH * displayScaleY; + + // 应用当前的缩放和平移变换 + const screenX = displayX * scale + translateX; + const screenY = displayY * scale + translateY; + const screenW = displayWidth * scale; + const screenH = displayHeight * scale; + + return { + x: screenX, + y: screenY, + width: screenW, + height: screenH, + }; + }; + + // 输出所有矩形数据到控制台 + const logRectangleData = () => { + console.log( + "当前矩形列表:", + rectangles.map((rect, index) => ({ + index, + id: rect.id, + leftTop: { x: rect.x, y: rect.y }, + rightBottom: { x: rect.x + rect.width, y: rect.y + rect.height }, + width: rect.width, + height: rect.height, + })) + ); + }; + + // 检查点击是否在矩形内 + const findRectangleAtPoint = (mouseX, mouseY) => { + if (!videoNaturalWidth || !videoNaturalHeight) return -1; + + const canvas = canvasRef.current; + if (!canvas) return -1; + + // 计算视频显示区域 + const displayW = canvas.width; + const displayH = canvas.height; + const videoAR = videoNaturalWidth / videoNaturalHeight; + const displayAR = displayW / displayH; + + let drawW, drawH, offsetX, offsetY; + if (videoAR > displayAR) { + drawW = displayW; + drawH = displayW / videoAR; + offsetX = 0; + offsetY = (displayH - drawH) / 2; + } else { + drawH = displayH; + drawW = displayH * videoAR; + offsetX = (displayW - drawW) / 2; + offsetY = 0; + } + + // 从后往前检查(优先选择最上层的矩形) + for (let i = rectangles.length - 1; i >= 0; i--) { + const rect = rectangles[i]; + + // 将绝对坐标转换为显示坐标 + const displayScaleX = drawW / videoNaturalWidth; + const displayScaleY = drawH / videoNaturalHeight; + + const displayX = offsetX + rect.x * displayScaleX; + const displayY = offsetY + rect.y * displayScaleY; + const displayW_rect = rect.width * displayScaleX; + const displayH_rect = rect.height * displayScaleY; + + // 转换鼠标坐标到视频显示坐标系 + const videoMouseX = (mouseX - translateX) / scale; + const videoMouseY = (mouseY - translateY) / scale; + + // 检查是否在矩形内 + if ( + videoMouseX >= displayX && + videoMouseX <= displayX + displayW_rect && + videoMouseY >= displayY && + videoMouseY <= displayY + displayH_rect + ) { + return i; + } + } + + return -1; + }; + + // 重新绘制所有矩形 + const redrawAllRectangles = () => { + const canvas = canvasRef.current; + if (!canvas) { + console.log("redrawAllRectangles: canvas不存在"); + return; + } + + const ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // 如果视频没有加载完成,直接返回 + if (!videoNaturalWidth || !videoNaturalHeight) { + console.log("redrawAllRectangles: 视频尺寸未准备好", { + videoNaturalWidth, + videoNaturalHeight, + }); + return; + } + + // 如果没有矩形框数据且没有正在绘制的预览矩形,也记录一下 + if ((!rectangles || rectangles.length === 0) && !currentDrawingRect) { + console.log("redrawAllRectangles: 没有矩形框数据且没有预览矩形"); + return; + } + + // 计算视频显示区域 + const displayW = canvas.width; + const displayH = canvas.height; + const videoAR = videoNaturalWidth / videoNaturalHeight; + const displayAR = displayW / displayH; + + let drawW, drawH, offsetX, offsetY; + if (videoAR > displayAR) { + drawW = displayW; + drawH = displayW / videoAR; + offsetX = 0; + offsetY = (displayH - drawH) / 2; + } else { + drawH = displayH; + drawW = displayH * videoAR; + offsetX = (displayW - drawW) / 2; + offsetY = 0; + } + + ctx.save(); + ctx.translate(translateX, translateY); + ctx.scale(scale, scale); + + // 绘制所有已保存的矩形 + if (rectangles && rectangles.length > 0) { + rectangles.forEach((rect, index) => { + // 将绝对坐标转换为显示坐标(在变换空间中) + const displayScaleX = drawW / videoNaturalWidth; + const displayScaleY = drawH / videoNaturalHeight; + + const displayX = offsetX + rect.x * displayScaleX; + const displayY = offsetY + rect.y * displayScaleY; + const displayW_rect = rect.width * displayScaleX; + const displayH_rect = rect.height * displayScaleY; + + // 检查是否为选中的标靶 + const isSelected = + selectedTargetId && + rect.id && + rect.id.toString() === selectedTargetId.toString(); + + // 设置矩形样式 - 根据不同状态设置不同颜色和样式 + if (index === selectedRectIndex && isDraggingRect) { + ctx.strokeStyle = "lime"; // 拖拽时显示为绿色 + ctx.lineWidth = 2 / scale; + } else if (isSelected) { + ctx.strokeStyle = "lime"; // 选中状态显示为lime绿色 + ctx.lineWidth = 2 / scale; // 选中时线条更粗 + ctx.setLineDash([]); // 实线 + } else { + ctx.strokeStyle = "blue"; // 正常状态为蓝色 + ctx.lineWidth = 1 / scale; + ctx.setLineDash([]); // 实线 + } + + ctx.strokeRect(displayX, displayY, displayW_rect, displayH_rect); + + // 显示矩形序号 + ctx.fillStyle = + index === selectedRectIndex && isDraggingRect + ? "lime" + : isSelected + ? "lime" + : "blue"; + ctx.font = `${12 / scale}px Arial`; + // ctx.fillText(`#${index + 1}`, displayX + 5 / scale, displayY + 15 / scale); + }); + } + + // 绘制当前正在绘制的矩形预览 + if (currentDrawingRect) { + const displayScaleX = drawW / videoNaturalWidth; + const displayScaleY = drawH / videoNaturalHeight; + + const displayX = offsetX + currentDrawingRect.x * displayScaleX; + const displayY = offsetY + currentDrawingRect.y * displayScaleY; + const displayW_rect = currentDrawingRect.width * displayScaleX; + const displayH_rect = currentDrawingRect.height * displayScaleY; + + ctx.strokeStyle = "cyan"; + ctx.lineWidth = 2 / scale; + ctx.setLineDash([6, 4]); // 预览时使用虚线 + ctx.strokeRect(displayX, displayY, displayW_rect, displayH_rect); + } + + ctx.restore(); + }; // 更新鼠标位置显示 + const updateMousePosition = (mouseX, mouseY) => { + // 计算鼠标在原始视频坐标系中的位置 + const videoX = (mouseX - translateX) / scale; + const videoY = (mouseY - translateY) / scale; + + // 转换为绝对像素坐标 + const canvas = canvasRef.current; + if (!canvas) return; + + const displayW = canvas.width; + const displayH = canvas.height; + const videoAR = videoNaturalWidth / videoNaturalHeight; + const displayAR = displayW / displayH; + + let drawW, drawH, offsetX, offsetY; + if (videoAR > displayAR) { + drawW = displayW; + drawH = displayW / videoAR; + offsetX = 0; + offsetY = (displayH - drawH) / 2; + } else { + drawH = displayH; + drawW = displayH * videoAR; + offsetX = (displayW - drawW) / 2; + offsetY = 0; + } + + const videoScaleX = videoNaturalWidth / drawW; + const videoScaleY = videoNaturalHeight / drawH; + const absMouseX = Math.round((videoX - offsetX) * videoScaleX); + const absMouseY = Math.round((videoY - offsetY) * videoScaleY); + + // 检查是否在视频区域内 + if ( + absMouseX >= 0 && + absMouseX < videoNaturalWidth && + absMouseY >= 0 && + absMouseY < videoNaturalHeight + ) { + setMousePos({ x: absMouseX, y: absMouseY }); + } + }; + + // 重置视图 + const handleReset = () => { + setScale(1.0); + setTranslateX(0); + setTranslateY(0); + // 不清除选择框,保留 selectionRect 和 rectInfo + }; + + // 保存矩形信息 + const handleSave = useCallback(async () => { + // 防止重复保存 + if (isSaving) { + console.log("正在保存中,忽略重复请求"); + return; + } + + console.log("=== 保存矩形信息 ==="); + console.log("矩形总数:", rectangles.length); + + if (rectangles.length === 0) { + console.log("没有创建任何矩形"); + return; + } + + setIsSaving(true); + + try { + // 组装指定格式的数据 + const targets = {}; + console.log(rectangles, "当前矩形数据"); + + rectangles.forEach((rect, index) => { + targets[index.toString()] = { + info: { + rectangle_area: { + x: rect.x, + y: rect.y, + w: rect.width, + h: rect.height, + }, + threshold: { + binary: rect.binaryThreshold || 120, + gauss: rect.gaussianBlurThreshold || 1, + gradient: rect.gradientThreshold || 100, + anchor: rect.anchorThreshold || 80, + }, + radius: rect.radius || 40.0, + id: index, + desc: rect.name || `${index}_target`, + base: rect.isReferencePoint || false, + }, + perspective: [ + [1.0, 0, 0], + [0, 1.0, 0], + [0, 0, 1.0], + ], + }; + }); + + const outputData = { + _from: "setup", + cmd: "setPoints", + values: { + targets: targets, + }, + }; + + console.log("格式化数据:"); + + // 手动序列化以保持浮点数格式 + const jsonString = JSON.stringify(outputData, null, 2).replace( + /"perspective":\s*\[\s*\[\s*1,\s*0,\s*0\s*\],\s*\[\s*0,\s*1,\s*0\s*\],\s*\[\s*0,\s*0,\s*1\s*\]\s*\]/g, + '"perspective": [\n [1.0, 0, 0],\n [0, 1.0, 0],\n [0, 0, 1.0]\n ]' + ); + + if (isConnected) { + const success = sendMessage(jsonString); + + if (success) { + console.log("数据已发送到服务器"); + + // 保存成功后刷新标靶列表数据 + setTimeout(() => { + refreshTargets(); + }, 500); // 延迟500ms确保服务器处理完成 + + // 清除选中状态 + if (onClearSelection) { + onClearSelection(); + } + } else { + console.error("发送数据失败"); + } + } else { + console.error("WebSocket未连接,无法发送数据"); + } + } catch (error) { + console.error("保存过程中出现错误:", error); + } finally { + // 延迟重置保存状态,确保不会立即被重复触发 + setTimeout(() => { + setIsSaving(false); + }, 1000); + } + }, [rectangles, isConnected, sendMessage, refreshTargets, onClearSelection, isSaving]); + + // 全局滚轮事件处理,防止alt+滚轮触发页面滚动 + useEffect(() => { + const handleGlobalWheel = (e) => { + if (e.altKey) { + const container = containerRef.current; + // 检查事件目标是否在摄像头容器内 + if (container && container.contains(e.target)) { + // 如果在容器内,不拦截,让容器处理器处理 + return; + } + + // 只有在容器外才拦截 + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + return false; + } + }; + + // 在document上添加监听器 + document.addEventListener("wheel", handleGlobalWheel, { passive: false }); + + return () => { + document.removeEventListener("wheel", handleGlobalWheel); + }; + }, []); + + // 应用变换效果 + useEffect(() => { + applyTransform(); + }, [scale, translateX, translateY]); + + // 监听视频尺寸变化,确保重新绘制 + useEffect(() => { + if (videoNaturalWidth && videoNaturalHeight) { + console.log("视频尺寸已更新,重新绘制矩形框"); + redrawAllRectangles(); + } + }, [videoNaturalWidth, videoNaturalHeight]); + + // 监听矩形列表变化,自动重绘 + useEffect(() => { + console.log("矩形列表发生变化,重新绘制:", rectangles); + // 使用requestAnimationFrame来优化重绘性能 + const rafId = requestAnimationFrame(() => { + redrawAllRectangles(); + }); + + return () => cancelAnimationFrame(rafId); + }, [rectangles]); + + // 强制刷新矩形框的函数 + const forceRefreshRectangles = useCallback(() => { + console.log("强制刷新矩形框"); + redrawAllRectangles(); + }, []); + + // 从标靶数据初始化矩形框 + useEffect(() => { + console.log("targets 或 loading 状态变化:", { + targets, + loading, + targetsLength: targets?.length, + }); + + if (!loading && targets && targets.length > 0) { + console.log("从标靶数据初始化矩形框:", targets); + + const initialRectangles = targets + .map((target) => { + const rectangleArea = target.rectangleArea; + console.log("处理标靶:", target.id, "矩形区域:", rectangleArea); + if ( + rectangleArea && + rectangleArea.x !== undefined && + rectangleArea.y !== undefined + ) { + return { + id: target.id, + key: target.key, + x: rectangleArea.x, + y: rectangleArea.y, + width: rectangleArea.w || rectangleArea.width || 100, + height: rectangleArea.h || rectangleArea.height || 100, + // 保留所有标靶属性,确保拖拽后不会丢失 + name: target.name, + radius: target.radius, + isReferencePoint: target.isReferencePoint, + gradientThreshold: target.gradientThreshold, + anchorThreshold: target.anchorThreshold, + gaussianBlurThreshold: target.gaussianBlurThreshold, + binaryThreshold: target.binaryThreshold, + hasAdvancedConfig: target.hasAdvancedConfig, + }; + } + return null; + }) + .filter((rect) => rect !== null); // 过滤掉空值 + + console.log("生成的矩形框数据:", initialRectangles); + console.log("当前矩形框数据:", rectangles); + console.log( + "标靶数据详情:", + targets.map((t) => ({ id: t.id, rectangleArea: t.rectangleArea })) + ); + + // 总是根据targets数据更新rectangles,确保数据同步 + console.log("强制更新矩形框数据以确保与targets同步"); + setRectangles(initialRectangles); + console.log("已从标靶数据强制更新矩形框:", initialRectangles); + + // 矩形框更新后,延迟一下确保重绘 + const timeoutId = setTimeout(() => { + redrawAllRectangles(); + }, 100); + return () => clearTimeout(timeoutId); + } else if (!loading && (!targets || targets.length === 0)) { + // 如果没有标靶数据,清空矩形框 + console.log( + "标靶数据为空,准备清空矩形框,当前矩形框数量:", + rectangles.length + ); + setRectangles([]); + console.log("标靶数据为空,已清空矩形框"); + } + }, [targets, loading]); // 只依赖targets和loading状态 + + // 专门监听rectangles变化并重绘 + useEffect(() => { + console.log("rectangles状态变化:", rectangles); + // 矩形状态改变时立即重绘 + if (videoNaturalWidth && videoNaturalHeight) { + // 如果矩形数组为空,强制清除画布 + if (rectangles.length === 0) { + const canvas = canvasRef.current; + if (canvas) { + const ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + console.log("强制清除画布,因为矩形数组为空"); + } + } else { + redrawAllRectangles(); + } + } + }, [rectangles, videoNaturalWidth, videoNaturalHeight]); + + // 监听拖拽状态变化,自动重绘 + useEffect(() => { + redrawAllRectangles(); + }, [isDraggingRect, selectedRectIndex]); + + // 确保在视频尺寸和矩形框数据都准备好时重绘 + useEffect(() => { + if (videoNaturalWidth && videoNaturalHeight && rectangles.length > 0) { + // 立即尝试重绘一次 + redrawAllRectangles(); + } + }, [videoNaturalWidth, videoNaturalHeight, rectangles.length]); + + // 监听选中标靶变化,重新绘制高亮效果 + useEffect(() => { + console.log("选中标靶ID变化:", selectedTargetId); + // 只有在有矩形框的时候才重绘,使用requestAnimationFrame优化性能 + if (rectangles.length > 0) { + const rafId = requestAnimationFrame(() => { + redrawAllRectangles(); + }); + + return () => cancelAnimationFrame(rafId); + } + }, [selectedTargetId]); + + // 容器滚轮事件处理 + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const handleContainerWheel = (e) => { + if (e.altKey) { + e.preventDefault(); + e.stopPropagation(); + + // 执行缩放逻辑 + const rect = container.getBoundingClientRect(); + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + const beforeX = (mouseX - translateX) / scale; + const beforeY = (mouseY - translateY) / scale; + + const delta = e.deltaY > 0 ? -scaleStep : scaleStep; + const newScale = Math.max( + minScale, + Math.min(maxScale, scale + delta) + ); + + const newTranslateX = mouseX - beforeX * newScale; + const newTranslateY = mouseY - beforeY * newScale; + + setScale(newScale); + setTranslateX(newTranslateX); + setTranslateY(newTranslateY); + } + }; + + // 使用原生addEventListener,更好的控制 + container.addEventListener("wheel", handleContainerWheel, { + passive: false, + }); + + return () => { + container.removeEventListener("wheel", handleContainerWheel); + }; + }, [scale, translateX, translateY, minScale, maxScale, scaleStep]); + + // 窗口大小变化时调整画布 + useEffect(() => { + const handleResize = () => { + setTimeout(resizeCanvas, 100); + }; + + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + return ( +
+ {/* 视频容器 */} +
+ {/* 视频内容 */} +
+ MJPEG 视频流 console.error("视频流加载失败")} + style={{ + position: "absolute", + left: 0, + top: 0, + width: "100%", + height: "100%", + objectFit: "contain", + userSelect: "none", + pointerEvents: "none", + }} + /> +
+ + {/* 绘制画布 */} + +
+ + {/* 重置按钮 */} + + + {/* 保存按钮 */} + + + {/* 信息显示 */} +
+
+ 分辨率: {videoNaturalWidth} × {videoNaturalHeight} +
+
缩放: {Math.round(scale * 100)}%
+
+ 鼠标: ({mousePos.x}, {mousePos.y}) +
+
+ 标靶数量: {rectangles.length}/{maxRectangles} +
+
+ + {/* 操作说明 */} +
+
Alt + 滚轮: 缩放
+
Alt + 拖拽: 平移
+
左键拖拽空白: 创建矩形
+
左键拖拽矩形: 移动矩形
+
+
+ ); +}; + +export default CameraView; diff --git a/client/src/sections/wuyuanbiaoba/components/RealtimeCharts.jsx b/client/src/sections/wuyuanbiaoba/components/RealtimeCharts.jsx new file mode 100644 index 0000000..6cc3386 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/RealtimeCharts.jsx @@ -0,0 +1,296 @@ +import React from 'react'; +import { Typography, Badge } from 'antd'; +import ReactECharts from 'echarts-for-react'; + +const { Title } = Typography; + +const RealtimeCharts = ({ tableData, lastUpdateTime }) => { + // 固定的设备颜色映射,确保颜色一致性 + const getDeviceColor = (deviceId) => { + const colorMap = { + 'DEV000': "#1890ff", // 蓝色 + 'DEV001': "#52c41a", // 绿色 + 'DEV002': "#faad14", // 橙色 + 'DEV003': "#f5222d", // 红色 + 'DEV004': "#722ed1", // 紫色 + 'DEV005': "#fa8c16", // 橙红色 + 'DEV006': "#13c2c2", // 青色 + 'DEV007': "#eb2f96", // 粉色 + 'DEV008': "#2f54eb", // 深蓝色 + 'DEV009': "#fa541c", // 火橙色 + }; + + // 如果设备ID在映射中,使用固定颜色 + if (colorMap[deviceId]) { + return colorMap[deviceId]; + } + + // 对于未预定义的设备,基于设备编号生成颜色 + const deviceNumber = deviceId.replace(/\D/g, ''); // 提取数字 + const colors = [ + "#1890ff", "#52c41a", "#faad14", "#f5222d", "#722ed1", + "#fa8c16", "#13c2c2", "#eb2f96", "#2f54eb", "#fa541c" + ]; + return colors[parseInt(deviceNumber) % colors.length]; + }; + + // 准备图表数据 + const prepareChartData = () => { + // 获取所有唯一的设备ID并排序,确保顺序一致 + const deviceIds = [...new Set(tableData.map((item) => item.deviceId))].sort(); + + // 获取所有时间点并排序 + const allTimes = [ + ...new Set(tableData.map((item) => item.updateTime)), + ].sort((a, b) => new Date(a) - new Date(b)); + const timeLabels = allTimes.map((time) => { + const date = new Date(time); + return date.toLocaleTimeString("zh-CN", { + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); + }); + + // 为每个设备准备数据 + const deviceData = deviceIds.map((deviceId) => { + const deviceItems = tableData.filter( + (item) => item.deviceId === deviceId + ); + + // 为每个时间点找到对应的X和Y值,如果没有则为null + const xData = allTimes.map((time) => { + const item = deviceItems.find((d) => d.updateTime === time); + return item ? parseFloat(item.xValue) : null; + }); + + const yData = allTimes.map((time) => { + const item = deviceItems.find((d) => d.updateTime === time); + return item ? parseFloat(item.yValue) : null; + }); + + // 使用固定的颜色映射 + const color = getDeviceColor(deviceId); + + return { + deviceId, + xData, + yData, + color, + }; + }); + + return { timeLabels, deviceData }; + }; + + const { timeLabels, deviceData } = prepareChartData(); + + // X值折线图配置 + const getXChartOption = () => ({ + title: { + text: "X轴位移数据", + left: "center", + textStyle: { + fontSize: 16, + fontWeight: "normal", + }, + }, + tooltip: { + trigger: "axis", + formatter: function (params) { + let result = `时间: ${params[0].axisValue}
`; + params.forEach((param) => { + if (param.value !== null) { + result += `${param.seriesName}: ${param.value} mm
`; + } + }); + return result; + }, + }, + legend: { + orient: "horizontal", + bottom: "5%", + textStyle: { + fontSize: 12, + }, + }, + grid: { + left: "3%", + right: "4%", + bottom: "15%", + top: "15%", + containLabel: true, + }, + xAxis: { + type: "category", + data: timeLabels, + axisLabel: { + rotate: 45, + fontSize: 11, + }, + }, + yAxis: { + type: "value", + name: "X值(mm)", + nameTextStyle: { + fontSize: 13, + }, + axisLabel: { + fontSize: 11, + }, + }, + series: deviceData.map((device) => ({ + name: device.deviceId, + type: "line", + data: device.xData, + smooth: false, + connectNulls: false, + lineStyle: { + color: device.color, + width: 2, + }, + itemStyle: { + color: device.color, + }, + symbol: "circle", + symbolSize: 4, + })), + }); + + // Y值折线图配置 + const getYChartOption = () => ({ + title: { + text: "Y轴位移数据", + left: "center", + textStyle: { + fontSize: 16, + fontWeight: "normal", + }, + }, + tooltip: { + trigger: "axis", + formatter: function (params) { + let result = `时间: ${params[0].axisValue}
`; + params.forEach((param) => { + if (param.value !== null) { + result += `${param.seriesName}: ${param.value} mm
`; + } + }); + return result; + }, + }, + legend: { + orient: "horizontal", + bottom: "5%", + textStyle: { + fontSize: 12, + }, + }, + grid: { + left: "3%", + right: "4%", + bottom: "15%", + top: "15%", + containLabel: true, + }, + xAxis: { + type: "category", + data: timeLabels, + axisLabel: { + rotate: 45, + fontSize: 11, + }, + }, + yAxis: { + type: "value", + name: "Y值(mm)", + nameTextStyle: { + fontSize: 13, + }, + axisLabel: { + fontSize: 11, + }, + }, + series: deviceData.map((device) => ({ + name: device.deviceId, + type: "line", + data: device.yData, + smooth: false, + connectNulls: false, + lineStyle: { + color: device.color, + width: 2, + }, + itemStyle: { + color: device.color, + }, + symbol: "circle", + symbolSize: 4, + })), + }); + + return ( +
+ + 实时数据图 + <Badge + status="processing" + text={`实时更新 - 最后更新: ${lastUpdateTime.toLocaleTimeString()}`} + style={{ marginLeft: "16px", fontSize: "12px" }} + /> + +
+ {/* X轴折线图 */} +
+ +
+ + {/* Y轴折线图 */} +
+ +
+
+
+ ); +}; + +export default RealtimeCharts; diff --git a/client/src/sections/wuyuanbiaoba/components/RealtimeDataTable.jsx b/client/src/sections/wuyuanbiaoba/components/RealtimeDataTable.jsx new file mode 100644 index 0000000..020f740 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/RealtimeDataTable.jsx @@ -0,0 +1,61 @@ +import React from "react"; +import { Table, Typography, Badge } from "antd"; + +const { Title } = Typography; + +const RealtimeDataTable = ({ realtimeData }) => { + const tableColumns = [ + { title: "设备编号", dataIndex: "deviceId", key: "deviceId" }, + { + title: "X值(mm)", + dataIndex: "xValue", + key: "xValue", + render: (text) => Number(text), + }, + { + title: "Y值(mm)", + dataIndex: "yValue", + key: "yValue", + render: (text) => Number(text), + }, + { title: "更新时间", dataIndex: "updateTime", key: "updateTime", width: 180 }, + ]; + + return ( +
+ + 最新数据 + <Badge + status="processing" + text={`${realtimeData.length} 个标靶数据`} + style={{ marginLeft: "16px", fontSize: "12px" }} + /> + +
+ + + + ); +}; + +export default RealtimeDataTable; diff --git a/client/src/sections/wuyuanbiaoba/components/TargetDetailModal.jsx b/client/src/sections/wuyuanbiaoba/components/TargetDetailModal.jsx new file mode 100644 index 0000000..d7a2b8d --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/TargetDetailModal.jsx @@ -0,0 +1,228 @@ +import React, { useState, useEffect } from "react"; +import { + Modal, + Form, + Input, + Checkbox, + Slider, + Select, + Button, + Popconfirm, +} from "antd"; +import { RightOutlined, DownOutlined } from "@ant-design/icons"; + +const { Option } = Select; + +const TargetDetailModal = ({ + visible, + mode, + targetData, + onOk, + onCancel, + onDelete, +}) => { + const [form] = Form.useForm(); + const [advancedConfig, setAdvancedConfig] = useState(false); + + // 高斯模糊阈值选项 + const gaussianBlurOptions = [1, 3, 5, 7, 9, 11]; + + useEffect(() => { + if (visible && targetData) { + // 编辑模式时填充表单数据 + form.setFieldsValue({ + name: targetData.name || "", + radius: targetData.radius || "", + isReferencePoint: targetData.isReferencePoint || false, + gradientThreshold: targetData.gradientThreshold || 100, + anchorThreshold: targetData.anchorThreshold || 80, + gaussianBlurThreshold: targetData.gaussianBlurThreshold || 3, + }); + setAdvancedConfig(targetData.hasAdvancedConfig || false); + } else if (visible && mode === "add") { + // 新增模式时设置默认值 + form.setFieldsValue({ + name: "", + radius: "", + isReferencePoint: false, + gradientThreshold: 100, + anchorThreshold: 80, + gaussianBlurThreshold: 3, + }); + setAdvancedConfig(false); + } + }, [visible, targetData, mode, form]); + + const handleOk = () => { + form + .validateFields() + .then((values) => { + const targetInfo = { + ...values, + hasAdvancedConfig: advancedConfig, + id: targetData?.id || Date.now().toString(), + }; + onOk(targetInfo); + form.resetFields(); + setAdvancedConfig(false); + }) + .catch((info) => { + console.log("表单验证失败:", info); + }); + }; + + const handleCancel = () => { + form.resetFields(); + setAdvancedConfig(false); + onCancel(); + }; + + const handleDelete = () => { + if (targetData) { + // 传递 key 或 id 给删除函数 + const targetKey = targetData.key || targetData.id; + onDelete(targetKey); + } + }; + + const handleAdvancedConfigChange = () => { + setAdvancedConfig(!advancedConfig); + }; + + return ( + + + + ), + , + , + ]} + > +
+ + + + + + + + + + + + + {advancedConfig && ( + <> + + 设为基准点 + + + + `${value}`, + }} + included={true} + /> + + + + `${value}`, + }} + included={true} + /> + + + + + + + )} + +
+ ); +}; + +export default TargetDetailModal; diff --git a/client/src/sections/wuyuanbiaoba/components/TargetList.jsx b/client/src/sections/wuyuanbiaoba/components/TargetList.jsx new file mode 100644 index 0000000..8e87ad0 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/TargetList.jsx @@ -0,0 +1,84 @@ +import React from "react"; +import { Table, Button } from "antd"; +import { EditOutlined } from "@ant-design/icons"; + +const TargetList = ({ + targetListData, + selectedTargetId, + onEditTarget, + onSelectTarget, + onClickClearAll, +}) => { + const targetColumns = [ + { + title: "标靶操作", + dataIndex: "name", + key: "name", + render: (text, record) => ( +
onSelectTarget(record)} + > + + {text} + + +
+ ), + }, + ]; + + return ( +
+
+ + + ); +}; + +export default TargetList; diff --git a/client/src/sections/wuyuanbiaoba/components/TemplateList.jsx b/client/src/sections/wuyuanbiaoba/components/TemplateList.jsx new file mode 100644 index 0000000..6f2e6ab --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/TemplateList.jsx @@ -0,0 +1,99 @@ +import React from "react"; +import { Table, Button, Radio } from "antd"; +import { EditOutlined } from "@ant-design/icons"; + +const TemplateList = ({ + tempListData, + selectedTemplate, + onTemplateSelect, + onAddTemplate, + onEditTemplate, +}) => { + const tempColumns = [ + { + title: "模板选择", + dataIndex: "name", + key: "name", + render: (text, record) => ( +
+
+ onTemplateSelect(record.key)} + style={{ marginRight: "12px" }} + /> + + {text} + + {record.imageUrl && ( + {`${text} + )} +
+ +
+ ), + }, + ]; + + return ( +
+
+ {tempListData.length < 3 && ( + + )} + + ); +}; + +export default TemplateList; diff --git a/client/src/sections/wuyuanbiaoba/components/TemplateModal.jsx b/client/src/sections/wuyuanbiaoba/components/TemplateModal.jsx new file mode 100644 index 0000000..3e01b48 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/TemplateModal.jsx @@ -0,0 +1,427 @@ +import React, { useState, useEffect } from "react"; +import { + Modal, + Form, + Input, + InputNumber, + Checkbox, + Slider, + Select, + Button, + Space, + message, + Popconfirm, + Upload, +} from "antd"; +import { DeleteOutlined, UploadOutlined } from "@ant-design/icons"; + +const { Option } = Select; + +const TemplateModal = ({ + visible, + mode, // 'add' | 'edit' + templateData, + onOk, + onCancel, + onDelete, + tempListData, +}) => { + const [form] = Form.useForm(); + const [isBaseline, setIsBaseline] = useState(false); + const [isPerspectiveCorrection, setIsPerspectiveCorrection] = + useState(false); + const [binaryThreshold, setBinaryThreshold] = useState(100); + const [gaussianBlur, setGaussianBlur] = useState(1); + const [physicalRadius, setPhysicalRadius] = useState(40.0); + const [gradientThresholdValue, setGradientThresholdValue] = useState(100); + const [anchorThresholdValue, setAnchorThresholdValue] = useState(80); + const [fileList, setFileList] = useState([]); + const [imageUrl, setImageUrl] = useState(""); + const [previewVisible, setPreviewVisible] = useState(false); + const [previewImage, setPreviewImage] = useState(""); + + // 当模态框打开时,设置表单初始值 + useEffect(() => { + if (visible) { + if (mode === "edit" && templateData) { + // 编辑模式:填充现有数据 + form.setFieldsValue({ + name: templateData.name, + gaussianBlur: templateData.gaussianBlur || 1, + physicalRadius: templateData.physicalRadius || 40.0, + gradientThresholdValue: + templateData.gradientThresholdValue || 100, + anchorThresholdValue: templateData.anchorThresholdValue || 80, + }); + setIsBaseline(templateData.isBaseline || false); + setIsPerspectiveCorrection( + templateData.isPerspectiveCorrection || false + ); + setBinaryThreshold(templateData.binaryThreshold || 100); + setGaussianBlur(templateData.gaussianBlur || 1); + setPhysicalRadius(templateData.physicalRadius || 40.0); + setGradientThresholdValue( + templateData.gradientThresholdValue || 100 + ); + setAnchorThresholdValue(templateData.anchorThresholdValue || 80); + + // 设置图片数据 + if (templateData.imageUrl) { + setImageUrl(templateData.imageUrl); + setFileList([ + { + uid: "-1", + name: templateData.name + ".jpg", + status: "done", + url: templateData.imageUrl, + }, + ]); + } else { + setImageUrl(""); + setFileList([]); + } + } else { + // 新增模式:设置默认值 + form.resetFields(); + setIsBaseline(false); + setIsPerspectiveCorrection(false); + setBinaryThreshold(100); + setGaussianBlur(1); + setPhysicalRadius(40.0); + setGradientThresholdValue(100); + setAnchorThresholdValue(80); + setImageUrl(""); + setFileList([]); + } + } + }, [visible, mode, templateData, form]); + + // 图片上传处理 + const handleUploadChange = ({ fileList: newFileList }) => { + setFileList(newFileList); + + // 如果文件列表为空(删除图片),清空imageUrl + if (newFileList.length === 0) { + setImageUrl(""); + } + }; + + const beforeUpload = (file) => { + const isJpgOrPng = + file.type === "image/jpeg" || file.type === "image/png"; + if (!isJpgOrPng) { + message.error("只能上传 JPG/PNG 格式的图片!"); + return false; + } + const isLt2M = file.size / 1024 / 1024 < 1; + if (!isLt2M) { + message.error("图片大小不能超过 1MB!"); + return false; + } + + // 读取文件并转换为base64 + const reader = new FileReader(); + reader.onload = (e) => { + const base64Data = e.target.result; + setImageUrl(base64Data); + + // 更新文件列表,添加预览URL + setFileList([ + { + uid: file.uid, + name: file.name, + status: "done", + url: base64Data, // 使用base64数据作为预览URL + originFileObj: file, + }, + ]); + }; + reader.readAsDataURL(file); + + return false; // 阻止默认上传行为 + }; + + // 处理图片预览 + const handlePreview = async (file) => { + if (!file.url && !file.preview) { + file.preview = await getBase64(file.originFileObj); + } + setPreviewImage(file.url || file.preview); + setPreviewVisible(true); + }; + + // 将文件转换为base64用于预览 + const getBase64 = (file) => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result); + reader.onerror = (error) => reject(error); + }); + + const handleOk = async () => { + try { + const values = await form.validateFields(); + + // 检查是否上传了图片 + if (!imageUrl) { + message.error("请上传标靶图片"); + return; + } + + // 检查模板数量限制(仅新增时) + if (mode === "add" && tempListData.length >= 3) { + message.error( + "已达到标靶模板数量上限(3个)!请删除未使用的模板后再新增。" + ); + return; + } + + const templateInfo = { + ...values, + isBaseline, + isPerspectiveCorrection, + binaryThreshold, + gaussianBlur, + physicalRadius, + gradientThresholdValue, + anchorThresholdValue, + imageUrl, + key: mode === "edit" ? templateData.key : Date.now().toString(), + id: mode === "edit" ? templateData.id : Date.now(), + }; + + onOk(templateInfo); + message.success(mode === "add" ? "新增模板成功!" : "编辑模板成功!"); + } catch (error) { + console.error("表单验证失败:", error); + } + }; + + const handleDelete = () => { + if (templateData) { + // 检查是否为第一个模板(内置模板) + if (templateData.key === 'builtin_1') { + message.warning("该模板为内置模板,不允许删除!"); + return; + } + onDelete(templateData); + message.success("删除模板成功!"); + } + }; + + const title = mode === "add" ? "新增标靶模板" : "编辑标靶模板"; + + return ( + <> + + + + ), + , + ].filter(Boolean)} + > +
+ + + + + + + {fileList.length >= 1 ? null : ( +
+ +
上传图片
+
+ )} +
+
+ 支持JPG、PNG格式,文件大小不超过1MB +
+
+ + + + setIsBaseline(e.target.checked)} + > + 设为基准点 + + + + + + + +
+ +
+ {gradientThresholdValue} +
+
+
+ + +
+ +
+ {anchorThresholdValue} +
+
+
+ + + + +
+ + {/* 图片预览Modal */} + setPreviewVisible(false)} + width={600} + centered + > + 预览 + + + ); +}; + +export default TemplateModal; diff --git a/client/src/sections/wuyuanbiaoba/components/index.js b/client/src/sections/wuyuanbiaoba/components/index.js new file mode 100644 index 0000000..072da63 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/components/index.js @@ -0,0 +1,7 @@ +export { default as CameraView } from './CameraView'; +export { default as TargetList } from './TargetList'; +export { default as TemplateList } from './TemplateList'; +export { default as RealtimeCharts } from './RealtimeCharts'; +export { default as RealtimeDataTable } from './RealtimeDataTable'; +export { default as TemplateModal } from './TemplateModal'; +export { default as TargetDetailModal } from './TargetDetailModal'; diff --git a/client/src/sections/wuyuanbiaoba/container/index.jsx b/client/src/sections/wuyuanbiaoba/container/index.jsx new file mode 100644 index 0000000..f46cea9 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/container/index.jsx @@ -0,0 +1,476 @@ +import React, { useState, useEffect } from "react"; +import { Tabs, Typography } from "antd"; +import { EyeOutlined } from "@ant-design/icons"; +import { + CameraView, + TargetList, + TemplateList, + RealtimeCharts, + RealtimeDataTable, + TemplateModal, + TargetDetailModal, +} from "../components"; +import { WebSocketProvider, useWebSocket, useWebSocketSubscription } from "../actions/websocket.jsx"; +import { useTemplateStorage } from "../hooks/useTemplateStorage.js"; +import { useTargetStorage } from "../hooks/useTargetStorage.js"; + +const { Title } = Typography; + +// 内部组件,使用WebSocket hook +const WuyuanbiaobaContent = () => { + const { isConnected, sendMessage } = useWebSocket(); + + // 订阅实时数据 + const realtimeDataSubscription = useWebSocketSubscription('dev', 'data'); + + const { + templates: tempListData, + loading: templatesLoading, + addTemplate, + updateTemplate, + deleteTemplate, + getTemplateByKey, + } = useTemplateStorage(); + + const { + targets: targetListData, + loading: targetsLoading, + addTarget, + updateTarget, + deleteTarget, + refreshTargets, + } = useTargetStorage(); + const [selectedTemplate, setSelectedTemplate] = useState(null); + const [tableData, setTableData] = useState([]); + const [realtimeData, setRealtimeData] = useState([]); + const [lastUpdateTime, setLastUpdateTime] = useState(new Date()); + + // 模板相关状态 + const [templateModalVisible, setTemplateModalVisible] = useState(false); + const [templateModalMode, setTemplateModalMode] = useState("add"); // 'add' | 'edit' + const [currentEditTemplate, setCurrentEditTemplate] = useState(null); + + // 标靶详情模态框相关状态 + const [targetDetailModalVisible, setTargetDetailModalVisible] = + useState(false); + const [targetDetailModalMode, setTargetDetailModalMode] = useState("edit"); // 'edit' + const [currentEditTarget, setCurrentEditTarget] = useState(null); + + // 添加选中标靶的状态 + const [selectedTargetId, setSelectedTargetId] = useState(null); + + // 处理实时数据并转换为表格格式 + const processRealtimeData = (data) => { + if (!data || !data.data || !Array.isArray(data.data)) { + return []; + } + + return data.data.map(item => ({ + key: item.pos, + deviceId: `target${Number(item.pos)+1}`, + xValue: item.x, + yValue: item.y, + updateTime: data.time || new Date().toLocaleString(), + })); + }; + + // 初始化数据 + useEffect(() => { + // 初始化空的实时数据表格 + setRealtimeData([]); + setTableData([]); + console.log('数据已初始化,等待实时数据...',import.meta.env.MODE); + + }, []); + + // 模板数据加载完成后,默认选中内置模板 + useEffect(() => { + if (!templatesLoading && tempListData.length > 0 && !selectedTemplate) { + // 查找内置模板 + const builtinTemplate = tempListData.find(template => template.key === 'builtin_1'); + if (builtinTemplate) { + setSelectedTemplate('builtin_1'); + console.log('默认选中内置模板:', builtinTemplate.name); + } else { + // 如果没有内置模板,选择第一个模板 + setSelectedTemplate(tempListData[0].key); + console.log('默认选中第一个模板:', tempListData[0].name); + } + } + }, [templatesLoading, tempListData, selectedTemplate]); + + // WebSocket连接成功后的处理 + useEffect(() => { + if (isConnected) { + console.log("WebSocket已连接,等待实时数据..."); + } else { + console.log("WebSocket未连接"); + } + }, [isConnected]); + + // 调试实时数据订阅状态 + useEffect(() => { + console.log('实时数据订阅状态:', { + hasData: !!realtimeDataSubscription.latest, + dataCount: realtimeDataSubscription.data?.length || 0, + latestTimestamp: realtimeDataSubscription.latest?.timestamp, + }); + }, [realtimeDataSubscription]); + + // 处理实时数据更新 + useEffect(() => { + if (realtimeDataSubscription.latest && realtimeDataSubscription.latest.values) { + const newRealtimeData = processRealtimeData(realtimeDataSubscription.latest.values); + + if (newRealtimeData.length > 0) { + console.log('收到实时数据:', newRealtimeData); + + // 更新最新数据表格 - 保留之前设备的数据,只更新有新数据的设备 + setRealtimeData(prevRealtimeData => { + // 创建设备ID到数据的映射 + const deviceDataMap = new Map(); + + // 先保留所有之前的设备数据 + prevRealtimeData.forEach(data => { + deviceDataMap.set(data.deviceId, data); + }); + + // 用新数据更新或添加设备 + newRealtimeData.forEach(data => { + deviceDataMap.set(data.deviceId, data); + }); + + // 转换回数组格式,按设备ID排序保持一致性 + return Array.from(deviceDataMap.values()).sort((a, b) => + a.deviceId.localeCompare(b.deviceId) + ); + }); + + // 更新历史数据(用于图表显示) + setTableData(prevData => { + const updatedData = [ + ...prevData, + ...newRealtimeData.map((point, index) => ({ + ...point, + key: `${Date.now()}_${point.key}`, // 为历史数据生成唯一key + })), + ]; + // 保持最多100个数据点 + return updatedData.slice(-100); + }); + + setLastUpdateTime(new Date()); + } + } + }, [realtimeDataSubscription.latest]); + + // 编辑标靶的处理函数 + const handleEditTarget = (target) => { + setCurrentEditTarget(target); + setTargetDetailModalMode("edit"); + setTargetDetailModalVisible(true); + console.log("编辑标靶:", target); + }; + + // 选中标靶的处理函数 + const handleSelectTarget = (target) => { + setSelectedTargetId(target.id); + console.log("选中标靶:", target); + }; + + // 清除选中标靶的处理函数 + const handleClearSelection = () => { + setSelectedTargetId(null); + console.log("清除标靶选中状态"); + }; + + // 处理矩形框点击事件 + const handleRectangleClick = (targetData) => { + console.log("矩形框被点击,打开标靶详情:", targetData); + setCurrentEditTarget(targetData); + setTargetDetailModalMode("edit"); + setTargetDetailModalVisible(true); + }; + + // 选择模板的处理函数 + const handleTemplateSelect = (templateKey) => { + setSelectedTemplate(templateKey); + console.log("选中模板:", templateKey); + }; + + // 添加新模板的处理函数 + const handleAddTemplate = () => { + setTemplateModalMode("add"); + setCurrentEditTemplate(null); + setTemplateModalVisible(true); + }; + + // 编辑模板的处理函数 + const handleEditTemplate = (template) => { + setTemplateModalMode("edit"); + setCurrentEditTemplate(template); + setTemplateModalVisible(true); + }; + + // 模态框确认处理函数 + const handleTemplateModalOk = (templateInfo) => { + console.log(templateInfo, "templateInfo"); + + let success = false; + if (templateModalMode === "add") { + success = addTemplate(templateInfo); + } else { + success = updateTemplate(templateInfo); + } + + if (success) { + setTemplateModalVisible(false); + } else { + console.error("模板操作失败"); + // 可以添加用户提示 + } + }; + + // 模态框取消处理函数 + const handleTemplateModalCancel = () => { + setTemplateModalVisible(false); + setCurrentEditTemplate(null); + }; + + // 删除模板处理函数 + const handleDeleteTemplate = (template) => { + const success = deleteTemplate(template.key); + + if (success) { + setTemplateModalVisible(false); + + // 如果删除的是当前选中的模板,则清空选中状态 + if (selectedTemplate === template.key) { + setSelectedTemplate(null); + } + } else { + console.error("删除模板失败"); + // 可以添加用户提示 + } + }; + + // 标靶详情模态框确认处理函数 + const handleTargetDetailModalOk = (targetInfo) => { + const success = updateTarget(targetInfo); + + if (success) { + setTargetDetailModalVisible(false); + setCurrentEditTarget(null); + console.log("更新标靶信息:", targetInfo); + } else { + console.error("更新标靶失败"); + // 可以添加用户提示 + } + }; + + // 标靶详情模态框取消处理函数 + const handleTargetDetailModalCancel = () => { + setTargetDetailModalVisible(false); + setCurrentEditTarget(null); + }; + + // 删除标靶处理函数 + const handleDeleteTarget = (targetKey) => { + console.log("开始删除标靶:", targetKey); + const success = deleteTarget(targetKey); + + if (success) { + setTargetDetailModalVisible(false); + setCurrentEditTarget(null); + // 如果删除的标靶是当前选中的,清除选中状态 + if (selectedTargetId === targetKey) { + setSelectedTargetId(null); + } + console.log("删除标靶成功:", targetKey); + + // 强制刷新标靶数据,确保UI立即更新 + setTimeout(() => { + refreshTargets(); + }, 500); + } else { + console.error("删除标靶失败"); + // 可以添加用户提示 + } + }; + // 标靶-一键清零 + const onClickClearAll = () => { + console.log("一键清零操作"); + sendMessage( + JSON.stringify({ + _from: "setup", + cmd: "clearZero", + values: {}, + }) + ); + }; + + // Tabs items 配置 + const tabItems = [ + { + key: "target-list", + label: "标靶列表", + children: ( + + ), + }, + { + key: "temp-list", + label: "模板列表", + children: ( + + ), + }, + ]; + + return ( +
+ {/* Header 区域 */} +
+ + 视觉位移计配置工具 + +
+ +
+
+ + {/* 中间区域 - 固定视口剩余高度 */} +
+ {/* Camera 区域 */} + + + {/* 右侧 Target List / Temp List 区域 */} +
+ +
+
+ + {/* 底部区域 - 在视口下方,需要滚动查看 */} +
+ {/* Charts 区域 */} + + + {/* Table 区域 */} + +
+ + {/* 模板编辑模态框 */} + + + {/* 标靶详情模态框 */} + +
+ ); +}; + +// 主组件,使用WebSocket Provider包装 +const Wuyuanbiaoba = () => { + return ( + + + + ); +}; + +export default Wuyuanbiaoba; diff --git a/client/src/sections/wuyuanbiaoba/hooks/useTargetStorage.js b/client/src/sections/wuyuanbiaoba/hooks/useTargetStorage.js new file mode 100644 index 0000000..6c7062b --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/hooks/useTargetStorage.js @@ -0,0 +1,344 @@ +import { useState, useEffect, useCallback } from 'react'; +import { useWebSocket, useWebSocketSubscription } from '../actions/websocket.jsx'; + +/** + * 标靶数据管理 Hook + * + * 功能: + * - 通过WebSocket获取标靶数据 + * - 提供标靶的增删改查功能 + * - 自动处理WebSocket通信 + * + * 使用方法: + * ```jsx + * const { + * targets, + * loading, + * addTarget, + * updateTarget, + * deleteTarget, + * refreshTargets + * } = useTargetStorage(); + * ``` + */ +export const useTargetStorage = () => { + const [targets, setTargets] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [isProcessing, setIsProcessing] = useState(false); + + const { isConnected, sendMessage } = useWebSocket(); + + // 监听标靶数据响应 + const { latest: targetDataResponse } = useWebSocketSubscription('dev', 'getPoints'); + + // 发送获取标靶数据的命令 + const fetchTargets = useCallback(() => { + if (!isConnected) { + console.warn('WebSocket未连接,无法获取标靶数据'); + return; + } + + setLoading(true); + setError(null); + + const success = sendMessage(JSON.stringify({ + "_from": "setup", + "cmd": "getPoints", + "values": {} + })); + + if (!success) { + setError('发送获取标靶数据命令失败'); + setLoading(false); + } + }, [isConnected, sendMessage]); + + // 处理接收到的标靶数据 + useEffect(() => { + if (targetDataResponse && targetDataResponse.values) { + try { + const responseValues = targetDataResponse.values; + console.log('收到标靶数据:', responseValues); + + // 检查是否为空对象 + if (!responseValues || Object.keys(responseValues).length === 0) { + console.log('服务端返回空的标靶数据'); + setTargets([]); + setError(null); + setLoading(false); + return; + } + + // 处理服务端返回的 targets 对象格式 + const targetsData = responseValues.targets || {}; + + // 将对象转换为数组格式,并转换为前端需要的格式 + const formattedTargets = Object.keys(targetsData).map((targetKey) => { + const targetInfo = targetsData[targetKey]; + const info = targetInfo.info || {}; + const rectangleArea = info.rectangle_area || {}; + const threshold = info.threshold || {}; + + return { + key: info.id !== undefined ? info.id.toString() : targetKey, + id: info.id !== undefined ? info.id.toString() : targetKey, + name: info.desc || `目标${targetKey}`, + radius: info.radius || 40.0, + isReferencePoint: info.base || false, + // 根据实际数据结构映射阈值 + gradientThreshold: threshold.gradient || 100, // 梯度阈值 + anchorThreshold: threshold.anchor || 80, // 锚点阈值 + gaussianBlurThreshold: threshold.gauss || 3, + binaryThreshold: threshold.binary || 120, // 保留二值化阈值 + hasAdvancedConfig: true, // 有配置数据的都认为是有高级配置 + // 保留原始服务端数据 + rectangleArea: rectangleArea, + perspective: targetInfo.perspective || null, + handlerInfo: targetInfo.handler_info || null, + }; + }); + + setTargets(formattedTargets); + setError(null); + console.log('解析到标靶数据:', formattedTargets); + } catch (err) { + console.error('处理标靶数据失败:', err); + setError('处理标靶数据失败'); + setTargets([]); // 出错时设置为空数组 + } finally { + setLoading(false); + } + } else if (targetDataResponse && !targetDataResponse.values) { + // 如果收到响应但没有values,可能是空响应 + console.log('收到空的标靶数据响应'); + setTargets([]); + setError(null); + setLoading(false); + } + }, [targetDataResponse]); + + // WebSocket连接建立后自动获取数据 + useEffect(() => { + if (isConnected) { + fetchTargets(); + } + }, [isConnected, fetchTargets]); + + // 通用的标靶数据处理纯函数 + const buildTargetsPayload = useCallback((targetsArray) => { + const targets = {}; + + targetsArray.forEach((target, index) => { + const rectangleArea = target.rectangleArea || {}; + targets[index.toString()] = { + info: { + rectangle_area: { + x: rectangleArea.x || 0, + y: rectangleArea.y || 0, + w: rectangleArea.w || rectangleArea.width || 100, + h: rectangleArea.h || rectangleArea.height || 100, + }, + threshold: { + binary: target.binaryThreshold || 120, + gauss: target.gaussianBlurThreshold || 1, + gradient: target.gradientThreshold || 100, + anchor: target.anchorThreshold || 80, + }, + radius: parseFloat(target.radius) || 40.0, + id: target.id || target.key, + desc: target.name || `${target.id || target.key}_target`, + base: target.isReferencePoint || false, + }, + perspective: target.perspective || [ + [1.0, 0, 0], + [0, 1.0, 0], + [0, 0, 1.0], + ], + }; + }); + + return { + _from: "setup", + cmd: "setPoints", + values: { + targets: targets, + }, + }; + }, []); + + // 通用的发送标靶数据函数 + const sendTargetsData = useCallback((outputData, operationType, targetIdentifier) => { + if (isProcessing) { + console.log(`${operationType}请求正在处理中,忽略重复请求`); + return false; + } + + setIsProcessing(true); + console.log(`准备发送的${operationType}数据:`, outputData); + + try { + // 发送更新后的标靶列表到服务端 + const jsonString = JSON.stringify(outputData, null, 2).replace( + /"perspective":\s*\[\s*\[\s*1,\s*0,\s*0\s*\],\s*\[\s*0,\s*1,\s*0\s*\],\s*\[\s*0,\s*0,\s*1\s*\]\s*\]/g, + '"perspective": [\n [1.0, 0, 0],\n [0, 1.0, 0],\n [0, 0, 1.0]\n ]' + ); + + const success = sendMessage(jsonString); + + if (success) { + console.log(`${operationType}标靶成功,已发送更新数据到服务端:`, targetIdentifier); + console.log('发送的数据:', outputData); + // 延迟重新获取数据,确保服务器处理完成 + setTimeout(() => { + console.log('开始重新获取标靶数据...'); + fetchTargets(); + setIsProcessing(false); + }, 1000); + return true; + } else { + console.error(`发送${operationType}数据到服务端失败`); + setIsProcessing(false); + return false; + } + } catch (error) { + console.error(`${operationType}数据处理失败:`, error); + setIsProcessing(false); + return false; + } + }, [sendMessage, fetchTargets, isProcessing]); + + // 添加标靶 + const addTarget = useCallback((targetInfo) => { + if (!isConnected) { + console.warn('WebSocket未连接,无法添加标靶'); + return false; + } + + try { + const success = sendMessage(JSON.stringify({ + "_from": "setup", + "cmd": "addPoint", + "values": targetInfo + })); + + if (success) { + // 本地更新(实际数据会通过WebSocket响应更新) + const newTarget = { + ...targetInfo, + key: targetInfo.id || Date.now().toString(), + id: targetInfo.id || Date.now().toString(), + }; + setTargets(prev => [...prev, newTarget]); + console.log('发送添加标靶命令成功'); + return true; + } + + return false; + } catch (error) { + console.error('添加标靶失败:', error); + return false; + } + }, [isConnected, sendMessage]); + + // 更新标靶 + const updateTarget = useCallback((targetInfo) => { + console.log('准备更新标靶:', targetInfo); + + if (!isConnected) { + console.warn('WebSocket未连接,无法更新标靶'); + return false; + } + + try { + // 先更新本地状态 + let updatedTargets = []; + setTargets(prev => { + console.log(prev, '更新标靶前的状态'); + updatedTargets = prev.map(target => + target.key === targetInfo.key || target.id === targetInfo.id + ? { ...target, ...targetInfo } + : target + ); + console.log(updatedTargets, '更新标靶后的状态'); + console.log('更新的标靶匹配:', prev.map(t => ({ + id: t.id, + key: t.key, + match: t.key === targetInfo.key || t.id === targetInfo.id, + isUpdated: t.key === targetInfo.key || t.id === targetInfo.id ? '是' : '否' + }))); + return updatedTargets; + }); + + // 使用通用函数构建payload并发送 + const outputData = buildTargetsPayload(updatedTargets); + return sendTargetsData(outputData, '更新', targetInfo.key || targetInfo.id); + + } catch (error) { + console.error('更新标靶失败:', error); + return false; + } + }, [isConnected, buildTargetsPayload, sendTargetsData]); + + // 删除标靶 + const deleteTarget = useCallback((targetKey) => { + console.log('准备删除标靶:', targetKey); + + if (!isConnected) { + console.warn('WebSocket未连接,无法删除标靶'); + return false; + } + + try { + // 先更新本地状态 + let updatedTargets = []; + setTargets(prev => { + console.log(prev, '删除标靶前的状态'); + updatedTargets = prev.filter(target => target.key !== targetKey && target.id !== targetKey); + console.log(updatedTargets, '删除标靶后的状态'); + console.log('删除的标靶ID匹配:', prev.map(t => ({ id: t.id, key: t.key, match: t.key === targetKey || t.id === targetKey }))); + return updatedTargets; + }); + + // 使用通用函数构建payload并发送 + const outputData = buildTargetsPayload(updatedTargets); + return sendTargetsData(outputData, '删除', targetKey); + + } catch (error) { + console.error('删除标靶失败:', error); + return false; + } + }, [isConnected, buildTargetsPayload, sendTargetsData]); + + // 根据key查找标靶 + const getTargetByKey = useCallback((key) => { + return targets.find(target => target.key === key || target.id === key); + }, [targets]); + + // 刷新标靶数据 + const refreshTargets = useCallback(() => { + fetchTargets(); + }, [fetchTargets]); + + // 清空标靶数据 + const clearTargets = useCallback(() => { + setTargets([]); + }, []); + + return { + targets, + loading, + error, + isProcessing, + addTarget, + updateTarget, + deleteTarget, + getTargetByKey, + refreshTargets, + clearTargets, + // WebSocket连接状态 + isConnected, + }; +}; + +export default useTargetStorage; diff --git a/client/src/sections/wuyuanbiaoba/hooks/useTemplateStorage.js b/client/src/sections/wuyuanbiaoba/hooks/useTemplateStorage.js new file mode 100644 index 0000000..ce91473 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/hooks/useTemplateStorage.js @@ -0,0 +1,250 @@ +import { useState, useEffect } from 'react'; + +// localStorage 存储键名 +const TEMPLATE_STORAGE_KEY = 'wuyuanbiaoba_templates'; + +// 将图片转换为base64的工具函数 +const convertImageToBase64 = (imagePath) => { + return new Promise((resolve, reject) => { + const img = new Image(); + img.crossOrigin = 'anonymous'; // 处理跨域问题 + + img.onload = () => { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + canvas.width = img.width; + canvas.height = img.height; + + ctx.drawImage(img, 0, 0); + + try { + const base64 = canvas.toDataURL('image/jpeg', 0.8); + resolve(base64); + } catch (error) { + reject(error); + } + }; + + img.onerror = () => { + reject(new Error(`Failed to load image: ${imagePath}`)); + }; + + img.src = imagePath; + }); +}; + +// 创建内置模板的函数 +const createBuiltinTemplate = async () => { + try { + // 标靶图片路径 + const imagePath = '/client/assets/img/wuyuanbiaoba_template_images/temp_target1.jpg'; + const imageBase64 = await convertImageToBase64(imagePath); + + return { + key: 'builtin_1', + name: 'template1', + isBaseline: false, + isPerspectiveCorrection: false, + binaryThreshold: 100, + gaussianBlur: 1, + physicalRadius: 40.0, + gradientThresholdValue: 100, + anchorThresholdValue: 80, + imageUrl: imageBase64, + id: 'builtin_1', + }; + } catch (error) { + console.error('创建内置模板失败:', error); + // 如果图片加载失败,返回不带图片的内置模板 + return { + key: 'builtin_1', + name: '模板1', + isBaseline: false, + isPerspectiveCorrection: false, + binaryThreshold: 100, + gaussianBlur: 1, + physicalRadius: 40.0, + gradientThresholdValue: 100, + anchorThresholdValue: 80, + imageUrl: "", + id: 'builtin_1', + }; + } +}; + +// localStorage 工具函数 +const saveTemplatesToStorage = (templates) => { + try { + localStorage.setItem(TEMPLATE_STORAGE_KEY, JSON.stringify(templates)); + return true; + } catch (error) { + console.error('保存模板数据到localStorage失败:', error); + return false; + } +}; + +const getTemplatesFromStorage = () => { + try { + const stored = localStorage.getItem(TEMPLATE_STORAGE_KEY); + return stored ? JSON.parse(stored) : null; + } catch (error) { + console.error('从localStorage读取模板数据失败:', error); + return null; + } +}; + +// 模板存储管理 Hook +export const useTemplateStorage = () => { + const [templates, setTemplates] = useState([]); + const [loading, setLoading] = useState(true); + + // 初始化加载模板数据 + useEffect(() => { + const loadTemplates = async () => { + const storedTemplates = getTemplatesFromStorage(); + + if (storedTemplates && storedTemplates.length > 0) { + // 如果localStorage中有数据,检查是否已有内置模板 + const hasBuiltinTemplate = storedTemplates.some(template => template.key === 'builtin_1'); + + if (!hasBuiltinTemplate) { + // 如果没有内置模板,添加内置模板 + try { + const builtinTemplate = await createBuiltinTemplate(); + const updatedTemplates = [builtinTemplate, ...storedTemplates]; + setTemplates(updatedTemplates); + saveTemplatesToStorage(updatedTemplates); + console.log('内置模板已添加到现有模板列表'); + } catch (error) { + console.error('添加内置模板失败:', error); + setTemplates(storedTemplates); + } + } else { + // 已有内置模板,直接使用现有数据 + setTemplates(storedTemplates); + } + } else { + // 如果localStorage中没有数据,只创建内置模板 + try { + const builtinTemplate = await createBuiltinTemplate(); + const allTemplates = [builtinTemplate]; + + setTemplates(allTemplates); + saveTemplatesToStorage(allTemplates); + console.log('已创建内置模板'); + } catch (error) { + console.error('创建内置模板失败:', error); + // 如果创建失败,创建空模板列表 + setTemplates([]); + saveTemplatesToStorage([]); + } + } + + setLoading(false); + }; + + loadTemplates(); + }, []); + + // 添加模板 + const addTemplate = (templateInfo) => { + const newTemplates = [...templates, templateInfo]; + setTemplates(newTemplates); + const saved = saveTemplatesToStorage(newTemplates); + + if (!saved) { + // 如果保存失败,回滚状态 + console.error('添加模板失败:无法保存到localStorage'); + return false; + } + + return true; + }; + + // 更新模板 + const updateTemplate = (templateInfo) => { + const updatedTemplates = templates.map((item) => + item.key === templateInfo.key ? templateInfo : item + ); + setTemplates(updatedTemplates); + const saved = saveTemplatesToStorage(updatedTemplates); + + if (!saved) { + // 如果保存失败,回滚状态 + console.error('更新模板失败:无法保存到localStorage'); + setTemplates(templates); // 回滚到原状态 + return false; + } + + return true; + }; + + // 删除模板 + const deleteTemplate = (templateKey) => { + const filteredTemplates = templates.filter((item) => item.key !== templateKey); + setTemplates(filteredTemplates); + const saved = saveTemplatesToStorage(filteredTemplates); + + if (!saved) { + // 如果保存失败,回滚状态 + console.error('删除模板失败:无法保存到localStorage'); + setTemplates(templates); // 回滚到原状态 + return false; + } + + return true; + }; + + // 根据key查找模板 + const getTemplateByKey = (key) => { + return templates.find(template => template.key === key); + }; + + // 清空所有模板 + const clearAllTemplates = () => { + setTemplates([]); + const saved = saveTemplatesToStorage([]); + + if (!saved) { + console.error('清空模板失败:无法保存到localStorage'); + return false; + } + + return true; + }; + + // 重置为默认模板 + const resetToDefaultTemplates = async () => { + try { + const builtinTemplate = await createBuiltinTemplate(); + const allTemplates = [builtinTemplate]; + + setTemplates(allTemplates); + const saved = saveTemplatesToStorage(allTemplates); + + if (!saved) { + console.error('重置模板失败:无法保存到localStorage'); + return false; + } + + return true; + } catch (error) { + console.error('重置模板失败:', error); + return false; + } + }; + + return { + templates, + loading, + addTemplate, + updateTemplate, + deleteTemplate, + getTemplateByKey, + clearAllTemplates, + resetToDefaultTemplates, + }; +}; + +export default useTemplateStorage; diff --git a/client/src/sections/wuyuanbiaoba/index.js b/client/src/sections/wuyuanbiaoba/index.js new file mode 100644 index 0000000..4019aca --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/index.js @@ -0,0 +1,7 @@ +import route from './router'; +import actions from './actions'; + +export default { + route: route, + actions: actions, +}; diff --git a/client/src/sections/wuyuanbiaoba/router.js b/client/src/sections/wuyuanbiaoba/router.js new file mode 100644 index 0000000..69fa842 --- /dev/null +++ b/client/src/sections/wuyuanbiaoba/router.js @@ -0,0 +1,10 @@ +import Wuyuanbiaoba from './container/index' + +export default { + type: 'outer', + route: { + key: 'wuyuanbiaoba', + path: "/wuyuanbiaoba", + component: Wuyuanbiaoba + } +}; diff --git a/client/src/utils/api.js b/client/src/utils/api.js new file mode 100644 index 0000000..5ed04e4 --- /dev/null +++ b/client/src/utils/api.js @@ -0,0 +1,6 @@ +export const apiTable = { + login: "/login", + logout: "/logout", + + qiniuToken: '/qiniu/token' +} diff --git a/client/src/utils/index.js b/client/src/utils/index.js new file mode 100644 index 0000000..cd43037 --- /dev/null +++ b/client/src/utils/index.js @@ -0,0 +1,22 @@ +import { apiTable } from './api' + +import { request, basicAction, basicReducer } from '@peace/react_client' +import { message } from 'antd' + +const apiRequest = new request({ + proxy: '/_api', + userKey: 'user', // session 中的用户key 值 用于拼接 token + message: message, // 全局提示组件 + interceptor: (res, err) => { // 拦截器 + if (err) { + if (err?.status === 401) { + window.location.replace('/signin'); + sessionStorage.clear() + } + return err + } + return res + } +}) + +export { basicAction, basicReducer, apiTable, apiRequest } diff --git a/client/src/utils/parseProcessData.js b/client/src/utils/parseProcessData.js new file mode 100644 index 0000000..1d5279d --- /dev/null +++ b/client/src/utils/parseProcessData.js @@ -0,0 +1,103 @@ +'use strict'; + +/** 解析项企流程表单的字段值 */ + +const schemaRecursionObj = (obj, target, schemaPath) => { + let schemaPath_ = JSON.parse(JSON.stringify(schemaPath)) + if (obj.properties) { + for (let prKey in obj.properties) { + if (obj.properties[prKey].title == target) { + schemaPath_.push({ + prKey, + ...obj.properties[prKey] + }) + return schemaPath_ + } + const hasProperties = obj.properties[prKey].properties + const isGroup = obj.properties[prKey].type == 'array' && obj.properties[prKey].title == '分组' + if (hasProperties || isGroup) { + schemaPath_.push({ + prKey, + ...obj.properties[prKey], + isGroup: isGroup, + }) + schemaPath_ = schemaRecursionObj( + isGroup ? + obj.properties[prKey].items + : obj.properties[prKey], + target, + schemaPath_ + ) + if (!schemaPath_) { + return [] + } + if (schemaPath_.length > schemaPath.length) { + return schemaPath_ + } + } + } + } else { + return schemaPath_ + } +} + +const dataRecursionObj = (dataObj, index, needData, lastKeyObj, nd) => { + const keyObj = needData[nd].schemaPath[index] + if (dataObj.hasOwnProperty(keyObj.prKey)) { + if (lastKeyObj.prKey == keyObj.prKey) { + let gotValue = dataObj[keyObj.prKey] + if (keyObj.enum && !needData[nd].fromDataSource) { + let vIndex = keyObj.enum.findIndex(ke => ke == gotValue) + gotValue = keyObj.enumNames[vIndex] + } + return gotValue + } else { + if (keyObj.isGroup) { + debugger + for (let item of dataObj[keyObj.prKey]) { + const gotValue = dataRecursionObj(item, index + 1, needData, lastKeyObj, nd) + if (gotValue) { + return gotValue + } + } + } else { + return dataRecursionObj(dataObj[keyObj.prKey], index + 1, needData, lastKeyObj, nd) + } + } + } +} + +const getData = (applyDetail, needData) => { + for (let nd in needData) { + if (needData[nd].noProcess) { + continue + } + needData[nd].schemaPath = schemaRecursionObj(applyDetail.formSchema.jsonSchema, needData[nd]['keyWord'], []) + if (needData[nd].schemaPath && needData[nd].schemaPath.length) { + const lastKeyObj = needData[nd].schemaPath[ + needData[nd].schemaPath.length - 1 + ] + needData[nd].value = dataRecursionObj(applyDetail.formData, 0, needData, lastKeyObj, nd) + } else { + // 记录错误 关键数据没找到 + } + } +} + +export const parseProcessData = ( + applyDetail, + /* + applyDetail = { + formSchema: r?.formData?.workflowProcessVersion?.workflowProcessForm?.formSchema, + formData: r?.formData?.formData + } + */ + pomsNeedData = { + title: { + keyWord: '标题', + }, + }) => { + let needData = JSON.parse(JSON.stringify(pomsNeedData)) + getData(applyDetail, needData) + return needData +} diff --git a/config.cjs b/config.cjs new file mode 100644 index 0000000..9a40d88 --- /dev/null +++ b/config.cjs @@ -0,0 +1,32 @@ +const path = require('path') + +module.exports = { + env: process.env.NODE_ENV || 'development', // 运行环境 development | production + port: process.env.PORT || 5000, // 服务端口 + title: 'FreeSun', // 网站标题 + favicon: '/client/assets/favicon.ico', // 网站图标 + scripts: [// 需引入的静态脚本文件 + '/client/assets/script/peace.js' + ], + proxy: [{ // 代理配置 + path: '/_api', + target: process.env.API, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/_api/, ""), + logs: process.env.NODE_ENV == 'development', // 是否打印代理日志 + }], + vite: { // vite 配置 + envPrefix: 'FS_', // 传递到前端页面 window.env 的环境变量的前缀 + resolve: { + alias: { // 别名 + '@u': path.join(__dirname, './client/src/utils'), + '@comps': path.join(__dirname, './client/src/components'), + '@assets': path.join(__dirname, './client/assets'), + } + }, + }, + //--- + xunruan: { // 讯软服务配置 + host: 'http://222.186.227.196:31935' + }, +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..4038e13 --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + + + + + + <!--app-title--> + + + + + + + +
+ + + + \ No newline at end of file diff --git a/jenkinsfile b/jenkinsfile new file mode 100644 index 0000000..787828f --- /dev/null +++ b/jenkinsfile @@ -0,0 +1,22 @@ +podTemplate { + node('pod-templ-jenkins-slave-common') { + + env.IMAGE_NAME = "${IOT_IMAGES_REGISTRY}/${IOT}/${JOB_NAME}" + env.IMAGE_NAME_SHORT = "${IOT}/${JOB_NAME}" + env.SVN_Add = "${SVN_ADDRESS}/ 这儿这儿这儿写完整 SVN 地址" + + stage('Run shell') { + checkout([$class: 'SubversionSCM', filterChangelog: false, locations: [[cancelProcessOnExternalsFail: true, credentialsId: 'svn-build', depthOption: 'infinity', ignoreExternalsOption: true, local: '.', remote: "${SVN_Add}"]], quietOperation: true, workspaceUpdater: [$class: 'UpdateUpdater']]) + + container('image-builder') { + sh''' + find . -depth -name '.svn' -type d -exec rm -rf {} + + /kaniko/executor --context=${BUILD_WORKSPACE} --dockerfile=./Dockerfile --destination=${IMAGE_NAME}:${IMAGE_VERSION} --cache=false --cleanup + ''' + } + + buildName "${IMAGE_NAME_SHORT}:${IMAGE_VERSION}" + buildDescription "${IMAGE_NAME}:${IMAGE_VERSION}" + } + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aabb1f7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5026 @@ +{ + "name": "wuyuanbiaoba-web", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "wuyuanbiaoba-web", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@koa/multer": "^3.0.2", + "@peace/react_client": "^5.0.1", + "fs-extra": "^11.2.0", + "ws": "^8.18.3" + }, + "devDependencies": { + "@ant-design/icons": "^5.4.0", + "antd": "^5.19.0", + "echarts": "^5.6.0", + "echarts-for-react": "^3.0.2", + "react": "18.x", + "react-dom": "18.x", + "react-redux": "^9.1.2", + "react-router-dom": "^6.26.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.24.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/cssinjs/-/cssinjs-1.24.0.tgz", + "integrity": "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha1-u7/2iXj+/b5ozLUzvIy+HRr7VBM=", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@koa/multer": { + "version": "3.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@koa/multer/-/multer-3.1.0.tgz", + "integrity": "sha512-ETf4OLpOew9XE9lyU+5HIqk3TCmdGAw9pUXgxzrlYip+PkxLGoU4meiVTxiW4B6lxdBNijb3DFQ7M2woLcDL1g==", + "license": "MIT", + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "multer": "*" + } + }, + "node_modules/@koa/router": { + "version": "13.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@koa/router/-/router-13.1.1.tgz", + "integrity": "sha512-JQEuMANYRVHs7lm7KY9PCIjkgJk73h4m4J+g2mkw2Vo1ugPZ17UJVqEH8F+HeAdjKz5do1OaLe7ArDz+z308gw==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.1", + "http-errors": "^2.0.0", + "koa-compose": "^4.1.0", + "path-to-regexp": "^6.3.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", + "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@peace/react_client": { + "version": "5.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@peace/react_client/-/react_client-5.0.2.tgz", + "integrity": "sha512-dPJkCEGusuxZoEtWfCtUOGYMniDo1NvCb/sa0dYAakVzV8VMYBPlAUjvGRxpR6nUvFnqZ9XaWpx8BmT87WfKJA==", + "license": "ISC", + "dependencies": { + "@koa/router": "^13.1.0", + "@reduxjs/toolkit": "^2.3.0", + "@vitejs/plugin-react": "^4.3.3", + "ansis": "^3.5.2", + "common-bin": "^3.0.1", + "figlet": "^1.8.0", + "fs-extra": "^11.2.0", + "koa": "^2.15.3", + "koa-connect": "^2.1.0", + "koa-proxies": "^0.12.4", + "less": "^4.2.0", + "loading-cli": "^1.1.2", + "sirv": "^3.0.0", + "superagent": "^10.1.1", + "vite": "^5.4.11" + }, + "bin": { + "peace-rc": "bin/peace.js" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/qrcode/-/qrcode-1.0.0.tgz", + "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rc-component/trigger/-/trigger-2.3.0.tgz", + "integrity": "sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.8.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@reduxjs/toolkit/-/toolkit-2.8.2.tgz", + "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@remix-run/router/-/router-1.23.0.tgz", + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.3.tgz", + "integrity": "sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.3.tgz", + "integrity": "sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.3.tgz", + "integrity": "sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.3.tgz", + "integrity": "sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.3.tgz", + "integrity": "sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.3.tgz", + "integrity": "sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.3.tgz", + "integrity": "sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.3.tgz", + "integrity": "sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.3.tgz", + "integrity": "sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.3.tgz", + "integrity": "sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.3.tgz", + "integrity": "sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.3.tgz", + "integrity": "sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.3.tgz", + "integrity": "sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.3.tgz", + "integrity": "sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.3.tgz", + "integrity": "sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz", + "integrity": "sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz", + "integrity": "sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.3.tgz", + "integrity": "sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.3.tgz", + "integrity": "sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.3.tgz", + "integrity": "sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/antd": { + "version": "5.27.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/antd/-/antd-5.27.0.tgz", + "integrity": "sha512-o54dmpooLOc08RSGCkeEQBYAGPxUSmnhmYJKCNTHH46vzjOVxdteu+wPTRVkRbAkDTbs2VcNr5VL7Lu67rPIiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.2.1", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.3.0", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.34.0", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.3.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.0", + "rc-image": "~7.12.0", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.4", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.8", + "rc-slider": "~11.1.8", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.51.1", + "rc-tabs": "~15.7.0", + "rc-textarea": "~1.10.2", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.9.2", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=", + "license": "MIT", + "peer": true + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "license": "MIT" + }, + "node_modules/browserslist": { + "version": "4.25.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/browserslist/-/browserslist-4.25.2.tgz", + "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001733", + "electron-to-chromium": "^1.5.199", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U=", + "license": "MIT", + "peer": true + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "peer": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "license": "MIT", + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha1-lygHKpVPgFIoIlpt7qazhGHhvVo=", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001735", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", + "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha1-/t/F8TYEXiOYwEEO5EH5VwRkHhI=", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U=", + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "license": "MIT" + }, + "node_modules/colors-cli": { + "version": "1.0.33", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/colors-cli/-/colors-cli-1.0.33.tgz", + "integrity": "sha512-PWGsmoJFdOB0t+BeHgmtuoRZUQucOLl5ii81NBzOOGVxlgE04muFNHlR5j8i8MKbOPELBl3243AI6lGBTj5ICQ==", + "license": "MIT", + "bin": { + "colors": "bin/colors" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/common-bin": { + "version": "3.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/common-bin/-/common-bin-3.0.1.tgz", + "integrity": "sha512-AFGH8ZI3e82QiVZkLDCPCFOnBsdvs/FhY+ueDOFuSr+EqMGzPnneB6DkQSWqy7PC6kbkasfX2VQR5RKRR205lw==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "change-case": "^4.1.2", + "dargs": "^7.0.0", + "debug": "^4.3.4", + "is-type-of": "^1.2.1", + "semver": "^7.3.7", + "yargs": "^13.3.0", + "yargs-parser": "^13.1.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/common-bin/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha1-QUz1r3kKSMYKub5FJ9VtXkETPLE=", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha1-O4Sprq9M8x7EXmv13pG9+wWJ+vE=", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "license": "MIT" + }, + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "license": "MIT", + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U=", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha1-BAFcQd4Ly2nshAUPPZvgyvjW1cw=", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/depd/-/depd-2.0.0.tgz", + "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8=", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha1-mytnDQCkMWZ6inW6Kc0bmICc51E=", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/echarts": { + "version": "5.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/echarts/-/echarts-5.6.0.tgz", + "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.6.1" + } + }, + "node_modules/echarts-for-react": { + "version": "3.0.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/echarts-for-react/-/echarts-for-react-3.0.3.tgz", + "integrity": "sha512-KdvZGkCwmx5DTHl7vjo0CBodSaPY31hPWRC4NZ5B+utQfoW+M54OTBvkoCmktR0kJ+1Bj6rP7pIJJnxPdySyug==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "size-sensor": "^1.0.1" + }, + "peerDependencies": { + "echarts": "^3.0.0 || ^4.0.0 || ^5.0.0", + "react": "^15.0.0 || >=16.0.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.203", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/electron-to-chromium/-/electron-to-chromium-1.5.203.tgz", + "integrity": "sha512-uz4i0vLhfm6dLZWbz/iH88KNDV+ivj5+2SA+utpgjKaj9Q0iDLuwk6Idhe9BTxciHudyx6IvTvijhkPvFGUQ0g==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/errno/-/errno-0.1.8.tgz", + "integrity": "sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8=", + "license": "MIT", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/figlet": { + "version": "1.8.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/figlet/-/figlet-1.8.2.tgz", + "integrity": "sha512-iPCpE9B/rOcjewIzDnagP9F2eySzGeHReX8WlrZQJkqFBk2wvq8gY0c6U6Hd2y9HnX1LQcYSeP7aEHoPt6sVKQ==", + "license": "MIT", + "bin": { + "figlet": "bin/index.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA=", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha1-WkLmO1UXc0nPQFvrjXdayruSwGM=", + "license": "MIT", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha1-w4nM2HrBbtLfpiRv1zuSaqAOa48=", + "license": "MIT", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk=", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "license": "MIT", + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "license": "ISC" + }, + "node_modules/is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha1-pSfTH7IyeSgd3l84XHe13nCnJDU=", + "license": "MIT" + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-type-of": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-type-of/-/is-type-of-1.4.0.tgz", + "integrity": "sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==", + "license": "MIT", + "dependencies": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "license": "MIT" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "license": "MIT" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=", + "dev": true, + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "license": "MIT", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa": { + "version": "2.16.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/koa/-/koa-2.16.2.tgz", + "integrity": "sha512-+CCssgnrWKx9aI3OeZwroa/ckG4JICxvIFnSiOUyl2Uv+UTI+xIw0FfFrWS7cQFpoePpr9o8csss7KzsTzNL8Q==", + "license": "MIT", + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.9.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "license": "MIT" + }, + "node_modules/koa-connect": { + "version": "2.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/koa-connect/-/koa-connect-2.1.0.tgz", + "integrity": "sha512-O9pcFafHk0oQsBevlbTBlB9co+2RUQJ4zCzu3qJPmGlGoeEZkne+7gWDkecqDPSbCtED6LmhlQladxs6NjOnMQ==", + "license": "MIT" + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha1-hqDETYHUBVG64i/uZwmQRXPupPU=", + "license": "MIT", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa-proxies": { + "version": "0.12.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/koa-proxies/-/koa-proxies-0.12.4.tgz", + "integrity": "sha512-xxrEtN0e7s7/gNRoOMUltCbuIaCWqTQUTZNWQqet/8MoxSW0hG422lx2Al9FfYO3nCeA+b5c5/YmILRzavivDA==", + "license": "MIT", + "dependencies": { + "http-proxy": "^1.18.1", + "path-match": "^1.2.4", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "koa": ">=2" + } + }, + "node_modules/koa/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/less": { + "version": "4.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/less/-/less-4.4.0.tgz", + "integrity": "sha512-kdTwsyRuncDfjEs0DlRILWNvxhDG/Zij4YLO4TMJgDLW+8OzpfkdPnRgrsRuY1o+oaxJGWsps5f/RVBgGmmN0w==", + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/loading-cli": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/loading-cli/-/loading-cli-1.1.2.tgz", + "integrity": "sha512-M1ntfXHpdGoQxfaqKBOQPwSrTr9EIoTgj664Q9UVSbSnJvAFdribo+Ij//1jvACgrGHaTvfKoD9PG3NOxGj44g==", + "license": "MIT", + "dependencies": { + "colors-cli": "^1.0.26" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", + "devOptional": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha1-b6I3xj29xKgsoP2ILkci3F5jTig=", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha1-V0yBOM4dK1hh8LRFedut1gxmFbI=", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "peer": true, + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha1-02H9XJgA9VhVGoNp/A3NRmK2Ek0=", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/only/-/only-0.0.2.tgz", + "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha1-fRf+SqEr3jTUp32RrPtiGcqtAcU=", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha1-4rXb7eAOf6m8NjYH9TMn6LBzGJs=", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha1-tI4O8rmOIF58Ha50fQsVCCN2YOs=", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha1-kWhkUzTrlCZYN1xW+AtMDLX4LG8=", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-match": { + "version": "1.2.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/path-match/-/path-match-1.2.4.tgz", + "integrity": "sha512-UWlehEdqu36jmh4h5CWJ7tARp1OEVKGHKm6+dg9qMq5RKUTV5WJrGgaZ3dN2m7WFAXDbjlHzvJvL/IUpy84Ktw==", + "license": "MIT", + "dependencies": { + "http-errors": "~1.4.0", + "path-to-regexp": "^1.0.0" + } + }, + "node_modules/path-match/node_modules/http-errors": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/http-errors/-/http-errors-1.4.0.tgz", + "integrity": "sha1-bAJC3qaz33r9oVPHEImzHG6Cqr8=", + "license": "MIT", + "dependencies": { + "inherits": "2.0.1", + "statuses": ">= 1.2.1 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/path-match/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "license": "ISC" + }, + "node_modules/path-match/node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-match/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/pify/-/pify-4.0.1.tgz", + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "license": "MIT", + "optional": true + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rc-cascader": { + "version": "3.34.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-cascader/-/rc-cascader-3.34.0.tgz", + "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-drawer/-/rc-drawer-7.3.0.tgz", + "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-field-form/-/rc-field-form-2.7.0.tgz", + "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.12.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-image/-/rc-image-7.12.0.tgz", + "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.4.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-overflow/-/rc-overflow-1.4.1.tgz", + "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-segmented/-/rc-segmented-2.7.0.tgz", + "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.8", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-slider/-/rc-slider-11.1.8.tgz", + "integrity": "sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.51.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-table/-/rc-table-7.51.1.tgz", + "integrity": "sha512-5iq15mTHhvC42TlBLRCoCBLoCmGlbRZAlyF21FonFnS/DIC8DeRqnmdyVREwt2CFbPceM0zSNdEeVfiGaqYsKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.7.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-tabs/-/rc-tabs-15.7.0.tgz", + "integrity": "sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-textarea/-/rc-textarea-1.10.2.tgz", + "integrity": "sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.9.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-upload/-/rc-upload-4.9.2.tgz", + "integrity": "sha512-nHx+9rbd1FKMiMRYsqQ3NkXUv7COHPBo3X1Obwq9SWS6/diF/A0aJ5OHubvwUAIDs+4RMleljV0pcrNUc823GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-virtual-list": { + "version": "3.19.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rc-virtual-list/-/rc-virtual-list-3.19.1.tgz", + "integrity": "sha512-DCapO2oyPqmooGhxBuXHM4lFuX+sshQwWqqkuyFA+4rShLe//+GEPVwiDgO+jKtKHtbeYwZoNvetwfHdOf+iUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-router/-/react-router-6.30.1.tgz", + "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/react-router-dom/-/react-router-dom-6.30.1.tgz", + "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0", + "react-router": "6.30.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=", + "license": "ISC" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "license": "MIT" + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ=", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.46.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/rollup/-/rollup-4.46.3.tgz", + "integrity": "sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.3", + "@rollup/rollup-android-arm64": "4.46.3", + "@rollup/rollup-darwin-arm64": "4.46.3", + "@rollup/rollup-darwin-x64": "4.46.3", + "@rollup/rollup-freebsd-arm64": "4.46.3", + "@rollup/rollup-freebsd-x64": "4.46.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.3", + "@rollup/rollup-linux-arm-musleabihf": "4.46.3", + "@rollup/rollup-linux-arm64-gnu": "4.46.3", + "@rollup/rollup-linux-arm64-musl": "4.46.3", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.3", + "@rollup/rollup-linux-ppc64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-musl": "4.46.3", + "@rollup/rollup-linux-s390x-gnu": "4.46.3", + "@rollup/rollup-linux-x64-gnu": "4.46.3", + "@rollup/rollup-linux-x64-musl": "4.46.3", + "@rollup/rollup-win32-arm64-msvc": "4.46.3", + "@rollup/rollup-win32-ia32-msvc": "4.46.3", + "@rollup/rollup-win32-x64-msvc": "4.46.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "license": "MIT", + "optional": true + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC", + "optional": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha1-NkWnuMEXx4f96HAgViJbtipFEx8=", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha1-ZsmiSnP5/CjL5msJ/tPTPcrxtCQ=", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sirv": { + "version": "3.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/sirv/-/sirv-3.0.1.tgz", + "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/size-sensor": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/size-sensor/-/size-sensor-1.0.2.tgz", + "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==", + "dev": true, + "license": "ISC" + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha1-Tyu9Vo6ZNavf1ZPzTGkdrbScRSw=", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha1-VcsADM8dSHKL0jxoWgY5mM8aG2M=", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=", + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/superagent": { + "version": "10.2.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/superagent/-/superagent-10.2.3.tgz", + "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.4", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=", + "dev": true, + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "license": "MIT", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "license": "MIT", + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha1-2JgQgj+qsd8VSbfZenb4Ziuub3o=", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha1-mSwyc/iCq9GdHgKJTMFHEX+EQyQ=", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "license": "MIT", + "peer": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha1-H9H2cjXVttD+54EFYAG/tpTAOwk=", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q=", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha1-tfJZyCzW4zaSHv17/Yv1YN6e7t8=", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha1-Ew8JcC667vJlDVTObj5XBvek+zg=", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/ylru": { + "version": "1.4.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/ylru/-/ylru-1.4.0.tgz", + "integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/zrender": { + "version": "5.6.1", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/zrender/-/zrender-5.6.1.tgz", + "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://nexus.ngaiot.com/repository/fs-npm/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true, + "license": "0BSD" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..48391ac --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "wuyuanbiaoba-web", + "version": "1.0.0", + "main": "index.html", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "peace-rc start", + "build": "peace-rc build" + }, + "author": "附离", + "license": "ISC", + "description": "基于 React.18 + Vite.4 预置 Antd.5 的客户端(web)", + "engines": { + "node": ">=20.0.0" + }, + "devDependencies": { + "@ant-design/icons": "^5.4.0", + "antd": "^5.19.0", + "react": "18.x", + "react-dom": "18.x", + "react-redux": "^9.1.2", + "echarts": "^5.6.0", + "echarts-for-react": "^3.0.2", + "react-router-dom": "^6.26.0" + }, + "dependencies": { + "@koa/multer": "^3.0.2", + "@peace/react_client": "^5.0.1", + "fs-extra": "^11.2.0", + "ws": "^8.18.3" + } +} diff --git a/server/controllers/xunruan.js b/server/controllers/xunruan.js new file mode 100644 index 0000000..aa72802 --- /dev/null +++ b/server/controllers/xunruan.js @@ -0,0 +1,18 @@ +const request = require('superagent') + +module.exports.decryption = async (ctx, next) => { + try { + const { xunruan } = ctx.config + const { file } = ctx.request + let url = `${xunruan.host}/uploadSecret`; + let res_ = await request.post(url).set('Content-Type', 'application/octet-stream') + .send(file.buffer) + .responseType('binary') + + ctx.status = 200; + ctx.body = res_.body + } catch (error) { + ctx.status = 400; + ctx.body = { message: 'decryption error.' }; + } +} diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..e69de29 diff --git a/server/routes.js b/server/routes.js new file mode 100644 index 0000000..f6e2bbe --- /dev/null +++ b/server/routes.js @@ -0,0 +1,22 @@ + +const multer = require('@koa/multer'); +const { setupTcpProxy } = require('./tcpProxy'); +const upload = multer({ + limits: { fileSize: 500 * 1024 * 1024 } // 将文件大小限制设置为200MB +}); +// +const xunruan = require('./controllers/xunruan.js'); + + + +// ... 路由都写在这里 +module.exports = async (app, router, conf) => { + // 讯软相关接口 + router.post('/xunruan/decryption', + upload.single('file'), + xunruan.decryption, + { content: '讯软解密', visible: true } + ); + // 设置TCP代理 + setupTcpProxy(conf); +} diff --git a/server/tcpProxy/index.js b/server/tcpProxy/index.js new file mode 100644 index 0000000..1057232 --- /dev/null +++ b/server/tcpProxy/index.js @@ -0,0 +1,163 @@ +const net = require('net'); +const WebSocket = require('ws'); +// TCP代理配置 +const TCP_HOST = process.env.NODE_ENV === 'development'? '10.8.30.179' : '127.0.0.1'; +const TCP_PORT = 2230; + +// 创建独立的WebSocket服务器用于TCP代理 +function setupTcpProxy(conf) { + // 从配置中获取端口,如果没有则使用默认端口 + const wsPort = (conf && conf.port) ? Number(conf.port) + 1 : 5001; // WebSocket端口比HTTP端口大1 + + console.log(`准备在端口 ${wsPort} 启动WebSocket服务器`); + + const wss = new WebSocket.Server({ + port: wsPort, + host: '0.0.0.0', // 监听所有网络接口,允许局域网访问 + path: '/tcp-proxy' + }); + + wss.on('connection', (ws, request) => { + console.log(`WebSocket连接建立,来自: ${request.socket.remoteAddress}`); + + // 创建TCP连接 + const tcpClient = new net.Socket(); + // TCP数据缓冲区 + let tcpDataBuffer = ''; + + // TCP连接成功 + tcpClient.connect(process.env.TCP_PORT || TCP_PORT, process.env.TCP_HOST || TCP_HOST, () => { + console.log(`TCP连接已建立到 ${TCP_HOST}:${TCP_PORT}`); + }); + + // TCP接收数据,转发到WebSocket + tcpClient.on('data', (data) => { + let textData; + // 尝试解析为文本 + try { + textData = data.toString('utf8'); + console.log('收到TCP数据片段:', textData.length, '字节'); + } catch (e) { + console.log('TCP数据无法解析为文本'); + return; + } + + // 将新数据添加到缓冲区 + tcpDataBuffer += textData; + + // 检查是否有完整的消息(以\n\n结尾) + let endIndex; + while ((endIndex = tcpDataBuffer.indexOf('\n\n')) !== -1) { + // 提取完整消息 + const completeMessage = tcpDataBuffer.substring(0, endIndex); + // 从缓冲区移除已处理的消息 + tcpDataBuffer = tcpDataBuffer.substring(endIndex + 2); + + console.log('提取到完整消息:', completeMessage.length, '字节'); + + // 转发完整消息到WebSocket + if (ws.readyState === WebSocket.OPEN) { + console.log('准备发送完整消息到WebSocket:', completeMessage.length, '字节'); + console.log('消息内容:', completeMessage); + ws.send(completeMessage, (err) => { + if (err) { + console.error('WebSocket发送数据错误:', err); + } else { + console.log('完整消息已转发到WebSocket客户端'); + } + }); + } + } + + console.log('缓冲区剩余数据:', tcpDataBuffer.length, '字节'); + }); + + // WebSocket接收数据,转发到TCP + ws.on('message', (data) => { + // 处理可能的Buffer数据,转换为字符串 + let messageStr; + + if (Buffer.isBuffer(data)) { + messageStr = data.toString('utf8'); + // console.log('WebSocket数据(Buffer转字符串):', messageStr); + } else if (typeof data === 'string') { + messageStr = data; + // console.log('WebSocket数据(字符串):', messageStr); + } else { + console.warn('收到未知类型数据,已忽略:', typeof data); + return; + } + + // 转发字符串数据到TCP服务器 + if (tcpClient.writable) { + console.log('准备发送数据到TCP服务器:', messageStr); + + // 检查数据大小 + const dataSize = Buffer.byteLength(messageStr, 'utf8'); + console.log(`数据大小: ${dataSize} bytes`); + + // 直接发送完整数据 + tcpClient.write(messageStr + '\n\n', (err) => { + if (err) { + console.error('TCP发送数据错误:', err); + } else { + console.log('数据已发送到TCP服务器'); + } + }); + } else { + console.warn('TCP连接不可写,无法发送数据'); + } + }); + + // TCP连接错误处理 + tcpClient.on('error', (err) => { + console.error('TCP连接错误:', err); + tcpDataBuffer = ''; // 清理缓冲区 + if (ws.readyState === WebSocket.OPEN) { + ws.close(1011, 'TCP连接错误'); + } + }); + + // TCP连接关闭 + tcpClient.on('close', () => { + console.log('TCP连接已关闭'); + tcpDataBuffer = ''; // 清理缓冲区 + if (ws.readyState === WebSocket.OPEN) { + ws.close(); + } + }); + + // WebSocket连接关闭 + ws.on('close', () => { + console.log('WebSocket连接已关闭'); + tcpDataBuffer = ''; // 清理缓冲区 + if (tcpClient.writable) { + tcpClient.destroy(); + } + }); + + // WebSocket错误处理 + ws.on('error', (err) => { + console.error('WebSocket错误:', err); + if (tcpClient.writable) { + tcpClient.destroy(); + } + }); + }); + + wss.on('listening', () => { + console.log(`TCP代理WebSocket服务器已启动在端口 ${wsPort},路径: /tcp-proxy`); + console.log(`局域网连接地址: ws://[本机IP]:${wsPort}/tcp-proxy`); + console.log(`本地连接地址: ws://localhost:${wsPort}/tcp-proxy`); + console.log(`注意:请确保防火墙允许端口 ${wsPort} 的访问`); + }); + + wss.on('error', (err) => { + console.error('WebSocket服务器错误:', err); + }); + + return wss; +} + + +module.exports = { setupTcpProxy };