diff --git a/spug_api/apps/host/views.py b/spug_api/apps/host/views.py index e2cf399..d7f27b4 100644 --- a/spug_api/apps/host/views.py +++ b/spug_api/apps/host/views.py @@ -98,22 +98,30 @@ class HostView(View): def delete(self, request): form, error = JsonParser( - Argument('id', type=int, help='请指定操作对象') + Argument('id', type=int, required=False), + Argument('group_id', type=int, required=False), ).parse(request.GET) if error is None: - deploy = Deploy.objects.filter(host_ids__regex=fr'[^0-9]{form.id}[^0-9]').annotate( - app_name=F('app__name'), - env_name=F('env__name') - ).first() - if deploy: - return json_response(error=f'应用【{deploy.app_name}】在【{deploy.env_name}】的发布配置关联了该主机,请解除关联后再尝试删除该主机') - task = Task.objects.filter(targets__regex=fr'[^0-9]{form.id}[^0-9]').first() - if task: - return json_response(error=f'任务计划中的任务【{task.name}】关联了该主机,请解除关联后再尝试删除该主机') - detection = Detection.objects.filter(type__in=('3', '4'), targets__regex=fr'[^0-9]{form.id}[^0-9]').first() - if detection: - return json_response(error=f'监控中心的任务【{detection.name}】关联了该主机,请解除关联后再尝试删除该主机') - Host.objects.filter(pk=form.id).delete() + if form.id: + host_ids = [form.id] + elif form.group_id: + group = Group.objects.get(pk=form.group_id) + host_ids = [x.id for x in group.hosts.all()] + else: + return json_response(error='参数错误') + for host_id in host_ids: + regex = fr'[^0-9]{host_id}[^0-9]' + deploy = Deploy.objects.filter(host_ids__regex=regex) \ + .annotate(app_name=F('app__name'), env_name=F('env__name')).first() + if deploy: + return json_response(error=f'应用【{deploy.app_name}】在【{deploy.env_name}】的发布配置关联了该主机,请解除关联后再尝试删除该主机') + task = Task.objects.filter(targets__regex=fr'[^0-9]{form.id}[^0-9]').first() + if task: + return json_response(error=f'任务计划中的任务【{task.name}】关联了该主机,请解除关联后再尝试删除该主机') + detection = Detection.objects.filter(type__in=('3', '4'), targets__regex=regex).first() + if detection: + return json_response(error=f'监控中心的任务【{detection.name}】关联了该主机,请解除关联后再尝试删除该主机') + Host.objects.filter(id__in=host_ids).delete() return json_response(error=error) diff --git a/spug_web/src/pages/host/Group.js b/spug_web/src/pages/host/Group.js index 89257ef..42a7815 100644 --- a/spug_web/src/pages/host/Group.js +++ b/spug_web/src/pages/host/Group.js @@ -5,13 +5,14 @@ */ import React, { useState, useEffect } from 'react'; import { observer } from 'mobx-react'; -import { Input, Card, Tree, Dropdown, Menu, Switch, Tooltip, message } from 'antd'; +import { Input, Card, Tree, Dropdown, Menu, Switch, Tooltip, Modal } from 'antd'; import { FolderOutlined, FolderAddOutlined, EditOutlined, DeleteOutlined, CopyOutlined, + CloseOutlined, ScissorOutlined, LoadingOutlined, QuestionCircleOutlined @@ -50,19 +51,32 @@ export default observer(function () { } onClick={() => store.showSelector(true)}>添加至分组 } onClick={() => store.showSelector(false)}>移动至分组 - } danger onClick={handleRemove}>删除此分组 + } danger onClick={handleRemoveHosts}>删除主机 + } danger onClick={handleRemove}>删除此分组 ) function handleSubmit() { - if (!store.group.title) { - return message.error('请输入分组名称') + if (store.group.title) { + setLoading(true); + const {key, parent_id, title} = store.group; + http.post('/api/host/group/', {id: key || undefined, parent_id, name: title}) + .then(() => setAction('')) + .finally(() => setLoading(false)) + } else { + if (store.group.key === 0) store.treeData = bakTreeData + setAction('') } - setLoading(true); - const {key, parent_id, title} = store.group; - http.post('/api/host/group/', {id: key || undefined, parent_id, name: title}) - .then(() => setAction('')) - .finally(() => setLoading(false)) + } + + function handleRemoveHosts() { + const group = store.group; + Modal.confirm({ + title: '操作确认', + content: `批量删除【${group.title}】分组内的 ${group.all_host_ids.length} 个主机?`, + onOk: () => http.delete('/api/host/', {params: {group_id: group.key}}) + .then(store.initial) + }) } function handleRemove() { @@ -102,13 +116,6 @@ export default observer(function () { .then(() => setLoading(false)) } - function handleBlur() { - if (store.group.key === 0) { - store.treeData = bakTreeData - } - setAction('') - } - function handleRightClick(v) { if (hasPermission('admin')) { store.group = v.node; @@ -131,7 +138,7 @@ export default observer(function () { defaultValue={nodeData.title} suffix={loading ? : } onClick={e => e.stopPropagation()} - onBlur={handleBlur} + onBlur={handleSubmit} onChange={e => store.group.title = e.target.value} onPressEnter={handleSubmit}/> } else if (action === 'del' && nodeData.key === store.group.key) {