Merge branch 'develop-cy' into 'develop'

【中心对接】 优化ws实现代码(从ahokks引入改为使用原生代码);ts校验不通过,暂时用ts-nocheck;

See merge request web-project/zhst-lambo!18
This commit is contained in:
江志雄 2024-04-23 16:15:07 +08:00
commit c4fe25f89b
11 changed files with 125 additions and 39 deletions

View File

@ -2,5 +2,6 @@ export { default as AlgorithmConfigModal } from "./algorithmConfigModal";
export { default as AlgorithmConfig } from "./algorithmConfig"; export { default as AlgorithmConfig } from "./algorithmConfig";
export { default as Login } from "./login"; export { default as Login } from "./login";
export { default as Password } from "./password"; export { default as Password } from "./password";
export { default as CenterLink } from "./centerLink";
export { default as SchemaFormModal } from "./algorithmConfig/components/schemaFormModal"; export { default as SchemaFormModal } from "./algorithmConfig/components/schemaFormModal";
export * from 'rc-util'; export * from 'rc-util';

View File

@ -0,0 +1 @@
export declare const createAElement: (url: string, isBlank: boolean) => void;

View File

@ -0,0 +1,14 @@
// 可应用于页面跳转以及文件下载
// 第一个参数:文件的下载路径/要跳转页面的路径(可携带参数)
// 第二个参数是否新打开一个页面true为新开一个页面false是在当前页面进行操作
export var createAElement = function createAElement(url, isBlank) {
var newLink = document.createElement('a');
newLink.className = 'create-link';
newLink.href = url;
if (isBlank) {
newLink.target = '_blank';
}
document.body.appendChild(newLink);
newLink.click();
document.body.removeChild(newLink);
};

View File

