feat: 新增websoket事件对应的events
This commit is contained in:
parent
d220b7b0f5
commit
1693316766
3
.env
3
.env
@ -3,5 +3,6 @@ COSMOS_ENDPOINT="http://10.66.66.234:26657"
|
||||
NODE_SECRET="aHVnZSBjb21wYW55IHBob25lIHdlc3QgcGxhY2Ugc2VtaW5hciBtaXJhY2xlIGxlbmQgbWFuZGF0ZSB0aGVuIGFkanVzdCBxdWl0IG1lYXQgY2hlYXAgbm9vZGxlIGNvdXBsZSBkZWZpbmUgbXVzY2xlIHB1bHNlIHNpc3RlciBwaWVjZSBkZXZpY2UgcHJpdmF0ZSBob29k"
|
||||
IS_DEBUG="true"
|
||||
ACCOUNT_NAME="de1"
|
||||
VIET_EVENTS_WS_URL="ws://10.66.66.234:8080/events"
|
||||
VITE_BASE_URL="http://10.66.66.234:6060"
|
||||
VITE_BLOCK_URL="http://localhost:3001"
|
||||
VITE_BLOCK_URL="http://10.66.66.234:1317"
|
||||
@ -12,6 +12,7 @@ use paw_common::preclude::{CoreConfig, CoreResponse};
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, specta::Type)]
|
||||
pub struct ProxyNodeInfo {
|
||||
pub name: String,
|
||||
pub ip: String,
|
||||
pub country_code: String,
|
||||
pub country_name: String,
|
||||
pub country_name_zh: String,
|
||||
@ -76,7 +77,7 @@ pub async fn get_nodes(config: CoreConfig) -> Result<Vec<ProxyNodeInfo>> {
|
||||
debug!("Successfully got nodes: {:?}", result.data);
|
||||
Ok(result.data)
|
||||
} else {
|
||||
error!("Failed to get nodes: {}", response.text().await?);
|
||||
debug!("Failed to get nodes: {}", response.text().await?);
|
||||
bail!("Failed to get nodes")
|
||||
}
|
||||
}
|
||||
|
||||
86
src/App.tsx
86
src/App.tsx
@ -12,7 +12,7 @@ import {
|
||||
setMaliciousNodeList,
|
||||
setNodeDownList,
|
||||
} from "@/store/web3Slice";
|
||||
import type { AppDispatch, RootState } from "@/store";
|
||||
import type { AppDispatch } from "@/store";
|
||||
|
||||
import eventBus, { eventTypes } from "@/utils/eventBus";
|
||||
import { WebSocketClient } from "@/utils/webSocketClient";
|
||||
@ -20,6 +20,8 @@ import { WebSocketClient } from "@/utils/webSocketClient";
|
||||
import Titlebar from "@/components/Titlebar";
|
||||
import Layout from "@/layout";
|
||||
import Tray from "@/components/Tray";
|
||||
import { getRandomCountryKey } from "./data";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
function App() {
|
||||
// 执行启动自检
|
||||
@ -37,37 +39,49 @@ function App() {
|
||||
// const { } = useSelector(
|
||||
// (state: RootState) => state.web3Reducer
|
||||
// );
|
||||
const webSocketClient = useRef<WebSocketClient | null>();
|
||||
let eventsWs: WebSocketClient | null = null;
|
||||
|
||||
const openWsTraffic = async () => {
|
||||
if (webSocketClient.current) return;
|
||||
const { api_port } = await loadCoreConfig();
|
||||
// todo! 后面会把二级制文件启动的参数作为配置项,这里暂时写死
|
||||
webSocketClient.current = new WebSocketClient(
|
||||
`ws://127.0.0.1:${api_port}/traffic`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer secret",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (eventsWs) return;
|
||||
eventsWs = new WebSocketClient("ws://10.66.66.234:8080/events", {});
|
||||
console.log(eventsWs, "openWsTraffic Start");
|
||||
// 执行 WebSocket 操作
|
||||
await webSocketClient.current.connect();
|
||||
webSocketClient.current.addListener((msg: any) => {
|
||||
if (msg.code === 0) {
|
||||
switch (msg.event) {
|
||||
await eventsWs?.connect();
|
||||
await eventsWs?.addListener((msg: any) => {
|
||||
try {
|
||||
const msgData = msg ? JSON.parse(msg.data) : {};
|
||||
if (msgData.code === 0) {
|
||||
console.log(msgData, "msgDatamsgData");
|
||||
switch (msgData.event) {
|
||||
case eventTypes.NODE_UP:
|
||||
console.log("节点上线");
|
||||
break;
|
||||
case eventTypes.NODE_DOWN:
|
||||
// 添加下线节点到store 里面
|
||||
dispatch(setNodeDownList(msg.data.name));
|
||||
if (msgData.data.name) {
|
||||
// 获取一个随机的国家code
|
||||
const countryCode = getRandomCountryKey();
|
||||
dispatch(
|
||||
setNodeDownList({
|
||||
name: msgData.data.name,
|
||||
code: countryCode,
|
||||
})
|
||||
);
|
||||
}
|
||||
console.log("节点下线");
|
||||
break;
|
||||
case eventTypes.MALICIOUS_NODE:
|
||||
// 添加恶意节点到store 里面
|
||||
dispatch(setMaliciousNodeList(msg.data.name));
|
||||
if (msgData.data.name) {
|
||||
// 获取一个随机的国家code
|
||||
const countryCode = getRandomCountryKey();
|
||||
dispatch(
|
||||
setMaliciousNodeList({
|
||||
name: msgData.data.name,
|
||||
code: countryCode,
|
||||
})
|
||||
);
|
||||
}
|
||||
console.log("检测到恶意节点");
|
||||
break;
|
||||
case eventTypes.NODE_INIT_COMPLATE:
|
||||
@ -86,30 +100,38 @@ function App() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error, "error");
|
||||
}
|
||||
});
|
||||
console.log(eventsWs, "openWsTraffic End");
|
||||
};
|
||||
|
||||
const createdSoketEventBus = async () => {
|
||||
eventBus.on(eventTypes.NODE_INIT_COMPLATE, (data: any) => {
|
||||
console.log("节点预配置完成", data);
|
||||
webSocketClient.current?.sendMessage(data);
|
||||
eventsWs?.sendMessage(data);
|
||||
});
|
||||
eventBus.on(eventTypes.NODE_REMOVE, (data: any) => {
|
||||
console.log("节点清除");
|
||||
webSocketClient.current?.sendMessage({
|
||||
const timestamp = dayjs().unix();
|
||||
const params = {
|
||||
code: 0,
|
||||
event: eventTypes.NODE_REMOVE,
|
||||
data: {
|
||||
name: data,
|
||||
},
|
||||
});
|
||||
timestamp,
|
||||
};
|
||||
console.log(JSON.stringify(params), "节点清除 params");
|
||||
eventsWs?.sendMessage(JSON.stringify(params));
|
||||
});
|
||||
};
|
||||
|
||||
const closeWsTraffic = async () => {
|
||||
if (webSocketClient.current) {
|
||||
await webSocketClient.current.disconnect();
|
||||
webSocketClient.current = null;
|
||||
if (eventsWs) {
|
||||
await eventsWs.disconnect();
|
||||
eventsWs = null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -124,11 +146,13 @@ function App() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// initWebsocketsAndEventBus();
|
||||
// return () => {
|
||||
// closeWsTraffic();
|
||||
// removeSoketEventBus();
|
||||
// };
|
||||
setTimeout(() => {
|
||||
initWebsocketsAndEventBus();
|
||||
}, 1000);
|
||||
return () => {
|
||||
closeWsTraffic();
|
||||
removeSoketEventBus();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@ -209,7 +209,7 @@ export type CoreConfig = { socks_port: number; socks_user: string; socks_pass: s
|
||||
/**
|
||||
* 节点信息
|
||||
*/
|
||||
export type ProxyNodeInfo = { name: string; country_code: string; country_name: string; country_name_zh: string; city_name: string; city_name_zh: string; delay: number; download: number; upload: number; survive_score: number; exit: boolean; use: boolean }
|
||||
export type ProxyNodeInfo = { name: string; ip: string; country_code: string; country_name: string; country_name_zh: string; city_name: string; city_name_zh: string; delay: number; download: number; upload: number; survive_score: number; exit: boolean; use: boolean }
|
||||
|
||||
/** tauri-specta globals **/
|
||||
|
||||
|
||||
@ -500,6 +500,18 @@ export const countryNameMap = {
|
||||
Curaçao: '库拉索',
|
||||
}
|
||||
|
||||
// 获取一个随机的国家key
|
||||
export function getRandomCountryKey() {
|
||||
const keys = Object.keys(countryCodeMap)
|
||||
return keys[Math.floor(Math.random() * keys.length)]
|
||||
}
|
||||
|
||||
// 获取一个随机的国家name
|
||||
export function getRandomCountryName() {
|
||||
const keys = Object.keys(countryCodeMap)
|
||||
return countryCodeMap[keys[Math.floor(Math.random() * keys.length)]]
|
||||
}
|
||||
|
||||
// 国家代码映射
|
||||
export const countryCodeMap: { [key: string]: string } = {
|
||||
AD: '安道尔',
|
||||
|
||||
@ -201,7 +201,6 @@ export function useStartupCheck() {
|
||||
// 只有当核心正在运行时才更新节点
|
||||
if (isCoreRunning) {
|
||||
if (nodesResult.status === "ok") {
|
||||
console.log("触发了???");
|
||||
const proxies:any[] = [];
|
||||
nodesResult.data.forEach((node,index) => {
|
||||
const { country_code } = node
|
||||
@ -210,8 +209,8 @@ export function useStartupCheck() {
|
||||
}
|
||||
proxies.push({ country_code: country_code,ingress_country_code: nodesResult.data[index + 1].country_code })
|
||||
})
|
||||
console.log(proxies,'proxiesproxiesproxies')
|
||||
// dispatch(setProxiesList1())
|
||||
// console.log(proxies,'proxiesproxiesproxies')
|
||||
dispatch(setProxiesList1(proxies))
|
||||
dispatch(setNodes(nodesResult.data));
|
||||
} else {
|
||||
dispatch(setNodesError("Failed to fetch nodes"));
|
||||
|
||||
@ -3,17 +3,17 @@ import { FormInstance } from "antd";
|
||||
import { FormDialog } from "@/components/FormDialog";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { nodeList, getRandomNodes } from "@/store/datas";
|
||||
import "./index.scss";
|
||||
import { EllipsisTooltip } from "@/components/Encapsulation";
|
||||
import NotFailNodeIcon from "@/assets/svg/common/not-fail-node.svg?react";
|
||||
import NotWarningNodeIcon from "@/assets/svg/common/not-warning-node.svg?react";
|
||||
import { NODEDIALOGTYPE } from "../../index";
|
||||
import { cn, getUrl } from "@/lib/utils";
|
||||
import eventBus, { eventTypes } from "@/utils/eventBus";
|
||||
|
||||
import { } from "@/store/web3Slice";
|
||||
import { AppDispatch, RootState } from "@/store";
|
||||
import { isTimestampPlusTenMinutesBeforeNow } from "@/utils/tools";
|
||||
import { removeMaliciousNodeList, removeNodeDownList } from "@/store/web3Slice";
|
||||
import { countryCodeMap } from "@/data";
|
||||
|
||||
export interface DialogConfig {
|
||||
title: string;
|
||||
@ -24,8 +24,7 @@ export interface DialogConfig {
|
||||
export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
props
|
||||
) => {
|
||||
const { name, code, exit = false } = props.proxyInfo;
|
||||
|
||||
const { code, exit = false } = props.proxyInfo;
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@ -44,7 +43,7 @@ export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
</div>
|
||||
<EllipsisTooltip
|
||||
className="text-lg flex-1 font-semibold"
|
||||
text={name}
|
||||
text={countryCodeMap[code]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -70,7 +69,7 @@ export const ClearNodeDialog = ({
|
||||
type: DialogConfig;
|
||||
}) => {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const { } = useSelector(
|
||||
const { maliciousNodeList, nodeDownList } = useSelector(
|
||||
(state: RootState) => state.web3Reducer
|
||||
);
|
||||
const [isClear, setIsClear] = useState(false);
|
||||
@ -81,18 +80,26 @@ export const ClearNodeDialog = ({
|
||||
successHandle();
|
||||
setIsClear(true);
|
||||
if (type.title === NODEDIALOGTYPE.ClearFailNode.title) {
|
||||
|
||||
nodeDownList.forEach((item) => {
|
||||
dispatch(removeNodeDownList(item.name));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
});
|
||||
} else if (type.title === NODEDIALOGTYPE.ClearWargingNode.title) {
|
||||
|
||||
maliciousNodeList.forEach((item) => {
|
||||
dispatch(removeMaliciousNodeList(item.name));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
});
|
||||
}
|
||||
// showDialog(false);
|
||||
};
|
||||
|
||||
const proxyList = useMemo(() => {
|
||||
const newData = getRandomNodes(nodeList);
|
||||
|
||||
return newData;
|
||||
}, [nodeList, open, isClear, type]);
|
||||
if (type.title === NODEDIALOGTYPE.ClearFailNode.title) {
|
||||
return nodeDownList;
|
||||
} else {
|
||||
return maliciousNodeList;
|
||||
}
|
||||
}, [nodeDownList, maliciousNodeList, type.title]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
@ -119,8 +126,10 @@ export const ClearNodeDialog = ({
|
||||
>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{proxyList.length > 0 ? (
|
||||
proxyList.map((item) => {
|
||||
return <ProxyItem proxyInfo={item} key={item.name} />;
|
||||
proxyList
|
||||
.filter((item: any) => item?.name)
|
||||
.map((item: any) => {
|
||||
return <ProxyItem proxyInfo={item} key={item?.name} />;
|
||||
})
|
||||
) : (
|
||||
<div className="w-full h-[382px] flex flex-col items-center justify-center">
|
||||
|
||||
@ -3,7 +3,6 @@ import { FormInstance } from "antd";
|
||||
import { FormDialog } from "@/components/FormDialog";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { nodeList, getRandomNodes } from "@/store/datas";
|
||||
import "./index.scss";
|
||||
import { EllipsisTooltip } from "@/components/Encapsulation";
|
||||
import NotFailNodeIcon from "@/assets/svg/common/not-fail-node.svg?react";
|
||||
@ -13,8 +12,8 @@ import { cn, getUrl } from "@/lib/utils";
|
||||
import eventBus, { eventTypes } from "@/utils/eventBus";
|
||||
|
||||
import { AppDispatch, RootState } from "@/store";
|
||||
import {removeMaliciousNodeList,removeNodeDownList} from '@/store/web3Slice'
|
||||
import { isTimestampPlusTenMinutesBeforeNow } from "@/utils/tools";
|
||||
import { removeMaliciousNodeList, removeNodeDownList } from "@/store/web3Slice";
|
||||
import { countryCodeMap } from "@/data";
|
||||
|
||||
export interface DialogConfig {
|
||||
title: string;
|
||||
@ -25,8 +24,7 @@ export interface DialogConfig {
|
||||
export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
props
|
||||
) => {
|
||||
const { name, code, exit = false } = props.proxyInfo;
|
||||
|
||||
const { code, exit = false } = props.proxyInfo;
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@ -45,7 +43,7 @@ export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
</div>
|
||||
<EllipsisTooltip
|
||||
className="text-lg flex-1 font-semibold"
|
||||
text={name}
|
||||
text={countryCodeMap[code]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -83,14 +81,14 @@ export const ClearNodeDialog = ({
|
||||
setIsClear(true);
|
||||
if (type.title === NODEDIALOGTYPE.ClearFailNode.title) {
|
||||
nodeDownList.forEach((item) => {
|
||||
dispatch(removeNodeDownList(item.name));
|
||||
dispatch(removeNodeDownList(item));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
})
|
||||
});
|
||||
} else if (type.title === NODEDIALOGTYPE.ClearWargingNode.title) {
|
||||
maliciousNodeList.forEach((item) => {
|
||||
dispatch(removeMaliciousNodeList(item.name));
|
||||
dispatch(removeMaliciousNodeList(item));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
})
|
||||
});
|
||||
}
|
||||
// showDialog(false);
|
||||
};
|
||||
@ -127,9 +125,11 @@ export const ClearNodeDialog = ({
|
||||
}
|
||||
>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{proxyList?.length > 0 ? (
|
||||
proxyList.map((item) => {
|
||||
return <ProxyItem proxyInfo={item} key={item.name} />;
|
||||
{proxyList.length > 0 ? (
|
||||
proxyList
|
||||
.filter((item: any) => item?.name)
|
||||
.map((item: any) => {
|
||||
return <ProxyItem proxyInfo={item} key={item?.name} />;
|
||||
})
|
||||
) : (
|
||||
<div className="w-full h-[382px] flex flex-col items-center justify-center">
|
||||
|
||||
@ -3,16 +3,17 @@ import { FormInstance } from "antd";
|
||||
import { FormDialog } from "@/components/FormDialog";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { nodeList, getRandomNodes } from "@/store/datas";
|
||||
import "./index.scss";
|
||||
import { EllipsisTooltip } from "@/components/Encapsulation";
|
||||
import NotFailNodeIcon from "@/assets/svg/common/not-fail-node.svg?react";
|
||||
import NotWarningNodeIcon from "@/assets/svg/common/not-warning-node.svg?react";
|
||||
import { NODEDIALOGTYPE } from "../../index";
|
||||
import { cn, getUrl } from "@/lib/utils";
|
||||
import eventBus, { eventTypes } from "@/utils/eventBus";
|
||||
|
||||
import { AppDispatch, RootState } from "@/store";
|
||||
import { isTimestampPlusTenMinutesBeforeNow } from "@/utils/tools";
|
||||
import { removeMaliciousNodeList, removeNodeDownList } from "@/store/web3Slice";
|
||||
import { countryCodeMap } from "@/data";
|
||||
|
||||
export interface DialogConfig {
|
||||
title: string;
|
||||
@ -23,8 +24,7 @@ export interface DialogConfig {
|
||||
export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
props
|
||||
) => {
|
||||
const { name, code, exit = false } = props.proxyInfo;
|
||||
|
||||
const { code, exit = false } = props.proxyInfo;
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@ -43,7 +43,7 @@ export const ProxyItem: React.FC<{ proxyInfo: any; clasName?: string }> = (
|
||||
</div>
|
||||
<EllipsisTooltip
|
||||
className="text-lg flex-1 font-semibold"
|
||||
text={name}
|
||||
text={countryCodeMap[code]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -69,7 +69,9 @@ export const ClearNodeDialog = ({
|
||||
type: DialogConfig;
|
||||
}) => {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const {} = useSelector((state: RootState) => state.web3Reducer);
|
||||
const { maliciousNodeList, nodeDownList } = useSelector(
|
||||
(state: RootState) => state.web3Reducer
|
||||
);
|
||||
const [isClear, setIsClear] = useState(false);
|
||||
const showDialog = (open: boolean) => {
|
||||
setOpen(open);
|
||||
@ -78,16 +80,26 @@ export const ClearNodeDialog = ({
|
||||
successHandle();
|
||||
setIsClear(true);
|
||||
if (type.title === NODEDIALOGTYPE.ClearFailNode.title) {
|
||||
nodeDownList.forEach((item) => {
|
||||
dispatch(removeNodeDownList(item.name));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
});
|
||||
} else if (type.title === NODEDIALOGTYPE.ClearWargingNode.title) {
|
||||
maliciousNodeList.forEach((item) => {
|
||||
dispatch(removeMaliciousNodeList(item.name));
|
||||
eventBus.emit(eventTypes.NODE_REMOVE, item.name);
|
||||
});
|
||||
}
|
||||
// showDialog(false);
|
||||
};
|
||||
|
||||
const proxyList = useMemo(() => {
|
||||
const newData = getRandomNodes(nodeList);
|
||||
|
||||
return [];
|
||||
}, [nodeList, open, isClear, type]);
|
||||
if (type.title === NODEDIALOGTYPE.ClearFailNode.title) {
|
||||
return nodeDownList;
|
||||
} else {
|
||||
return maliciousNodeList;
|
||||
}
|
||||
}, [nodeDownList, maliciousNodeList, type.title]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
@ -114,8 +126,10 @@ export const ClearNodeDialog = ({
|
||||
>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{proxyList.length > 0 ? (
|
||||
proxyList.map((item) => {
|
||||
return <ProxyItem proxyInfo={item} key={item.name} />;
|
||||
proxyList
|
||||
.filter((item: any) => item?.name)
|
||||
.map((item: any) => {
|
||||
return <ProxyItem proxyInfo={item} key={item?.name} />;
|
||||
})
|
||||
) : (
|
||||
<div className="w-full h-[382px] flex flex-col items-center justify-center">
|
||||
|
||||
@ -290,14 +290,14 @@ const NewHome = () => {
|
||||
};
|
||||
useEffect(() => {
|
||||
blockChainApi.getLatestBlock().then((res) => {
|
||||
console.log("res", res);
|
||||
console.log("getLatestBlock res:", res);
|
||||
});
|
||||
initData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(dataInfo, "awaidataInfodataInfotawait");
|
||||
}, [dataInfo]);
|
||||
// useEffect(() => {
|
||||
// console.log(dataInfo, "awaidataInfodataInfotawait");
|
||||
// }, [dataInfo]);
|
||||
|
||||
return (
|
||||
<div className="decentralized w-full h-full flex flex-col relative">
|
||||
|
||||
@ -159,18 +159,18 @@ export const appSlice = createSlice({
|
||||
reducers: {
|
||||
removeMaliciousNodeList: (state, action) => {
|
||||
state.maliciousNodeList = state.maliciousNodeList.filter(
|
||||
(item) => item !== action.payload
|
||||
(item) => item.name !== action.payload.name
|
||||
);
|
||||
},
|
||||
removeNodeDownList: (state, action) => {
|
||||
state.nodeDownList = state.nodeDownList.filter(
|
||||
(item) => item !== action.payload
|
||||
(item) => item.name !== action.payload.name
|
||||
);
|
||||
},
|
||||
setMaliciousNodeList: (state, action) => {
|
||||
// 判断当前节点是否已经存在
|
||||
const maliciousNode = state.maliciousNodeList.find(
|
||||
(item) => action.payload === item
|
||||
(item) => action.payload.name === item.name
|
||||
);
|
||||
if (!maliciousNode) {
|
||||
state.maliciousNodeList.push(action.payload);
|
||||
@ -179,7 +179,7 @@ export const appSlice = createSlice({
|
||||
setNodeDownList: (state, action) => {
|
||||
// 判断当前节点是否已经存在
|
||||
const nodeDown = state.nodeDownList.find(
|
||||
(item) => action.payload === item
|
||||
(item) => action.payload.name === item.name
|
||||
);
|
||||
if (!nodeDown) {
|
||||
state.nodeDownList.push(action.payload);
|
||||
@ -196,7 +196,10 @@ export const appSlice = createSlice({
|
||||
data: action.payload,
|
||||
});
|
||||
} else {
|
||||
proxy_info.proxies[0] = action.payload;
|
||||
proxy_info.proxies[0] = {
|
||||
...proxy_info.proxies[0],
|
||||
data: action.payload,
|
||||
};
|
||||
}
|
||||
state.proxy_info = proxy_info;
|
||||
},
|
||||
|
||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@ -4,6 +4,7 @@ interface ImportMetaEnv {
|
||||
// 定义你的环境变量,例如:
|
||||
readonly VITE_BASE_URL: string
|
||||
readonly VITE_BLOCK_URL: string
|
||||
readonly VIET_EVENTS_WS_URL: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user