优化HostSelector组件

pull/605/head
vapao 2022-11-06 22:46:11 +08:00
parent 4cb86923d6
commit 06479a8e45
13 changed files with 190 additions and 196 deletions

View File

@ -9,7 +9,7 @@ import { Link } from 'react-router-dom';
import { Switch, Form, Input, Select, Button, Radio } from 'antd'; import { Switch, Form, Input, Select, Button, Radio } from 'antd';
import Repo from './Repo'; import Repo from './Repo';
import envStore from 'pages/config/environment/store'; import envStore from 'pages/config/environment/store';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import store from './store'; import store from './store';
export default observer(function Ext1Setup1() { export default observer(function Ext1Setup1() {
@ -62,8 +62,7 @@ export default observer(function Ext1Setup1() {
</Form.Item> </Form.Item>
</Form.Item> </Form.Item>
<Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。"> <Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>} <HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
<Button type="link" style={{padding: 0}} onClick={() => store.selectorVisible = true}>选择主机</Button>
</Form.Item> </Form.Item>
<Form.Item required label="Git仓库地址" extra={<span className="btn" onClick={() => setVisible(true)}>私有仓库</span>}> <Form.Item required label="Git仓库地址" extra={<span className="btn" onClick={() => setVisible(true)}>私有仓库</span>}>
<Input disabled={store.isReadOnly} value={info['git_repo']} onChange={e => info['git_repo'] = e.target.value} <Input disabled={store.isReadOnly} value={info['git_repo']} onChange={e => info['git_repo'] = e.target.value}
@ -116,11 +115,6 @@ export default observer(function Ext1Setup1() {
disabled={!(info.env_id && info.git_repo && info.host_ids.length)} disabled={!(info.env_id && info.git_repo && info.host_ids.length)}
onClick={() => store.page += 1}>下一步</Button> onClick={() => store.page += 1}>下一步</Button>
</Form.Item> </Form.Item>
<Selector
visible={store.selectorVisible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => store.selectorVisible = false}
onOk={(_, ids) => info.host_ids = ids}/>
{visible && <Repo url={info['git_repo']} onOk={v => info['git_repo'] = v} onCancel={() => setVisible(false)}/>} {visible && <Repo url={info['git_repo']} onOk={v => info['git_repo'] = v} onCancel={() => setVisible(false)}/>}
</Form> </Form>
) )

View File

@ -8,12 +8,11 @@ import { observer } from 'mobx-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Form, Switch, Select, Button, Input, Radio } from 'antd'; import { Form, Switch, Select, Button, Input, Radio } from 'antd';
import envStore from 'pages/config/environment/store'; import envStore from 'pages/config/environment/store';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import store from './store'; import store from './store';
export default observer(function Ext2Setup1() { export default observer(function Ext2Setup1() {
const [envs, setEnvs] = useState([]); const [envs, setEnvs] = useState([]);
const [selectorVisible, setSelectorVisible] = useState(false);
function updateEnvs() { function updateEnvs() {
const ids = store.currentRecord['deploys'].map(x => x.env_id); const ids = store.currentRecord['deploys'].map(x => x.env_id);
@ -61,8 +60,7 @@ export default observer(function Ext2Setup1() {
</Form.Item> </Form.Item>
</Form.Item> </Form.Item>
<Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。"> <Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>} <HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
<Button type="link" style={{padding: 0}} onClick={() => setSelectorVisible(true)}>选择主机</Button>
</Form.Item> </Form.Item>
<Form.Item label="发布模式" tooltip="串行即发布时一台完成后再发布下一台,期间出现异常则终止发布。并行则每个主机相互独立发布同时进行。"> <Form.Item label="发布模式" tooltip="串行即发布时一台完成后再发布下一台,期间出现异常则终止发布。并行则每个主机相互独立发布同时进行。">
<Radio.Group <Radio.Group
@ -110,11 +108,6 @@ export default observer(function Ext2Setup1() {
disabled={!(info.env_id && info.host_ids.length)} disabled={!(info.env_id && info.host_ids.length)}
onClick={() => store.page += 1}>下一步</Button> onClick={() => store.page += 1}>下一步</Button>
</Form.Item> </Form.Item>
<Selector
visible={selectorVisible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => setSelectorVisible(false)}
onOk={(_, ids) => info.host_ids = ids}/>
</Form> </Form>
) )
}) })

View File

@ -20,7 +20,6 @@ class Store {
@observable ext1Visible = false; @observable ext1Visible = false;
@observable ext2Visible = false; @observable ext2Visible = false;
@observable autoVisible = false; @observable autoVisible = false;
@observable selectorVisible = false;
@observable f_name; @observable f_name;
@observable f_desc; @observable f_desc;

View File

@ -6,9 +6,9 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { PlusOutlined, ThunderboltOutlined, BulbOutlined, QuestionCircleOutlined } from '@ant-design/icons'; import { PlusOutlined, ThunderboltOutlined, BulbOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Form, Button, Alert, Radio, Tooltip } from 'antd'; import { Form, Button, Radio, Tooltip } from 'antd';
import { ACEditor, AuthDiv, Breadcrumb } from 'components'; import { ACEditor, AuthDiv, Breadcrumb } from 'components';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import TemplateSelector from './TemplateSelector'; import TemplateSelector from './TemplateSelector';
import Parameter from './Parameter'; import Parameter from './Parameter';
import Output from './Output'; import Output from './Output';
@ -87,17 +87,7 @@ function TaskIndex() {
<div className={style.index} hidden={store.showConsole}> <div className={style.index} hidden={store.showConsole}>
<Form layout="vertical" className={style.left}> <Form layout="vertical" className={style.left}>
<Form.Item required label="目标主机"> <Form.Item required label="目标主机">
{store.host_ids.length > 0 ? ( <HostSelector type="button" value={store.host_ids} onChange={(_, ids) => store.host_ids = ids}/>
<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> </Form.Item>
<Form.Item required label="执行命令" style={{position: 'relative'}}> <Form.Item required label="执行命令" style={{position: 'relative'}}>
@ -144,12 +134,6 @@ function TaskIndex() {
{store.showTemplate && <TemplateSelector onCancel={store.switchTemplate} onOk={handleTemplate}/>} {store.showTemplate && <TemplateSelector onCancel={store.switchTemplate} onOk={handleTemplate}/>}
{store.showConsole && <Output onBack={store.switchConsole}/>} {store.showConsole && <Output onBack={store.switchConsole}/>}
{visible && <Parameter parameters={parameters} onCancel={() => setVisible(false)} onOk={v => handleSubmit(v)}/>} {visible && <Parameter parameters={parameters} onCancel={() => setVisible(false)} onOk={v => handleSubmit(v)}/>}
<Selector
visible={store.showHost}
selectedRowKeys={[...store.host_ids]}
onCancel={() => store.showHost = false}
onOk={(_, ids) => store.host_ids = ids}/>
</AuthDiv> </AuthDiv>
) )
} }

View File

@ -10,12 +10,6 @@
width: 60%; width: 60%;
border-right: 1px solid #dfdfdf; border-right: 1px solid #dfdfdf;
.area {
cursor: pointer;
width: 200px;
height: 32px;
}
.tips { .tips {
position: absolute; position: absolute;
top: 10px; top: 10px;

View File

@ -11,7 +11,6 @@ class Store {
@observable tag = ''; @observable tag = '';
@observable host_ids = []; @observable host_ids = [];
@observable token = null; @observable token = null;
@observable showHost = false;
@observable showConsole = false; @observable showConsole = false;
@observable showTemplate = false; @observable showTemplate = false;
@ -50,10 +49,6 @@ class Store {
} }
} }
switchHost = () => {
this.showHost = !this.showHost;
};
switchTemplate = () => { switchTemplate = () => {
this.showTemplate = !this.showTemplate this.showTemplate = !this.showTemplate
}; };

View File

@ -8,7 +8,7 @@ import { observer } from 'mobx-react';
import { ExclamationCircleOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import { ExclamationCircleOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import { Modal, Form, Input, Select, Button, Radio, Table, Tooltip, message } from 'antd'; import { Modal, Form, Input, Select, Button, Radio, Table, Tooltip, message } from 'antd';
import { ACEditor } from 'components'; import { ACEditor } from 'components';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import Parameter from './Parameter'; import Parameter from './Parameter';
import { http, cleanCommand } from 'libs'; import { http, cleanCommand } from 'libs';
import lds from 'lodash'; import lds from 'lodash';
@ -20,7 +20,6 @@ export default observer(function () {
const [body, setBody] = useState(S.record.body); const [body, setBody] = useState(S.record.body);
const [parameter, setParameter] = useState(); const [parameter, setParameter] = useState();
const [parameters, setParameters] = useState([]); const [parameters, setParameters] = useState([]);
const [visible, setVisible] = useState(false);
useEffect(() => { useEffect(() => {
setParameters(S.record.parameters) setParameters(S.record.parameters)
@ -136,18 +135,12 @@ export default observer(function () {
<Button type="link" style={{padding: 0}} onClick={() => setParameter({})}>添加参数</Button> <Button type="link" style={{padding: 0}} onClick={() => setParameter({})}>添加参数</Button>
</Form.Item> </Form.Item>
<Form.Item label="目标主机"> <Form.Item label="目标主机">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>} <HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
<Button type="link" style={{padding: 0}} onClick={() => setVisible(true)}>选择主机</Button>
</Form.Item> </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}/>
{parameter ? ( {parameter ? (
<Parameter <Parameter
parameter={parameter} parameter={parameter}

View File

@ -6,16 +6,15 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { import {
PlusOutlined,
ThunderboltOutlined, ThunderboltOutlined,
QuestionCircleOutlined, QuestionCircleOutlined,
UploadOutlined, UploadOutlined,
CloudServerOutlined, CloudServerOutlined,
BulbOutlined, BulbOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Form, Button, Alert, Tooltip, Space, Card, Table, Input, Upload, message } from 'antd'; import { Form, Button, Tooltip, Space, Card, Table, Input, Upload, message } from 'antd';
import { AuthDiv, Breadcrumb } from 'components'; import { AuthDiv, Breadcrumb } from 'components';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import Output from './Output'; import Output from './Output';
import { http, uniqueId } from 'libs'; import { http, uniqueId } from 'libs';
import moment from 'moment'; import moment from 'moment';
@ -27,7 +26,6 @@ function TransferIndex() {
const [files, setFiles] = useState([]) const [files, setFiles] = useState([])
const [dir, setDir] = useState('') const [dir, setDir] = useState('')
const [hosts, setHosts] = useState([]) const [hosts, setHosts] = useState([])
const [sProps, setSProps] = useState({visible: false})
const [percent, setPercent] = useState() const [percent, setPercent] = useState()
const [token, setToken] = useState() const [token, setToken] = useState()
const [histories, setHistories] = useState([]) const [histories, setHistories] = useState([])
@ -80,23 +78,14 @@ function TransferIndex() {
}) })
} }
function handleAddHostFile() { function makeFile(row) {
setSProps({ setFiles([{
visible: true, id: uniqueId(),
onlyOne: true, type: 'host',
selectedRowKeys: [], name: row.name,
onCancel: () => setSProps({visible: false}), path: '',
onOk: (_, __, row) => setFiles([{id: uniqueId(), type: 'host', name: row.name, path: '', host_id: row.id}]), host_id: row.id
}) }])
}
function handleAddHost() {
setSProps({
visible: true,
selectedRowKeys: hosts.map(x => x.id),
onCancel: () => setSProps({visible: false}),
onOk: (_, __, rows) => setHosts(rows),
})
} }
function handleUpload(_, fileList) { function handleUpload(_, fileList) {
@ -131,7 +120,9 @@ function TransferIndex() {
<Card type="inner" title={`数据源${files.length ? `${files.length}` : ''}`} extra={(<Space size={24}> <Card type="inner" title={`数据源${files.length ? `${files.length}` : ''}`} extra={(<Space size={24}>
<Upload multiple beforeUpload={handleUpload}><Space <Upload multiple beforeUpload={handleUpload}><Space
className="btn"><UploadOutlined/>上传本地文件</Space></Upload> className="btn"><UploadOutlined/>上传本地文件</Space></Upload>
<Space className="btn" onClick={handleAddHostFile}><CloudServerOutlined/>添加主机文件</Space> <HostSelector onlyOne onChange={(_, __, row) => makeFile(row)}>
<Space className="btn"><CloudServerOutlined/>添加主机文件</Space>
</HostSelector>
</Space>)}> </Space>)}>
<Table rowKey="id" className={style.table} showHeader={false} pagination={false} size="small" <Table rowKey="id" className={style.table} showHeader={false} pagination={false} size="small"
dataSource={files}> dataSource={files}>
@ -153,13 +144,7 @@ function TransferIndex() {
<Input value={dir} onChange={e => setDir(e.target.value)} placeholder="请输入目标路径"/> <Input value={dir} onChange={e => setDir(e.target.value)} placeholder="请输入目标路径"/>
</Form.Item> </Form.Item>
<Form.Item required label="目标主机"> <Form.Item required label="目标主机">
{hosts.length > 0 ? (<Alert <HostSelector type="button" value={hosts.map(x => x.id)} onChange={(_, __, rows) => setHosts(rows)}/>
type="info"
className={style.area}
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{hosts.length}</b> </div>}
onClick={handleAddHost}/>) : (<Button icon={<PlusOutlined/>} onClick={handleAddHost}>
添加目标主机
</Button>)}
</Form.Item> </Form.Item>
</Form> </Form>
</Card> </Card>
@ -191,7 +176,6 @@ function TransferIndex() {
</div> </div>
</div> </div>
</div> </div>
<Selector {...sProps}/>
{token ? <Output token={token} onBack={handleCloseOutput}/> : null} {token ? <Output token={token} onBack={handleCloseOutput}/> : null}
</AuthDiv>) </AuthDiv>)
} }

View File

@ -5,15 +5,15 @@
*/ */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Modal, Row, Col, Tree, Table, Button, Space, Input } from 'antd'; import { Modal, Row, Col, Tree, Table, Button, Space, Input, Alert } from 'antd';
import { FolderOpenOutlined, FolderOutlined } from '@ant-design/icons'; import { FolderOpenOutlined, FolderOutlined, PlusOutlined } from '@ant-design/icons';
import IPAddress from './IPAddress'; import IPAddress from './IPAddress';
import hStore from './store'; import hStore from './store';
import store from './store2'; import store from './store2';
import styles from './index.module.less'; import styles from './selector.module.less';
function HostSelector(props) {
export default observer(function (props) { const [visible, setVisible] = useState(false)
const [isReady, setIsReady] = useState(false) const [isReady, setIsReady] = useState(false)
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedRowKeys, setSelectedRowKeys] = useState([]);
@ -42,8 +42,8 @@ export default observer(function (props) {
}, [store.treeData]) }, [store.treeData])
useEffect(() => { useEffect(() => {
setSelectedRowKeys(props.selectedRowKeys || []) setSelectedRowKeys([...props.value])
}, [props.selectedRowKeys]) }, [props.value])
useEffect(() => { useEffect(() => {
if (props.onlySelf) { if (props.onlySelf) {
@ -62,20 +62,19 @@ export default observer(function (props) {
} }
function handleSubmit() { function handleSubmit() {
if (props.onOk) { if (props.onChange) {
setLoading(true); setLoading(true);
let res let res
const selectedRows = store.rawRecords.filter(x => selectedRowKeys.includes(x.id)) const selectedRows = store.rawRecords.filter(x => selectedRowKeys.includes(x.id))
if (props.onlyOne) { if (props.onlyOne) {
res = props.onOk(store.group, selectedRowKeys[0], selectedRows[0]) res = props.onChange(store.group, selectedRowKeys[0], selectedRows[0])
} else { } else {
res = props.onOk(store.group, selectedRowKeys, selectedRows); res = props.onChange(store.group, selectedRowKeys, selectedRows);
} }
if (res && res.then) { if (res && res.then) {
res.then(props.onCancel, () => setLoading(false)) res.then(handleClose, () => setLoading(false))
} else { } else {
props.onCancel(); handleClose()
setLoading(false)
} }
} }
} }
@ -109,16 +108,45 @@ export default observer(function (props) {
) )
} }
function handleClose() {
setSelectedRowKeys([])
setLoading(false)
setVisible(false)
}
return ( return (
<div className={styles.selector}>
{props.children ? (
<div onClick={() => setVisible(true)}>{props.children}</div>
) : (
props.type === 'button' ? (
props.value.length > 0 ? (
<Alert
type="info"
className={styles.area}
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{props.value.length}</b> </div>}
onClick={() => setVisible(true)}/>
) : (
<Button icon={<PlusOutlined/>} onClick={() => setVisible(true)}>
添加目标主机
</Button>
)) : (
<div style={{display: 'flex', alignItems: 'center'}}>
{props.value.length > 0 && <span style={{marginRight: 16}}>已选择 {props.value.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => setVisible(true)}>选择主机</Button>
</div>
)
)}
<Modal <Modal
visible={[undefined, true].includes(props.visible)} visible={visible}
width={1000} width={1000}
className={styles.selector} className={styles.modal}
title={props.title || '主机列表'} title={props.title || '主机列表'}
onOk={handleSubmit} onOk={handleSubmit}
okButtonProps={{disabled: selectedRowKeys.length === 0}} okButtonProps={{disabled: selectedRowKeys.length === 0}}
confirmLoading={loading} confirmLoading={loading}
onCancel={props.onCancel}> onCancel={handleClose}>
<Row> <Row>
<Col span={6} style={{borderRight: '8px solid #f0f0f0', paddingRight: 12}}> <Col span={6} style={{borderRight: '8px solid #f0f0f0', paddingRight: 12}}>
<div className={styles.gTitle}>分组列表</div> <div className={styles.gTitle}>分组列表</div>
@ -171,5 +199,13 @@ export default observer(function (props) {
</Col> </Col>
</Row> </Row>
</Modal> </Modal>
</div>
) )
}) }
HostSelector.defaultProps = {
value: [],
type: 'text'
}
export default observer(HostSelector)

View File

@ -26,21 +26,6 @@
} }
} }
.selector {
:global(.ant-modal-footer) {
border-top: none
}
.gTitle {
height: 44px;
line-height: 44px;
padding-left: 12px;
font-weight: bold;
margin-bottom: 12px;
background: #fafafa;
}
}
.formAddress1 { .formAddress1 {
display: inline-block; display: inline-block;

View File

@ -0,0 +1,46 @@
.modal {
:global(.ant-modal-footer) {
border-top: none
}
.gTitle {
height: 44px;
line-height: 44px;
padding-left: 12px;
font-weight: bold;
margin-bottom: 12px;
background: #fafafa;
}
}
.area {
cursor: pointer;
width: 200px;
height: 32px;
}
.treeNode {
display: flex;
flex-direction: row;
align-items: center;
.title {
margin-left: 8px;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.number {
width: 30px;
text-align: right;
}
}

View File

@ -8,7 +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, message } from 'antd'; import { Modal, Form, Input, Select, Button, message } from 'antd';
import TemplateSelector from '../exec/task/TemplateSelector'; import TemplateSelector from '../exec/task/TemplateSelector';
import Selector from 'pages/host/Selector'; import HostSelector from 'pages/host/Selector';
import { LinkButton, ACEditor } from 'components'; import { LinkButton, ACEditor } from 'components';
import { http, cleanCommand } from 'libs'; import { http, cleanCommand } from 'libs';
import store from './store'; import store from './store';
@ -22,7 +22,6 @@ const helpMap = {
export default observer(function () { export default observer(function () {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [showTmp, setShowTmp] = useState(false); const [showTmp, setShowTmp] = useState(false);
const [showSelector, setShowSelector] = useState(false);
function handleTest() { function handleTest() {
setLoading(true) setLoading(true)
@ -131,10 +130,7 @@ export default observer(function () {
notFoundContent={null}/> notFoundContent={null}/>
</Form.Item> </Form.Item>
<Form.Item required label="监控主机" style={getStyle(['3', '4'])}> <Form.Item required label="监控主机" style={getStyle(['3', '4'])}>
{store.record.targets?.length > 0 && ( <HostSelector value={targets} onChange={(_, ids) => store.record.targets = ids}/>
<span style={{marginRight: 16}}>已选择 {store.record.targets.length} </span>
)}
<Button type="link" style={{padding: 0}} onClick={() => setShowSelector(true)}>选择主机</Button>
</Form.Item> </Form.Item>
<Form.Item label="响应时间" style={getStyle(['1'])}> <Form.Item label="响应时间" style={getStyle(['1'])}>
<Input suffix="ms" value={extra} placeholder="最长响应时间毫秒不设置则默认10秒超时" <Input suffix="ms" value={extra} placeholder="最长响应时间毫秒不设置则默认10秒超时"
@ -168,11 +164,6 @@ export default observer(function () {
<span style={{color: '#888', fontSize: 12}}>Tips: 仅测试第一个监控地址</span> <span style={{color: '#888', fontSize: 12}}>Tips: 仅测试第一个监控地址</span>
</Form.Item> </Form.Item>
{showTmp && <TemplateSelector onOk={({body}) => store.record.extra = body} onCancel={() => setShowTmp(false)}/>} {showTmp && <TemplateSelector onOk={({body}) => store.record.extra = body} onCancel={() => setShowTmp(false)}/>}
<Selector
visible={showSelector}
selectedRowKeys={[...store.record.targets]}
onCancel={() => setShowSelector(false)}
onOk={(_, ids) => store.record.targets = ids}/>
</Form> </Form>
) )
}) })

View File

@ -3,7 +3,7 @@
* Copyright (c) <spug.dev@gmail.com> * Copyright (c) <spug.dev@gmail.com>
* Released under the AGPL-3.0 License. * Released under the AGPL-3.0 License.
*/ */
import React, { useState } from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Form, Select, Button } from 'antd'; import { Form, Select, Button } from 'antd';
@ -13,7 +13,12 @@ import hostStore from 'pages/host/store';
import styles from './index.module.css'; import styles from './index.module.css';
export default observer(function () { export default observer(function () {
const [visible, setVisible] = useState(false) function handleChange(_, ids) {
if (store.targets.includes('local')) {
ids.unshift('local')
}
store.targets = ids
}
return ( return (
<React.Fragment> <React.Fragment>
@ -43,15 +48,10 @@ export default observer(function () {
))} ))}
</Form.Item> </Form.Item>
<Form.Item wrapperCol={{span: 14, offset: 6}}> <Form.Item wrapperCol={{span: 14, offset: 6}}>
<Button type="dashed" style={{width: '80%'}} onClick={() => setVisible(true)}> <HostSelector value={store.targets.filter(x => x !== 'local')} onChange={handleChange}>
<PlusOutlined/>添加执行对象 <Button type="dashed" style={{width: '80%'}}><PlusOutlined/>添加执行对象</Button>
</Button> </HostSelector>
</Form.Item> </Form.Item>
<HostSelector
visible={visible}
selectedRowKeys={[...store.targets]}
onCancel={() => setVisible(false)}
onOk={(_, ids) => store.targets = ids}/>
</Form> </Form>
<Form.Item wrapperCol={{span: 14, offset: 6}}> <Form.Item wrapperCol={{span: 14, offset: 6}}>
<Button disabled={store.targets.filter(x => x).length === 0} type="primary" <Button disabled={store.targets.filter(x => x).length === 0} type="primary"