@ -32,6 +32,7 @@ var src_exports = {};
__export(src_exports, { __export(src_exports, {
AlgorithmConfig: () => import_algorithmConfig.default, AlgorithmConfig: () => import_algorithmConfig.default,
AlgorithmConfigModal: () => import_algorithmConfigModal.default, AlgorithmConfigModal: () => import_algorithmConfigModal.default,
CenterLink: () => import_centerLink.default,
Login: () => import_login.default, Login: () => import_login.default,
Password: () => import_password.default, Password: () => import_password.default,
SchemaFormModal: () => import_schemaFormModal.default SchemaFormModal: () => import_schemaFormModal.default
@ -41,12 +42,14 @@ var import_algorithmConfigModal = __toESM(require("./algorithmConfigModal"));
var import_algorithmConfig = __toESM(require("./algorithmConfig")); var import_algorithmConfig = __toESM(require("./algorithmConfig"));
var import_login = __toESM(require("./login")); var import_login = __toESM(require("./login"));
var import_password = __toESM(require("./password")); var import_password = __toESM(require("./password"));
var import_centerLink = __toESM(require("./centerLink"));
var import_schemaFormModal = __toESM(require("./algorithmConfig/components/schemaFormModal")); var import_schemaFormModal = __toESM(require("./algorithmConfig/components/schemaFormModal"));
__reExport(src_exports, require("rc-util"), module.exports); __reExport(src_exports, require("rc-util"), module.exports);
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = { 0 && (module.exports = {
AlgorithmConfig, AlgorithmConfig,
AlgorithmConfigModal, AlgorithmConfigModal,
CenterLink,
Login, Login,
Password, Password,
SchemaFormModal, SchemaFormModal,

View File

@ -0,0 +1 @@
export declare const createAElement: (url: string, isBlank: boolean) => void;

View File

@ -0,0 +1,39 @@
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/utils/index.ts
var utils_exports = {};
__export(utils_exports, {
createAElement: () => createAElement
});
module.exports = __toCommonJS(utils_exports);
var createAElement = (url, isBlank) => {
var newLink = document.createElement("a");
newLink.className = "create-link";
newLink.href = url;
if (isBlank) {
newLink.target = "_blank";
}
document.body.appendChild(newLink);
newLink.click();
document.body.removeChild(newLink);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createAElement
});

View File

@ -1,8 +1,8 @@
import React,{useRef} from 'react' // @ts-nocheck
import React,{useRef,useState} from 'react'
import TerminalForm from './components/TerminalForm' import TerminalForm from './components/TerminalForm'
import WebTerminal from './components/WebTerminal' import WebTerminal from './components/WebTerminal'
import './index.less'; import './index.less';
import style from 'packages/meta/src/badge/style';
interface CenterLinkProps{ interface CenterLinkProps{
websocketUrl:string; // websocket服务地址 websocketUrl:string; // websocket服务地址
@ -22,8 +22,8 @@ const materialName='center-link';
const CenterLink:React.FC<CenterLinkProps>=(props:CenterLinkProps)=>{ const CenterLink:React.FC<CenterLinkProps>=(props:CenterLinkProps)=>{
const { const {
websocketUrl,
ip, ip,
websocketUrl,
token, token,
terminalStyle, terminalStyle,
onConnect, onConnect,
@ -35,22 +35,23 @@ const CenterLink:React.FC<CenterLinkProps>=(props:CenterLinkProps)=>{
style style
}=props; }=props;
const webRef=useRef(null); const webRef=useRef(null);
const [ipUrl,setIpUrl]=useState<string>(ip);
// 处理开始连接服务器ip的事件 // 处理开始连接服务器ip的事件
const handleConnectClick=(values:any)=>{ const handleConnectClick=(values:any)=>{
const {ip}=values; const {ip}=values;
if(ip&&token&&websocketUrl&&webRef.current){ setIpUrl((
webRef.current.connect(); )=>(ip))
}
onConnect&&onConnect(values); onConnect&&onConnect(values);
} }
return ( return (
<div className={materialName} style={style}> <div className={materialName} style={style}>
<TerminalForm onConnect={handleConnectClick} onExportLogs={onExportLogs} /> <TerminalForm ip={ipUrl} onConnect={handleConnectClick} onExportLogs={onExportLogs} />
<WebTerminal <WebTerminal
ref={webRef} ref={webRef}
ip={ipUrl}
websocketUrl={websocketUrl} websocketUrl={websocketUrl}
ip={ip}
token={token} token={token}
terminalStyle={terminalStyle} terminalStyle={terminalStyle}
onOpen={onOpen} onOpen={onOpen}

View File

@ -1,20 +1,27 @@
import React from 'react'; import React, { useEffect } from 'react';
import { Button, Form, Input,FormProps } from '@zhst/meta'; import { Button, Form, Input,FormProps } from '@zhst/meta';
import '../index.less'; import '../index.less';
const materialName='terminal-form'; const materialName='terminal-form';
export interface TerminalFormProps{ export interface TerminalFormProps{
ip:string; // ip地址
onConnect:FormProps['onFinish']; // 开始连接事件 onConnect:FormProps['onFinish']; // 开始连接事件
onExportLogs:()=>void; // 导出日志事件 onExportLogs:()=>void; // 导出日志事件
} }
const TerminalForm:React.FC<TerminalFormProps>=(props:TerminalFormProps)=> { const TerminalForm:React.FC<TerminalFormProps>=(props:TerminalFormProps)=> {
const { const {
ip,
onConnect, onConnect,
onExportLogs, onExportLogs,
}=props; }=props;
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(()=>{
form.setFieldsValue({
ip,
});
},[])
return ( return (
<div className={materialName}> <div className={materialName}>
<h1></h1> <h1></h1>

View File

@ -1,7 +1,6 @@
// @ts-nocheck
import React,{useRef,useEffect, useImperativeHandle, import React,{useRef,useEffect, useImperativeHandle,
forwardRef,} from 'react'; forwardRef,} from 'react';
import { useWebSocket } from '@zhst/hooks';
import { Terminal } from 'xterm'; import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit'; import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css'; import 'xterm/css/xterm.css';
@ -56,21 +55,10 @@ const WebTerminal:React.FC<WebTerminalProps&WebsocketOptions>=forwardRef((props:
onMessage, onMessage,
onError, onError,
}=props; }=props;
const { readyState, sendMessage, latestMessage, disconnect, connect }:WebsocketResult = useWebSocket( const termRef = useRef<React.RefObject<HTMLDivElement>|null>(null);
`${websocketUrl}?ip=${ip}&Authorization=${token}`,{manual:true,reconnectLimit:0,onOpen, const termClassRef=useRef<React.RefObject<HTMLDivElement>|null>(null)
onClose,
onMessage,
onError}
);
const termRef = useRef(null);
const termClassRef=useRef(null)
// const currLine=useRef(null); // const currLine=useRef(null);
const wsRef=useRef<React.RefObject<HTMLDivElement>|null>(null);
useEffect(()=>{
if(termClassRef?.current){
termClassRef.current.write(latestMessage?.data+'\r\n\x1b[33m$\x1b[0m ');
}
},[latestMessage]);
// terminal初始化 // terminal初始化
useEffect(()=>{ useEffect(()=>{
@ -78,12 +66,12 @@ const WebTerminal:React.FC<WebTerminalProps&WebsocketOptions>=forwardRef((props:
if(!termRef.current){ if(!termRef.current){
return; return;
} }
termClassRef.current=new Terminal({ let term=new Terminal({
fontFamily: 'Menlo, Monaco, "Courier New", monospace', fontFamily: 'Menlo, Monaco, "Courier New", monospace',
fontWeight: 400, fontWeight: 400,
fontSize: 14, fontSize: 14,
rows: Math.ceil( rows: Math.ceil(
(termRef.current?.clientHeight - (termRef.current.clientHeight -
150) / 150) /
14, 14,
), ),
@ -98,12 +86,12 @@ const WebTerminal:React.FC<WebTerminalProps&WebsocketOptions>=forwardRef((props:
background: "#1a1a1d", //背景色 background: "#1a1a1d", //背景色
cursor: "help", //设置光标 cursor: "help", //设置光标
} }
}) });
let term=termClassRef.current; termClassRef.current=term;
term.open(termRef.current); term.open(termRef.current);
term.focus(); // 光标聚集 term.focus(); // 光标聚集
term.promp=(_)=>{ term.promp=()=>{
term.write('\r\n\x1b[33m$\x1b[0m '); term.write('\r\n\x1b[33m$\x1b[0m ');
} }
const fitAddon=new FitAddon(); const fitAddon=new FitAddon();
@ -113,14 +101,44 @@ const WebTerminal:React.FC<WebTerminalProps&WebsocketOptions>=forwardRef((props:
},[]); },[]);
useEffect(()=>{
// @ts-ignore
if(ip&&websocketUrl&&token){
const ws=new WebSocket(`${websocketUrl}?ip=${ip}&Authorization=${token}`);
wsRef.current=ws;
if(wsRef?.current){
wsRef.current.onopen=(event: WebSocketEventMap['open'], instance: WebSocket)=>{
if(onOpen){
onOpen(event,instance);
}
}
wsRef.current.onclose=(event: WebSocketEventMap['close'], instance: WebSocket)=>{
if(onClose){
onClose(event,instance);
}
}
wsRef.current.onmessage=(message: WebSocketEventMap['message'], instance: WebSocket)=>{
if(termClassRef.current){
termClassRef.current.write(message?.data+'\r\n\x1b[33m$\x1b[0m ');
}
if(onMessage){
onMessage(message,instance);
}
}
wsRef.current.onerror=(event: WebSocketEventMap['error'], instance: WebSocket)=>{
if(onError){
onError(event,instance);
}
}
}
}
},[ip,websocketUrl,token])
// 自定义暴露给父组件的实例 // 自定义暴露给父组件的实例
useImperativeHandle(ref,()=>({ useImperativeHandle(ref,()=>(
readyState, wsRef.current
sendMessage, ));
latestMessage,
disconnect,
connect
}));
return ( return (
<div className={materialName}> <div className={materialName}>

View File

@ -5,8 +5,8 @@ const demo = () => {
return ( return (
<CenterLink <CenterLink
style={{width:'100%',height:'600px'}} style={{width:'100%',height:'600px'}}
websocketUrl={'ws://10.0.0.7:50051/active'} websocketUrl={'ws://127.0.0.1:50051/active'}
token={'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTM1OTI2NDYsImp0aSI6ImFkbWluIn0._mVU216h0q8va8bZ8PCKfGOKslYJWdRLFvLzUdvGDN4'} token={'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTM4NDAxOTAsImp0aSI6ImFkbWluIn0.KAcgU8r-AIQ2GEu5g2o-YANstqisy5WT6rz5fbMjdcs'}
ip={'127.0.0.1'} ip={'127.0.0.1'}
terminalStyle={{width:'100%',height:'calc(100% - 180px)'}} terminalStyle={{width:'100%',height:'calc(100% - 180px)'}}
onConnect={(values)=>{ onConnect={(values)=>{

View File

@ -99,6 +99,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>((props, ref)
const mergedStyle: React.CSSProperties = { ...segmented?.style, ...style }; const mergedStyle: React.CSSProperties = { ...segmented?.style, ...style };
return wrapCSSVar( return wrapCSSVar(
// @ts-ignore
<RcSegmented <RcSegmented
{...restProps} {...restProps}
className={cls} className={cls}