U 优化模版管理

pull/418/head
vapao 2021-12-02 10:57:44 +08:00
parent 981fa28505
commit 375ac435e2
7 changed files with 57 additions and 23 deletions

View File

@ -12,6 +12,7 @@ class ExecTemplate(models.Model, ModelMixin):
type = models.CharField(max_length=50)
body = models.TextField()
interpreter = models.CharField(max_length=20)
host_ids = models.TextField(default='[]')
desc = models.CharField(max_length=255, null=True)
created_at = models.CharField(max_length=20, default=human_datetime)
@ -22,6 +23,11 @@ class ExecTemplate(models.Model, ModelMixin):
def __repr__(self):
return '<ExecTemplate %r>' % self.name
def to_view(self):
tmp = self.to_dict()
tmp['host_ids'] = json.loads(self.host_ids)
return tmp
class Meta:
db_table = 'exec_templates'
ordering = ('-id',)

View File

@ -18,7 +18,7 @@ class TemplateView(View):
def get(self, request):
templates = ExecTemplate.objects.all()
types = [x['type'] for x in templates.order_by('type').values('type').distinct()]
return json_response({'types': types, 'templates': [x.to_dict() for x in templates]})
return json_response({'types': types, 'templates': [x.to_view() for x in templates]})
@auth('exec.template.add|exec.template.edit')
def post(self, request):
@ -28,6 +28,7 @@ class TemplateView(View):
Argument('type', help='请选择模版类型'),
Argument('body', help='请输入模版内容'),
Argument('interpreter', default='sh'),
Argument('host_ids', type=list, handler=json.dumps, default=[]),
Argument('desc', required=False)
).parse(request.body)
if error is None:

View File

@ -32,28 +32,33 @@ class TemplateSelector extends React.Component {
handleSubmit = () => {
if (this.state.selectedRows.length > 0) {
const {body, interpreter} = this.state.selectedRows[0]
this.props.onOk(body, interpreter)
const {host_ids, body, interpreter} = this.state.selectedRows[0]
this.props.onOk(host_ids, body, interpreter)
}
this.props.onCancel()
};
columns = [{
title: '类型',
dataIndex: 'type',
}, {
title: '名称',
dataIndex: 'name',
ellipsis: true
}, {
title: '内容',
dataIndex: 'body',
ellipsis: true
}, {
title: '备注',
dataIndex: 'desc',
ellipsis: true
}];
columns = [
{
title: '名称',
dataIndex: 'name',
ellipsis: true
}, {
title: '类型',
dataIndex: 'type',
}, {
title: '目标主机',
dataIndex: 'host_ids',
render: v => `${v.length}`
}, {
title: '内容',
dataIndex: 'body',
ellipsis: true
}, {
title: '备注',
dataIndex: 'desc',
ellipsis: true
}];
render() {
const {selectedRows} = this.state;
@ -84,7 +89,7 @@ class TemplateSelector extends React.Component {
<Input allowClear value={store.f_name} onChange={e => store.f_name = e.target.value} placeholder="请输入"/>
</SearchForm.Item>
<SearchForm.Item span={8}>
<Button type="primary" icon={<SyncOutlined />} onClick={store.fetchRecords}>刷新</Button>
<Button type="primary" icon={<SyncOutlined/>} onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item>
</SearchForm>
<Table

View File

@ -29,6 +29,15 @@ function TaskIndex() {
}
}, [loading])
useEffect(() => {
return () => {
store.host_ids = []
if (store.showConsole) {
store.switchConsole()
}
}
}, [])
function handleSubmit() {
setLoading(true)
const host_ids = store.host_ids;
@ -37,7 +46,8 @@ function TaskIndex() {
.finally(() => setLoading(false))
}
function handleTemplate(command, interpreter) {
function handleTemplate(host_ids, command, interpreter) {
if (host_ids.length > 0) store.host_ids = host_ids
setInterpreter(interpreter)
setCommand(command)
}

View File

@ -8,6 +8,7 @@ import { observer } from 'mobx-react';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { Modal, Form, Input, Select, Button, Radio, message } from 'antd';
import { ACEditor } from 'components';
import Selector from 'pages/host/Selector';
import { http, cleanCommand } from 'libs';
import store from './store';
@ -15,12 +16,14 @@ export default observer(function () {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [body, setBody] = useState(store.record.body);
const [visible, setVisible] = useState(false);
function handleSubmit() {
setLoading(true);
const formData = form.getFieldsValue();
formData['id'] = store.record.id;
formData['body'] = cleanCommand(body);
formData['host_ids'] = store.record.host_ids;
http.post('/api/exec/template/', formData)
.then(res => {
message.success('操作成功');
@ -91,10 +94,19 @@ export default observer(function () {
height="300px"/>
)}
</Form.Item>
<Form.Item label="目标主机">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => setVisible(true)}>选择主机</Button>
</Form.Item>
<Form.Item name="desc" label="备注信息">
<Input.TextArea placeholder="请输入模板备注信息"/>
</Form.Item>
</Form>
<Selector
visible={visible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => setVisible(false)}
onOk={(_, ids) => info.host_ids = ids}/>
</Modal>
)
})

View File

@ -69,7 +69,7 @@ class ComTable extends React.Component {
<Table.Column title="操作" render={info => (
<Action>
<Action.Button auth="exec.template.edit" onClick={() => store.showForm(info)}>编辑</Action.Button>
<Action.Button auth="exec.template.del" onClick={() => this.handleDelete(info)}>删除</Action.Button>
<Action.Button danger auth="exec.template.del" onClick={() => this.handleDelete(info)}>删除</Action.Button>
</Action>
)}/>
)}

View File

@ -26,7 +26,7 @@ class Store {
.finally(() => this.isFetching = false)
};
showForm = (info = {interpreter: 'sh'}) => {
showForm = (info = {interpreter: 'sh', host_ids: []}) => {
this.formVisible = true;
this.record = info
}