mirror of
https://github.com/whyour/qinglong.git
synced 2025-07-27 14:46:06 +08:00
add terminal input stdio
This commit is contained in:
parent
418695c4aa
commit
659078f9d6
|
@ -1,5 +1,6 @@
|
|||
import { Service, Inject } from 'typedi';
|
||||
import winston from 'winston';
|
||||
import { Connection } from 'sockjs';
|
||||
import nodeSchedule from 'node-schedule';
|
||||
import { ChildProcessWithoutNullStreams } from 'child_process';
|
||||
import {
|
||||
|
@ -33,6 +34,7 @@ export interface TaskCallbacks {
|
|||
) => Promise<void>;
|
||||
onLog?: (message: string) => Promise<void>;
|
||||
onError?: (message: string) => Promise<void>;
|
||||
onMessage?:(cb:(msg:string,conn:Connection)=>void)=>void;
|
||||
}
|
||||
|
||||
@Service()
|
||||
|
@ -120,6 +122,10 @@ export default class ScheduleService {
|
|||
);
|
||||
resolve({ ...others, pid: cp.pid, code });
|
||||
});
|
||||
|
||||
callbacks.onMessage?.((msg:string,conn:Connection)=>{
|
||||
cp.stdin.write(JSON.parse(msg).message)
|
||||
})
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
'[panel][执行任务失败] 命令: %s, 错误信息: %j',
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Service, Inject } from 'typedi';
|
||||
import { Connection } from 'sockjs';
|
||||
import winston from 'winston';
|
||||
import path, { join } from 'path';
|
||||
import SockService from './sock';
|
||||
|
@ -22,6 +23,7 @@ export default class ScriptService {
|
|||
return {
|
||||
onEnd: async (cp, endTime, diff) => {
|
||||
await rmPath(filePath);
|
||||
this.sockService.removeAllListeners('message')
|
||||
},
|
||||
onError: async (message: string) => {
|
||||
this.sockService.sendMessage({
|
||||
|
@ -35,6 +37,10 @@ export default class ScriptService {
|
|||
message,
|
||||
});
|
||||
},
|
||||
onMessage:(cb:(msg:string,conn:Connection)=>void)=>{
|
||||
this.sockService.off('message',cb)
|
||||
this.sockService.on('message',cb)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,15 @@ import { Service, Inject } from 'typedi';
|
|||
import winston from 'winston';
|
||||
import { Connection } from 'sockjs';
|
||||
import { SockMessage } from '../data/sock';
|
||||
import EventEmitter from 'events';
|
||||
|
||||
@Service()
|
||||
export default class SockService {
|
||||
export default class SockService extends EventEmitter{
|
||||
private clients: Connection[] = [];
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) { }
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {
|
||||
super()
|
||||
}
|
||||
|
||||
public getClients() {
|
||||
return this.clients;
|
||||
|
@ -16,11 +19,17 @@ export default class SockService {
|
|||
public addClient(conn: Connection) {
|
||||
if (this.clients.indexOf(conn) === -1) {
|
||||
this.clients.push(conn);
|
||||
|
||||
conn.on('data',(msg:string)=>{
|
||||
this.emit('message',msg,conn)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public removeClient(conn: Connection) {
|
||||
const index = this.clients.indexOf(conn);
|
||||
conn.removeAllListeners('data')
|
||||
|
||||
if (index !== -1) {
|
||||
this.clients.splice(index, 1);
|
||||
}
|
||||
|
|
|
@ -486,5 +486,7 @@
|
|||
"NPM 镜像源": "NPM Mirror Source",
|
||||
"PyPI 镜像源": "PyPI Mirror Source",
|
||||
"alpine linux 镜像源": "Alpine Linux Mirror Source",
|
||||
"如果恢复失败,可进入容器执行": "If recovery fails, you can enter the container and execute"
|
||||
"如果恢复失败,可进入容器执行": "If recovery fails, you can enter the container and execute",
|
||||
"终端输入": "terminal input",
|
||||
"发送": "send"
|
||||
}
|
||||
|
|
|
@ -486,5 +486,7 @@
|
|||
"NPM 镜像源": "NPM 镜像源",
|
||||
"PyPI 镜像源": "PyPI 镜像源",
|
||||
"alpine linux 镜像源": "alpine linux 镜像源",
|
||||
"如果恢复失败,可进入容器执行": "如果恢复失败,可进入容器执行"
|
||||
"如果恢复失败,可进入容器执行": "如果恢复失败,可进入容器执行",
|
||||
"终端输入": "终端输入",
|
||||
"发送": "发送"
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import React, {
|
|||
useCallback,
|
||||
useReducer,
|
||||
} from 'react';
|
||||
import { Drawer, Button, Tabs, Badge, Select, TreeSelect } from 'antd';
|
||||
import { Drawer, Button, Tabs, Badge, Select, TreeSelect, Input } from 'antd';
|
||||
import { request } from '@/utils/http';
|
||||
import config from '@/utils/config';
|
||||
import SplitPane from 'react-split-pane';
|
||||
|
@ -41,6 +41,7 @@ const EditModal = ({
|
|||
const [settingModalVisible, setSettingModalVisible] =
|
||||
useState<boolean>(false);
|
||||
const [log, setLog] = useState('');
|
||||
const [raw, setRaw] = useState('')
|
||||
const { theme } = useTheme();
|
||||
const editorRef = useRef<any>(null);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
|
@ -124,6 +125,12 @@ const EditModal = ({
|
|||
setLog((p) => `${p}${_message}`);
|
||||
}, []);
|
||||
|
||||
const send=()=>{
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.send({ type:'terminalInput', message:raw })
|
||||
setRaw('')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('manuallyRunScript', handleMessage);
|
||||
|
@ -253,6 +260,12 @@ const EditModal = ({
|
|||
padding: '0 15px',
|
||||
}}
|
||||
>
|
||||
<div style={{ minWidth: 0, display: 'flex', alignItems: 'center', gap:'8px' }}>
|
||||
<Input placeholder={intl.get('终端输入')} value={raw} onChange={(e)=>{
|
||||
setRaw(e.target.value)
|
||||
}}></Input>
|
||||
<Button type="primary" onClick={send}>{intl.get('发送')}</Button>
|
||||
</div>
|
||||
<Ansi>{log}</Ansi>
|
||||
</pre>
|
||||
</SplitPane>
|
||||
|
|
|
@ -7,4 +7,5 @@ export type SockMessageType =
|
|||
| 'runSubscriptionEnd'
|
||||
| 'reloadSystem'
|
||||
| 'updateNodeMirror'
|
||||
| 'updateLinuxMirror';
|
||||
| 'updateLinuxMirror'
|
||||
| 'terminalInput';
|
||||
|
|
Loading…
Reference in New Issue
Block a user