/** * Copyright (c) OpenSpug Organization. https://github.com/openspug/spug * Copyright (c) * Released under the AGPL-3.0 License. */ import React from 'react'; import { observer } from 'mobx-react'; import { CheckCircleTwoTone, LoadingOutlined, WarningTwoTone, FullscreenOutlined, FullscreenExitOutlined, CodeOutlined } from '@ant-design/icons'; import { Modal, Collapse, Tooltip } from 'antd'; import OutView from './OutView'; import { X_TOKEN } from 'libs'; import styles from './index.module.less'; import store from './store'; @observer class ExecConsole extends React.Component { constructor(props) { super(props); this.lastOutputs = {}; this.socket = null; this.terms = {}; this.outputs = {}; this.state = { activeKey: Object.keys(store.outputs)[0], isFullscreen: false } } componentDidMount() { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; this.socket = new WebSocket(`${protocol}//${window.location.host}/api/ws/exec/${store.token}/?x-token=${X_TOKEN}`); this.socket.onopen = () => { for (let key of Object.keys(store.outputs)) { this.handleWrite(key, '\x1b[36m### Waiting for scheduling ...\x1b[0m\r\n') } this.socket.send('ok'); }; this.socket.onmessage = e => { if (e.data === 'pong') { this.socket.send('ping') } else { const {key, data, status} = JSON.parse(e.data); if (status !== undefined) store.outputs[key].status = status; if (data) { this.handleWrite(key, data); const tmp = data.trim(); if (tmp) this.lastOutputs[key] = tmp.split('\r\n').slice(-1) } } }; this.socket.onerror = () => { for (let key of Object.keys(store.outputs)) { store.outputs[key]['status'] = 'websocket error' if (this.terms[key]) { this.terms[key].write('\x1b[31mWebsocket connection failed!\x1b[0m') } else { this.outputs[key] = '\x1b[31mWebsocket connection failed!\x1b[0m' } } } } componentWillUnmount() { this.socket.close(); store.isFullscreen = false; } handleWrite = (key, data) => { if (this.terms[key]) { this.terms[key].write(data) } else if (this.outputs[key]) { this.outputs[key] += data } else { this.outputs[key] = data } } StatusExtra = (props) => (
{props.status === -2 ? ( ) : ( <>
{this.lastOutputs[props.id]}
{props.status === 0 ? ( ) : ( )} )} this.openTerminal(e, props.id)}/>
) handleUpdate = (data) => { this.setState(data, () => { const key = this.state.activeKey; if (key && this.terms[key]) setTimeout(this.terms[key].fit) }) } openTerminal = (e, key) => { e.stopPropagation() window.open(`/ssh?id=${key}`) } render() { const {isFullscreen, activeKey} = this.state; return ( 执行控制台,
this.handleUpdate({isFullscreen: !isFullscreen})}> {isFullscreen ? : }
]} footer={null} onCancel={this.props.onCancel} onOk={this.handleSubmit} maskClosable={false}> this.handleUpdate({activeKey: key})}> {Object.entries(store.outputs).map(([key, item], index) => ( {item.title}} extra={}> this.outputs[key]} setTerm={term => this.terms[key] = term}/> ))}
) } } export default ExecConsole