优化批量执行指令和windows接入发送组合键
This commit is contained in:
@ -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"
|
||||
|
@ -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>
|
||||
);
|
||||
|
Reference in New Issue
Block a user