diff --git a/spug_api/apps/host/group.py b/spug_api/apps/host/group.py index 39e74ef..f11f894 100644 --- a/spug_api/apps/host/group.py +++ b/spug_api/apps/host/group.py @@ -20,6 +20,7 @@ def fetch_children(data): def merge_children(data, prefix, childes): for item in childes: name = f'{prefix}/{item["title"]}' + item['name'] = name if item['children']: merge_children(data, name, item['children']) else: @@ -36,8 +37,9 @@ class GroupView(View): grp = Group.objects.create(name='Default', sort_id=1) data[grp.id] = grp.to_view() - merge_children(data2, '', data.values()) - return json_response({'treeData': list(data.values()), 'groups': data2}) + data = list(data.values()) + merge_children(data2, '', data) + return json_response({'treeData': data, 'groups': data2}) def post(self, request): form, error = JsonParser( diff --git a/spug_api/apps/host/models.py b/spug_api/apps/host/models.py index 74ab617..e235a55 100644 --- a/spug_api/apps/host/models.py +++ b/spug_api/apps/host/models.py @@ -10,7 +10,6 @@ from libs.ssh import SSH class Host(models.Model, ModelMixin): name = models.CharField(max_length=50) - zone = models.CharField(max_length=50) hostname = models.CharField(max_length=50) port = models.IntegerField() username = models.CharField(max_length=50) @@ -52,6 +51,7 @@ class Group(models.Model, ModelMixin): def to_view(self): return { 'key': self.id, + 'value': self.id, 'title': self.name, 'children': [] } diff --git a/spug_api/apps/host/views.py b/spug_api/apps/host/views.py index a2cb17f..07de7c8 100644 --- a/spug_api/apps/host/views.py +++ b/spug_api/apps/host/views.py @@ -33,7 +33,7 @@ class HostView(View): def post(self, request): form, error = JsonParser( Argument('id', type=int, required=False), - Argument('zone', help='请输入主机类型'), + Argument('group_ids', type=list, filter=lambda x: len(x), help='请选择主机分组'), Argument('name', help='请输主机名称'), Argument('username', handler=str.strip, help='请输入登录用户名'), Argument('hostname', handler=str.strip, help='请输入主机名或IP'), @@ -47,14 +47,16 @@ class HostView(View): pkey=form.pkey) is False: return json_response('auth fail') - if form.id: - Host.objects.filter(pk=form.pop('id')).update(**form) - elif Host.objects.filter(name=form.name, deleted_by_id__isnull=True).exists(): + group_ids = form.pop('group_ids') + other = Host.objects.filter(name=form.name, deleted_by_id__isnull=True).first() + if other and (not form.id or other.id != form.id): return json_response(error=f'已存在的主机名称【{form.name}】') + if form.id: + Host.objects.filter(pk=form.id).update(**form) + host = Host.objects.get(pk=form.id) else: host = Host.objects.create(created_by=request.user, **form) - if request.user.role: - request.user.role.add_host_perm(host.id) + host.groups.set(group_ids) return json_response(error=error) def patch(self, request): diff --git a/spug_web/src/pages/host/Detail.js b/spug_web/src/pages/host/Detail.js new file mode 100644 index 0000000..f50e728 --- /dev/null +++ b/spug_web/src/pages/host/Detail.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { observer } from 'mobx-react'; +import { Drawer} from 'antd'; +import store from './store'; + +export default observer(function () { + return ( + store.detailVisible = false} + visible={store.detailVisible}> + + + ) +}) \ No newline at end of file diff --git a/spug_web/src/pages/host/Form.js b/spug_web/src/pages/host/Form.js index a9e8247..886c01a 100644 --- a/spug_web/src/pages/host/Form.js +++ b/spug_web/src/pages/host/Form.js @@ -6,7 +6,7 @@ import React, { useState, useEffect } from 'react'; import { observer } from 'mobx-react'; import { ExclamationCircleOutlined, UploadOutlined } from '@ant-design/icons'; -import { Modal, Form, Input, Select, Button, Upload, message } from 'antd'; +import { Modal, Form, Input, TreeSelect, Button, Upload, Alert, message } from 'antd'; import { http, X_TOKEN } from 'libs'; import store from './store'; @@ -102,12 +102,13 @@ export default observer(function () { confirmLoading={loading} onOk={handleSubmit}>
- - + + @@ -133,7 +134,7 @@ export default observer(function () { - ⚠️ 首次验证时需要输入登录用户名对应的密码,但不会存储该密码。 + diff --git a/spug_web/src/pages/host/Table.js b/spug_web/src/pages/host/Table.js index b2ab70f..6aa69c5 100644 --- a/spug_web/src/pages/host/Table.js +++ b/spug_web/src/pages/host/Table.js @@ -62,7 +62,11 @@ class ComTable extends React.Component { showTotal: total => `共 ${total} 条`, pageSizeOptions: ['10', '20', '50', '100'] }}> - a.name.localeCompare(b.name)}/> + store.showDetail(info)}>{info.name}} + sorter={(a, b) => a.name.localeCompare(b.name)}/> a.name.localeCompare(b.name)}/> diff --git a/spug_web/src/pages/host/index.js b/spug_web/src/pages/host/index.js index 00c2947..a419faa 100644 --- a/spug_web/src/pages/host/index.js +++ b/spug_web/src/pages/host/index.js @@ -11,6 +11,7 @@ import Group from './Group'; import ComTable from './Table'; import ComForm from './Form'; import ComImport from './Import'; +import Detail from './Detail'; import store from './store'; export default observer(function () { @@ -30,6 +31,7 @@ export default observer(function () { + {store.formVisible && } {store.importVisible && } diff --git a/spug_web/src/pages/host/store.js b/spug_web/src/pages/host/store.js index ec62f1d..8365888 100644 --- a/spug_web/src/pages/host/store.js +++ b/spug_web/src/pages/host/store.js @@ -17,6 +17,7 @@ class Store { @observable isFetching = false; @observable formVisible = false; @observable importVisible = false; + @observable detailVisible = false; @observable f_name; @observable f_host; @@ -59,6 +60,11 @@ class Store { this.record = info } + showDetail = (info) => { + this.record = info; + this.detailVisible = true; + } + _updateGroupCount = () => { if (this.treeData.length && this.records.length) { const counter = {}; @@ -83,6 +89,7 @@ class Store { host_ids = host_ids.concat(this._updateCount(counter, child)) } item.host_ids = Array.from(new Set(host_ids)); + if (item.key === this.group.key) this.group = item; return item.host_ids } }