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

View File

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

View File

@ -32,19 +32,24 @@ class TemplateSelector extends React.Component {
handleSubmit = () => { handleSubmit = () => {
if (this.state.selectedRows.length > 0) { if (this.state.selectedRows.length > 0) {
const {body, interpreter} = this.state.selectedRows[0] const {host_ids, body, interpreter} = this.state.selectedRows[0]
this.props.onOk(body, interpreter) this.props.onOk(host_ids, body, interpreter)
} }
this.props.onCancel() this.props.onCancel()
}; };
columns = [{ columns = [
title: '类型', {
dataIndex: 'type',
}, {
title: '名称', title: '名称',
dataIndex: 'name', dataIndex: 'name',
ellipsis: true ellipsis: true
}, {
title: '类型',
dataIndex: 'type',
}, {
title: '目标主机',
dataIndex: 'host_ids',
render: v => `${v.length}`
}, { }, {
title: '内容', title: '内容',
dataIndex: 'body', dataIndex: 'body',

View File

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

View File

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

View File

@ -69,7 +69,7 @@ class ComTable extends React.Component {
<Table.Column title="操作" render={info => ( <Table.Column title="操作" render={info => (
<Action> <Action>
<Action.Button auth="exec.template.edit" onClick={() => store.showForm(info)}>编辑</Action.Button> <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> </Action>
)}/> )}/>
)} )}

View File

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