mirror of https://github.com/openspug/spug
U 优化批量执行UX
parent
38b77c77bb
commit
ddd1cb8cc1
|
@ -38,7 +38,7 @@ class Job:
|
|||
|
||||
def _handle_command(self, command, interpreter):
|
||||
if interpreter == 'python':
|
||||
return f'python << EOF\n{command}\nEOF'
|
||||
return f'python << EOF\n# -*- coding: UTF-8 -*-\n{command}\nEOF'
|
||||
return command
|
||||
|
||||
def send(self, data):
|
||||
|
@ -53,7 +53,7 @@ class Job:
|
|||
if not self.token:
|
||||
with self.ssh:
|
||||
return self.ssh.exec_command(self.command, self.env)
|
||||
self.send('\r\33[K\x1b[36m### Executing ...\x1b[0m\r\n')
|
||||
self.send('\r\n\x1b[36m### Executing ...\x1b[0m\r\n')
|
||||
code = -1
|
||||
try:
|
||||
with self.ssh:
|
||||
|
|
|
@ -36,7 +36,7 @@ function OutView(props) {
|
|||
term.loadAddon(fitPlugin)
|
||||
term.open(el.current)
|
||||
fitPlugin.fit()
|
||||
term.write('WebSocket connecting ... ')
|
||||
term.write('\x1b[36m### WebSocket connecting ...\x1b[0m')
|
||||
const resize = () => fitPlugin.fit();
|
||||
window.addEventListener('resize', resize)
|
||||
setTerm(term)
|
||||
|
@ -49,7 +49,11 @@ function OutView(props) {
|
|||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const socket = new WebSocket(`${protocol}//${window.location.host}/api/ws/exec/${store.token}/?x-token=${X_TOKEN}`);
|
||||
socket.onopen = () => {
|
||||
term.write('\r\x1b[K\x1b[36m### Waiting for scheduling ...\x1b[0m')
|
||||
const message = '\r\x1b[K\x1b[36m### Waiting for scheduling ...\x1b[0m'
|
||||
for (let key of Object.keys(store.outputs)) {
|
||||
store.outputs[key].data = message
|
||||
}
|
||||
term.write(message)
|
||||
socket.send('ok');
|
||||
}
|
||||
socket.onmessage = e => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { PlusOutlined, ThunderboltOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { PlusOutlined, ThunderboltOutlined, BulbOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { Form, Button, Alert, Radio, Tooltip } from 'antd';
|
||||
import { ACEditor, AuthDiv, Breadcrumb } from 'components';
|
||||
import Selector from 'pages/host/Selector';
|
||||
|
@ -68,14 +68,19 @@ function TaskIndex() {
|
|||
<div className={style.index} hidden={store.showConsole}>
|
||||
<Form layout="vertical" className={style.left}>
|
||||
<Form.Item required label="目标主机">
|
||||
{store.host_ids.length > 0 && (
|
||||
<Alert style={{width: 200}} type="info" message={`已选择 ${store.host_ids.length} 台主机`}/>
|
||||
{store.host_ids.length > 0 ? (
|
||||
<Alert
|
||||
type="info"
|
||||
className={style.area}
|
||||
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{store.host_ids.length}</b> 台主机</div>}
|
||||
onClick={() => store.showHost = true}/>
|
||||
) : (
|
||||
<Button icon={<PlusOutlined/>} onClick={() => store.showHost = true}>
|
||||
从主机列表中选择
|
||||
</Button>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Button
|
||||
style={{marginBottom: 24}}
|
||||
icon={<PlusOutlined/>}
|
||||
onClick={() => store.showHost = true}>从主机列表中选择</Button>
|
||||
|
||||
<Form.Item required label="执行命令" style={{position: 'relative'}}>
|
||||
<Radio.Group
|
||||
buttonStyle="solid"
|
||||
|
@ -86,12 +91,10 @@ function TaskIndex() {
|
|||
<Radio.Button value="python">Python</Radio.Button>
|
||||
</Radio.Group>
|
||||
<a href="https://spug.cc/docs/batch-exec" target="_blank" rel="noopener noreferrer"
|
||||
className={style.tips}>全局变量</a>
|
||||
className={style.tips}><BulbOutlined/> 使用全局变量?</a>
|
||||
<Button style={{float: 'right'}} icon={<PlusOutlined/>} onClick={store.switchTemplate}>从执行模版中选择</Button>
|
||||
<ACEditor className={style.editor} mode={interpreter} value={command} width="100%" onChange={setCommand}/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button icon={<PlusOutlined/>} onClick={store.switchTemplate}>从执行模版中选择</Button>
|
||||
</Form.Item>
|
||||
<Button loading={loading} icon={<ThunderboltOutlined/>} type="primary" onClick={handleSubmit}>开始执行</Button>
|
||||
</Form>
|
||||
|
||||
|
|
|
@ -8,14 +8,21 @@
|
|||
padding: 24px;
|
||||
width: 60%;
|
||||
|
||||
.area {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 180px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.editor {
|
||||
height: calc(100vh - 588px) !important;
|
||||
height: calc(100vh - 482px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class Store {
|
|||
const host = hostStore.idMap[id];
|
||||
this.outputs[host.id] = {
|
||||
title: `${host.name}(${host.hostname}:${host.port})`,
|
||||
data: '',
|
||||
data: '\x1b[36m### WebSocket connecting ...\x1b[0m',
|
||||
status: -2
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue