优化批量执行指令和windows接入发送组合键

This commit is contained in:
dushixiang
2021-01-23 22:41:44 +08:00
parent ba982dacd0
commit 038f59d155
10 changed files with 290 additions and 91 deletions

View File

@ -28,7 +28,7 @@ import {
CloudUploadOutlined,
CopyOutlined,
DeleteOutlined,
DesktopOutlined,
DesktopOutlined, ExpandOutlined,
FileZipOutlined,
FolderAddOutlined,
LoadingOutlined,
@ -36,7 +36,7 @@ import {
UploadOutlined
} from '@ant-design/icons';
import Upload from "antd/es/upload";
import {download, getToken} from "../../utils/utils";
import {download, exitFull, getToken, requestFullScreen} from "../../utils/utils";
import './Access.css'
import Draggable from 'react-draggable';
@ -87,7 +87,9 @@ class Access extends Component {
confirmLoading: false,
uploadVisible: false,
uploadLoading: false,
startTime: new Date()
startTime: new Date(),
fullScreen: false,
fullScreenBtnText: '进入全屏'
};
async componentDidMount() {
@ -345,6 +347,7 @@ class Access extends Component {
return true;
}
console.log('--------------------')
console.log(keysym)
this.state.client.sendKeyEvent(1, keysym);
if (keysym === 65288) {
@ -370,6 +373,24 @@ class Access extends Component {
});
};
fullScreen = () => {
let fs = this.state.fullScreen;
if(fs){
exitFull();
this.setState({
fullScreen: false,
fullScreenBtnText: '进入全屏'
})
}else {
requestFullScreen(document.documentElement);
this.setState({
fullScreen: true,
fullScreenBtnText: '退出全屏'
})
}
}
showClipboard = () => {
this.setState({
clipboardVisible: true
@ -823,11 +844,18 @@ class Access extends Component {
<Menu.Item key="2" icon={<FileZipOutlined/>} onClick={this.showFileSystem}>
文件管理
</Menu.Item>
<Menu.Item key="3" icon={<ExpandOutlined />} onClick={this.fullScreen}>
{this.state.fullScreenBtnText}
</Menu.Item>
<SubMenu title="发送快捷键" icon={<DesktopOutlined/>}>
<Menu.Item
onClick={() => this.sendCombinationKey(['65507', '65513', '65535'])}>Ctrl+Alt+Delete</Menu.Item>
<Menu.Item
onClick={() => this.sendCombinationKey(['65507', '65513', '65288'])}>Ctrl+Alt+Backspace</Menu.Item>
<Menu.Item
onClick={() => this.sendCombinationKey(['65515', '114'])}>Windows+R</Menu.Item>
<Menu.Item
onClick={() => this.sendCombinationKey(['65515'])}>Windows</Menu.Item>
</SubMenu>
</Menu>
);
@ -892,22 +920,6 @@ class Access extends Component {
</Affix>
</Draggable>
{/*{*/}
{/* this.state.protocol === 'ssh' || this.state.protocol === 'rdp' ?*/}
{/* <Affix style={{position: 'absolute', top: 50, right: 50}}>*/}
{/* <Button*/}
{/* shape="circle"*/}
{/* icon={<FolderOpenOutlined/>}*/}
{/* onClick={() => {*/}
{/* this.showFileSystem();*/}
{/* }}*/}
{/* >*/}
{/* </Button>*/}
{/* </Affix>*/}
{/* : null*/}
{/*}*/}
<Drawer
title={title}
placement="right"

View File

@ -1,16 +1,16 @@
import React, {Component} from 'react';
import "xterm/css/xterm.css"
import {Terminal} from "xterm";
import {AttachAddon} from 'xterm-addon-attach';
import qs from "qs";
import {wsServer} from "../../common/constants";
import "./Console.css"
import {getToken} from "../../utils/utils";
import {FitAddon} from 'xterm-addon-fit'
function getGeometry(width, height) {
const cols = Math.floor(width / 9);
const rows = Math.floor(height / 17);
const rows = Math.floor(height / 17) - 1;
return [cols, rows];
}
@ -18,9 +18,11 @@ class Console extends Component {
state = {
containerOverflow: 'hidden',
containerWidth: 0,
containerHeight: 0,
term: null,
width: 0,
height: 0,
term: undefined,
webSocket: undefined,
fitAddon: undefined
};
componentDidMount() {
@ -30,9 +32,6 @@ class Console extends Component {
let width = this.props.width;
let height = this.props.height;
// let width = Math.floor(window.innerWidth * scale);
// let height = Math.floor(window.innerHeight * scale);
let params = {
'width': width,
'height': height,
@ -41,66 +40,127 @@ class Console extends Component {
let paramStr = qs.stringify(params);
let [cols, rows] = getGeometry(width, height);
const ua = navigator.userAgent.toLowerCase();
let lineHeight = 1;
if (ua.includes('windows')) {
lineHeight = 1.1;
}
let term = new Terminal({
cols: cols,
rows: rows,
// screenKeys: true,
// fontFamily: 'menlo',
fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
fontSize: 14,
lineHeight: lineHeight,
theme: {
background: '#1b1b1b'
},
rightClickSelectsWord: true,
});
// let fitAddon = new FitAddon();
// term.loadAddon(fitAddon);
let fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(this.refs.terminal);
// fitAddon.fit();
term.writeln('正在努力连接服务器中...');
term.writeln('Trying to connect to the server ...');
term.onResize(e => {
});
term.onData(data => {
let webSocket = this.state.webSocket;
if (webSocket !== undefined) {
webSocket.send(JSON.stringify({type: 'data', content: data}));
}
});
let token = getToken();
let webSocket = new WebSocket(wsServer + '/ssh?X-Auth-Token=' + token + '&' + paramStr);
term.loadAddon(new AttachAddon(webSocket));
this.props.appendWebsocket(webSocket);
this.props.appendWebsocket({'id': assetId, 'ws': webSocket});
webSocket.onopen = (e => {
term.clear();
term.focus();
if (command !== '') {
webSocket.send(command + String.fromCharCode(13));
}
this.onWindowResize();
});
webSocket.onerror = (e) => {
term.writeln("Failed to connect to server.");
}
webSocket.onclose = (e) => {
term.writeln("Connection is closed.");
}
let executedCommand = false
webSocket.onmessage = (e) => {
let msg = JSON.parse(e.data);
switch (msg['type']) {
case 'data':
term.write(msg['content']);
break;
case 'closed':
term.writeln(`\x1B[1;3;31m${msg['content']}\x1B[0m `)
webSocket.close();
break;
}
if (!executedCommand) {
if (command !== '') {
let webSocket = this.state.webSocket;
if (webSocket !== undefined && webSocket.readyState === WebSocket.OPEN) {
webSocket.send(JSON.stringify({type: 'data', content: command + String.fromCharCode(13)}));
}
}
executedCommand = true;
}
}
this.setState({
term: term,
containerWidth: width,
containerHeight: height
fitAddon: fitAddon,
webSocket: webSocket,
width: width,
height: height
});
// window.addEventListener('resize', this.onWindowResize);
window.addEventListener('resize', this.onWindowResize);
}
componentWillUnmount() {
let webSocket = this.state.webSocket;
if (webSocket) {
webSocket.close()
}
}
onWindowResize = (e) => {
let term = this.state.term;
if (term) {
const [cols, rows] = getGeometry(this.state.containerWidth, this.state.containerHeight);
term.resize(cols, rows);
let fitAddon = this.state.fitAddon;
let webSocket = this.state.webSocket;
if (term && fitAddon && webSocket) {
let height = term.cols;
let width = term.rows;
try {
fitAddon.fit();
} catch (e) {
console.log(e);
}
term.focus();
if(webSocket.readyState === WebSocket.OPEN){
webSocket.send(JSON.stringify({type: 'resize', content: JSON.stringify({height, width})}));
}
}
};
render() {
return (
<div>
<div ref='terminal' style={{
<div ref='terminal' id='terminal' style={{
overflow: this.state.containerOverflow,
width: this.state.containerWidth,
height: this.state.containerHeight,
backgroundColor: 'black'
width: this.state.width,
height: this.state.height,
backgroundColor: '#1b1b1b'
}}/>
</div>
);