{
this.setState({
- fileSystemVisible: false
+ fileSystemVisible: false,
+ enterBtnIndex: 1001, // xterm.js 输入框的zIndex是1000,在隐藏文件管理页面后要显示此按钮
});
}}
visible={this.state.fileSystemVisible}
diff --git a/web/src/components/asset/Asset.js b/web/src/components/asset/Asset.js
index 0c39582..5d50347 100644
--- a/web/src/components/asset/Asset.js
+++ b/web/src/components/asset/Asset.js
@@ -355,10 +355,10 @@ class Asset extends Component {
window.open(`#/access?assetId=${id}&assetName=${name}&protocol=${protocol}`);
}
} else {
- message.warn('您访问的资产未在线,请确认网络状态。', 10);
+ message.warn({content: '您访问的资产未在线,请确认网络状态。', key: id, duration: 10});
}
} else {
- message.error('操作失败 :( ' + result.message, 10);
+ message.error({content: result.message, key: id, duration: 10});
}
}
diff --git a/web/src/components/command/ChooseAsset.js b/web/src/components/command/ChooseAsset.js
new file mode 100644
index 0000000..e647bd6
--- /dev/null
+++ b/web/src/components/command/ChooseAsset.js
@@ -0,0 +1,427 @@
+import React, {Component} from 'react';
+
+import {
+ Badge,
+ Button,
+ Col,
+ Divider,
+ Input,
+ Layout,
+ Modal,
+ Row,
+ Select,
+ Space,
+ Table,
+ Tag,
+ Tooltip,
+ Typography
+} from "antd";
+import qs from "qs";
+import request from "../../common/request";
+import {message} from "antd/es";
+
+
+import {PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons';
+import {PROTOCOL_COLORS} from "../../common/constants";
+import {isEmpty} from "../../utils/utils";
+import dayjs from "dayjs";
+
+const confirm = Modal.confirm;
+const {Search} = Input;
+const {Content} = Layout;
+const {Title, Text} = Typography;
+
+class ChooseAsset extends Component {
+
+ inputRefOfName = React.createRef();
+ inputRefOfIp = React.createRef();
+ changeOwnerFormRef = React.createRef();
+
+ state = {
+ items: [],
+ total: 0,
+ queryParams: {
+ pageIndex: 1,
+ pageSize: 10,
+ protocol: 'ssh'
+ },
+ loading: false,
+ tags: [],
+ model: {},
+ selectedRowKeys: [],
+ selectedRows: [],
+ delBtnLoading: false,
+ changeOwnerModalVisible: false,
+ changeSharerModalVisible: false,
+ changeOwnerConfirmLoading: false,
+ changeSharerConfirmLoading: false,
+ users: [],
+ selected: {},
+ totalSelectedRows: [],
+ };
+
+ checkedAssets = undefined
+
+ async componentDidMount() {
+ this.checkedAssets = this.props.setCheckedAssets;
+ this.loadTableData();
+ let result = await request.get('/tags');
+ if (result['code'] === 1) {
+ this.setState({
+ tags: result['data']
+ })
+ }
+ }
+
+ async loadTableData(queryParams) {
+ this.setState({
+ loading: true
+ });
+
+ queryParams = queryParams || this.state.queryParams;
+
+ // queryParams
+ let paramsStr = qs.stringify(queryParams);
+
+ let data = {
+ items: [],
+ total: 0
+ };
+
+ try {
+ let result = await request.get('/assets/paging?' + paramsStr);
+ if (result['code'] === 1) {
+ data = result['data'];
+ } else {
+ message.error(result['message']);
+ }
+ } catch (e) {
+
+ } finally {
+ let sharer = this.state.sharer;
+ const items = data.items.map(item => {
+ let disabled = false;
+ if (sharer === item['owner']) {
+ disabled = true;
+ }
+ return {...item, 'key': item['id'], 'disabled': disabled}
+ })
+ let totalSelectedRows = this.state.totalSelectedRows;
+ let selectedRowKeys = totalSelectedRows.map(item => item['id']);
+ this.setState({
+ items: items,
+ total: data.total,
+ queryParams: queryParams,
+ loading: false,
+ selectedRowKeys: selectedRowKeys
+ });
+ }
+ }
+
+ handleChangPage = async (pageIndex, pageSize) => {
+ let queryParams = this.state.queryParams;
+ queryParams.pageIndex = pageIndex;
+ queryParams.pageSize = pageSize;
+
+ this.setState({
+ queryParams: queryParams
+ });
+
+ await this.loadTableData(queryParams)
+ };
+
+ handleSearchByName = name => {
+ let query = {
+ ...this.state.queryParams,
+ 'pageIndex': 1,
+ 'pageSize': this.state.queryParams.pageSize,
+ 'name': name,
+ }
+
+ this.loadTableData(query);
+ };
+
+ handleSearchByIp = ip => {
+ let query = {
+ ...this.state.queryParams,
+ 'pageIndex': 1,
+ 'pageSize': this.state.queryParams.pageSize,
+ 'ip': ip,
+ }
+
+ this.loadTableData(query);
+ };
+
+ handleTagsChange = tags => {
+ console.log(tags)
+ // this.setState({
+ // tags: tags
+ // })
+ let query = {
+ ...this.state.queryParams,
+ 'pageIndex': 1,
+ 'pageSize': this.state.queryParams.pageSize,
+ 'tags': tags.join(','),
+ }
+
+ this.loadTableData(query);
+ }
+
+ unSelectRow = async (assetId) => {
+ const selectedRowKeys = this.state.selectedRowKeys.filter(key => key !== assetId);
+ const totalSelectedRows = this.state.totalSelectedRows.filter(item => item['id'] !== assetId);
+ this.setState({
+ selectedRowKeys: selectedRowKeys,
+ totalSelectedRows: totalSelectedRows
+ })
+ }
+
+ render() {
+
+ const columns = [{
+ title: '序号',
+ dataIndex: 'id',
+ key: 'id',
+ render: (id, record, index) => {
+ return index + 1;
+ }
+ }, {
+ title: '资产名称',
+ dataIndex: 'name',
+ key: 'name',
+ render: (name, record) => {
+ let short = name;
+ if (short && short.length > 20) {
+ short = short.substring(0, 20) + " ...";
+ }
+ return (
+
+ {short}
+
+ );
+ }
+ }, {
+ title: '连接协议',
+ dataIndex: 'protocol',
+ key: 'protocol',
+ render: (text, record) => {
+ const title = `${record['ip'] + ':' + record['port']}`
+ return (
+
+ {text}
+
+ )
+ }
+ }, {
+ title: '标签',
+ dataIndex: 'tags',
+ key: 'tags',
+ render: tags => {
+ if (!isEmpty(tags)) {
+ let tagDocuments = []
+ let tagArr = tags.split(',');
+ for (let i = 0; i < tagArr.length; i++) {
+ if (tags[i] === '-') {
+ continue;
+ }
+ tagDocuments.push({tagArr[i]})
+ }
+ return tagDocuments;
+ }
+ }
+ }, {
+ title: '状态',
+ dataIndex: 'active',
+ key: 'active',
+ render: text => {
+
+ if (text) {
+ return (
+
+
+
+ )
+ } else {
+ return (
+
+
+
+ )
+ }
+ }
+ }, {
+ title: '所有者',
+ dataIndex: 'ownerName',
+ key: 'ownerName'
+ }, {
+ title: '创建日期',
+ dataIndex: 'created',
+ key: 'created',
+ render: (text, record) => {
+ return (
+
+ {dayjs(text).fromNow()}
+
+ )
+ }
+ },
+ ];
+
+ const selectedRowKeys = this.state.selectedRowKeys;
+ const rowSelection = {
+ selectedRowKeys: this.state.selectedRowKeys,
+ onChange: (selectedRowKeys, selectedRows) => {
+ this.setState({selectedRowKeys, selectedRows});
+ },
+ getCheckboxProps: (record) => ({
+ disabled: record['disabled'],
+ }),
+ };
+ let hasSelected = false;
+ if (selectedRowKeys.length > 0) {
+ let totalSelectedRows = this.state.totalSelectedRows;
+ let allSelectedRowKeys = totalSelectedRows.map(item => item['id']);
+ for (let i = 0; i < selectedRowKeys.length; i++) {
+ let selectedRowKey = selectedRowKeys[i];
+ if (!allSelectedRowKeys.includes(selectedRowKey)) {
+ hasSelected = true;
+ break;
+ }
+ }
+ }
+
+ return (
+ <>
+ 已选择资产列表
+
+ {
+ this.state.totalSelectedRows.map(item => {
+ return this.unSelectRow(item['id'])}
+ key={item['id']}>{item['name']}
+ })
+ }
+
+
+
+
+
+
+
+ 全部资产列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `总计 ${total} 条`
+ }}
+ loading={this.state.loading}
+ />
+
+ >
+ );
+ }
+}
+
+export default ChooseAsset;
diff --git a/web/src/components/command/DynamicCommand.js b/web/src/components/command/DynamicCommand.js
index 08eea4d..c7161bc 100644
--- a/web/src/components/command/DynamicCommand.js
+++ b/web/src/components/command/DynamicCommand.js
@@ -32,10 +32,10 @@ import {
SyncOutlined,
UndoOutlined
} from '@ant-design/icons';
-import {compare} from "../../utils/utils";
import {hasPermission, isAdmin} from "../../service/permission";
import dayjs from "dayjs";
+import ChooseAsset from "./ChooseAsset";
const confirm = Modal.confirm;
const {Content} = Layout;
@@ -191,6 +191,12 @@ class DynamicCommand extends Component {
});
};
+ setCheckedAssets = (checkedAssets) => {
+ this.setState({
+ checkedAssets: checkedAssets
+ })
+ }
+
executeCommand = e => {
let checkedAssets = this.state.checkedAssets;
if (checkedAssets.length === 0) {
@@ -198,18 +204,10 @@ class DynamicCommand extends Component {
return;
}
- let assets = this.state.assets;
let cAssets = checkedAssets.map(item => {
- let name = '';
- for (let i = 0; i < assets.length; i++) {
- if (assets[i]['id'] === item) {
- name = assets[i]['name'];
- break;
- }
- }
return {
- id: item,
- name: name
+ id: item['id'],
+ name: item['name']
}
});
@@ -474,17 +472,6 @@ class DynamicCommand extends Component {
assetsVisible: true,
commandId: record['id']
});
-
- let result = await request.get('/assets?protocol=ssh');
- if (result.code === 1) {
- let assets = result.data;
- assets.sort(compare('name'));
- this.setState({
- assets: assets
- });
- } else {
- message.error(result.message);
- }
}}>执行
@@ -640,7 +627,8 @@ class DynamicCommand extends Component {
{
this.setState({
@@ -648,19 +636,11 @@ class DynamicCommand extends Component {
});
}}
>
-
- 全选
-
-
+
- {
- return {
- label: item.name,
- value: item.id,
- key: item.id,
- }
- })} value={this.state.checkedAssets} onChange={this.onChange}/>
+
diff --git a/web/src/components/command/DynamicCommandModal.js b/web/src/components/command/DynamicCommandModal.js
index deb776c..7855292 100644
--- a/web/src/components/command/DynamicCommandModal.js
+++ b/web/src/components/command/DynamicCommandModal.js
@@ -21,6 +21,7 @@ const DynamicCommandModal = ({title, visible, handleOk, handleCancel, confirmLoa
title={title}
visible={visible}
maskClosable={false}
+
onOk={() => {
form
.validateFields()
diff --git a/web/src/components/credential/CredentialModal.js b/web/src/components/credential/CredentialModal.js
index 874e722..32f06f8 100644
--- a/web/src/components/credential/CredentialModal.js
+++ b/web/src/components/credential/CredentialModal.js
@@ -47,6 +47,7 @@ const CredentialModal = ({title, visible, handleOk, handleCancel, confirmLoading
title={title}
visible={visible}
maskClosable={false}
+
onOk={() => {
form
.validateFields()
diff --git a/web/src/components/devops/JobModal.js b/web/src/components/devops/JobModal.js
index 1246852..135baba 100644
--- a/web/src/components/devops/JobModal.js
+++ b/web/src/components/devops/JobModal.js
@@ -47,6 +47,7 @@ const JobModal = ({title, visible, handleOk, handleCancel, confirmLoading, model
title={title}
visible={visible}
maskClosable={false}
+
onOk={() => {
form
.validateFields()
diff --git a/web/src/components/devops/SecurityModal.js b/web/src/components/devops/SecurityModal.js
index f37f54d..6d54a3f 100644
--- a/web/src/components/devops/SecurityModal.js
+++ b/web/src/components/devops/SecurityModal.js
@@ -1,6 +1,5 @@
import React from 'react';
-import {Form, Input, InputNumber, Modal, Radio, Tooltip} from "antd/lib/index";
-import {ExclamationCircleOutlined} from "@ant-design/icons";
+import {Form, Input, InputNumber, Modal, Radio} from "antd/lib/index";
const formItemLayout = {
labelCol: {span: 6},
@@ -20,6 +19,7 @@ const SecurityModal = ({title, visible, handleOk, handleCancel, confirmLoading,
title={title}
visible={visible}
maskClosable={false}
+
onOk={() => {
form
.validateFields()
@@ -54,9 +54,7 @@ const SecurityModal = ({title, visible, handleOk, handleCancel, confirmLoading,
- 优先级
- } name='priority' rules={[{required: true, message: '请输入优先级'}]}>
+
diff --git a/web/src/components/user/User.js b/web/src/components/user/User.js
index 402bac1..44a9ef3 100644
--- a/web/src/components/user/User.js
+++ b/web/src/components/user/User.js
@@ -628,7 +628,6 @@ class User extends Component {
width={window.innerWidth * 0.8}
title='已授权资产'
visible={this.state.assetVisible}
-
maskClosable={false}
destroyOnClose={true}
onOk={() => {
@@ -649,7 +648,6 @@ class User extends Component {
{
this.changePasswordFormRef.current
.validateFields()
diff --git a/web/src/components/user/UserGroup.js b/web/src/components/user/UserGroup.js
index 5bc5af2..fef32e8 100644
--- a/web/src/components/user/UserGroup.js
+++ b/web/src/components/user/UserGroup.js
@@ -429,7 +429,6 @@ class UserGroup extends Component {
title='已授权资产'
visible={this.state.assetVisible}
maskClosable={false}
-
destroyOnClose={true}
onOk={() => {