完善文件管理
This commit is contained in:
parent
9b9dcf9b56
commit
1444891d96
@ -111,7 +111,6 @@ func SetupRoutes() *echo.Echo {
|
||||
sessions.GET("/:id/download", SessionDownloadEndpoint)
|
||||
sessions.GET("/:id/ls", SessionLsEndpoint)
|
||||
sessions.POST("/:id/mkdir", SessionMkDirEndpoint)
|
||||
sessions.DELETE("/:id/rmdir", SessionRmDirEndpoint)
|
||||
sessions.DELETE("/:id/rm", SessionRmEndpoint)
|
||||
sessions.DELETE("/:id", SessionDeleteEndpoint)
|
||||
sessions.GET("/:id/recording", SessionRecordingEndpoint)
|
||||
|
@ -476,63 +476,47 @@ func SessionMkDirEndpoint(c echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SessionRmDirEndpoint(c echo.Context) error {
|
||||
sessionId := c.Param("id")
|
||||
session, err := model.FindSessionById(sessionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remoteDir := c.QueryParam("dir")
|
||||
if "ssh" == session.Protocol {
|
||||
tun, ok := global.Store.Get(sessionId)
|
||||
if !ok {
|
||||
return errors.New("获取sftp客户端失败")
|
||||
}
|
||||
fileInfos, err := tun.Subject.SftpClient.ReadDir(remoteDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range fileInfos {
|
||||
if err := tun.Subject.SftpClient.Remove(path.Join(remoteDir, fileInfos[i].Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := tun.Subject.SftpClient.RemoveDirectory(remoteDir); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
} else if "rdp" == session.Protocol {
|
||||
drivePath, err := model.GetDrivePath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(path.Join(drivePath, remoteDir)); err != nil {
|
||||
return err
|
||||
}
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SessionRmEndpoint(c echo.Context) error {
|
||||
sessionId := c.Param("id")
|
||||
session, err := model.FindSessionById(sessionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remoteFile := c.QueryParam("file")
|
||||
key := c.QueryParam("key")
|
||||
if "ssh" == session.Protocol {
|
||||
tun, ok := global.Store.Get(sessionId)
|
||||
if !ok {
|
||||
return errors.New("获取sftp客户端失败")
|
||||
}
|
||||
if err := tun.Subject.SftpClient.Remove(remoteFile); err != nil {
|
||||
|
||||
sftpClient := tun.Subject.SftpClient
|
||||
|
||||
stat, err := sftpClient.Stat(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
fileInfos, err := tun.Subject.SftpClient.ReadDir(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range fileInfos {
|
||||
if err := tun.Subject.SftpClient.Remove(path.Join(key, fileInfos[i].Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := tun.Subject.SftpClient.RemoveDirectory(key); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := tun.Subject.SftpClient.Remove(key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return Success(c, nil)
|
||||
} else if "rdp" == session.Protocol {
|
||||
drivePath, err := model.GetDrivePath()
|
||||
@ -540,11 +524,13 @@ func SessionRmEndpoint(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.Remove(path.Join(drivePath, remoteFile)); err != nil {
|
||||
if err := os.RemoveAll(path.Join(drivePath, key)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Success(c, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,15 @@
|
||||
import React, {Component} from 'react';
|
||||
import Guacamole from 'guacamole-common-js';
|
||||
import {Affix, Button, Col, Drawer, Dropdown, Form, Input, Menu, message, Modal, Row, Space, Tooltip} from 'antd'
|
||||
import {Affix, Button, Col, Drawer, Dropdown, Form, Input, Menu, message, Modal, Row} from 'antd'
|
||||
import qs from "qs";
|
||||
import request from "../../common/request";
|
||||
import {wsServer} from "../../common/constants";
|
||||
import {
|
||||
AppstoreTwoTone,
|
||||
CloudDownloadOutlined,
|
||||
CloudUploadOutlined,
|
||||
CopyTwoTone,
|
||||
DeleteOutlined,
|
||||
DesktopOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
ExpandOutlined,
|
||||
FolderAddOutlined,
|
||||
LoadingOutlined,
|
||||
ReloadOutlined
|
||||
ExpandOutlined
|
||||
} from '@ant-design/icons';
|
||||
import {exitFull, getToken, isEmpty, requestFullScreen} from "../../utils/utils";
|
||||
import './Access.css'
|
||||
@ -48,9 +42,6 @@ class Access extends Component {
|
||||
uploadHeaders: {},
|
||||
keyboard: {},
|
||||
protocol: '',
|
||||
treeData: [],
|
||||
|
||||
confirmVisible: false,
|
||||
confirmLoading: false,
|
||||
uploadVisible: false,
|
||||
uploadLoading: false,
|
||||
@ -315,7 +306,7 @@ class Access extends Component {
|
||||
};
|
||||
|
||||
onKeyDown = (keysym) => {
|
||||
if (true === this.state.clipboardVisible || true === this.state.confirmVisible) {
|
||||
if (this.state.clipboardVisible || this.state.fileSystemVisible) {
|
||||
return true;
|
||||
}
|
||||
this.state.client.sendKeyEvent(1, keysym);
|
||||
@ -598,10 +589,10 @@ class Access extends Component {
|
||||
<Drawer
|
||||
title={'会话详情'}
|
||||
placement="right"
|
||||
width={window.innerWidth * 0.5}
|
||||
width={window.innerWidth * 0.8}
|
||||
closable={true}
|
||||
maskClosable={false}
|
||||
onClose={()=>{
|
||||
// maskClosable={false}
|
||||
onClose={() => {
|
||||
this.setState({
|
||||
fileSystemVisible: false
|
||||
});
|
||||
|
@ -5,14 +5,64 @@
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.selectedRow {
|
||||
background-color: #69c0ff;
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
transform: translateY(-25%);
|
||||
}
|
||||
50%{
|
||||
transform: translateY(4%);
|
||||
}
|
||||
65%{
|
||||
transform: translateY(-2%);
|
||||
}
|
||||
80%{
|
||||
transform: translateY(2%);
|
||||
}
|
||||
95%{
|
||||
transform: translateY(-1%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
.selectedRow > .ant-table-column-sort {
|
||||
background-color: #69c0ff;
|
||||
.popup {
|
||||
animation-name: fadeIn;
|
||||
animation-duration: 0.4s;
|
||||
background-clip: padding-box;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.75);
|
||||
left: 0;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
text-align: left;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
|
||||
.ant-table .ant-table-tbody > tr:hover:not(.ant-table-expanded-row .selectedRow) > td {
|
||||
background: #bae7ff;
|
||||
.popup li {
|
||||
clear: both;
|
||||
/*color: rgba(0, 0, 0, 0.65);*/
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
margin: 0;
|
||||
padding: 5px 12px;
|
||||
transition: all .3s;
|
||||
white-space: nowrap;
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
.popup li:hover {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
|
||||
.popup li > i {
|
||||
margin-right: 8px;
|
||||
}
|
@ -1,21 +1,22 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Button, Card, Form, Input, message, Modal, Row, Space, Table, Tooltip} from "antd";
|
||||
import {Button, Card, Col, Form, Input, message, Modal, Row, Space, Table, Tooltip} from "antd";
|
||||
import {
|
||||
CloudDownloadOutlined,
|
||||
CloudUploadOutlined,
|
||||
DeleteOutlined,
|
||||
FileExcelTwoTone,
|
||||
FileImageTwoTone,
|
||||
FileMarkdownTwoTone,
|
||||
FilePdfTwoTone,
|
||||
FileTextTwoTone,
|
||||
FileTwoTone,
|
||||
FileWordTwoTone,
|
||||
FileZipTwoTone,
|
||||
ExclamationCircleOutlined,
|
||||
FileExcelOutlined,
|
||||
FileImageOutlined,
|
||||
FileMarkdownOutlined,
|
||||
FileOutlined,
|
||||
FilePdfOutlined,
|
||||
FileTextOutlined,
|
||||
FileWordOutlined,
|
||||
FileZipOutlined,
|
||||
FolderAddOutlined,
|
||||
FolderTwoTone,
|
||||
LinkOutlined,
|
||||
ReloadOutlined,
|
||||
ThunderboltTwoTone,
|
||||
UploadOutlined
|
||||
} from "@ant-design/icons";
|
||||
import qs from "qs";
|
||||
@ -29,6 +30,7 @@ const formItemLayout = {
|
||||
labelCol: {span: 6},
|
||||
wrapperCol: {span: 14},
|
||||
};
|
||||
const {confirm} = Modal;
|
||||
|
||||
class FileSystem extends Component {
|
||||
|
||||
@ -40,7 +42,10 @@ class FileSystem extends Component {
|
||||
files: [],
|
||||
loading: false,
|
||||
selectedRowKeys: [],
|
||||
selectedRow: {}
|
||||
selectedRow: {},
|
||||
dropdown: {
|
||||
visible: false
|
||||
},
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -76,12 +81,6 @@ class FileSystem extends Component {
|
||||
})
|
||||
}
|
||||
|
||||
mkdir = () => {
|
||||
this.setState({
|
||||
confirmVisible: true
|
||||
})
|
||||
}
|
||||
|
||||
upload = () => {
|
||||
this.setState({
|
||||
uploadVisible: true
|
||||
@ -93,29 +92,40 @@ class FileSystem extends Component {
|
||||
}
|
||||
|
||||
rmdir = async () => {
|
||||
if (!this.state.selectedRow.key) {
|
||||
message.warning('请选择一个文件或目录');
|
||||
return;
|
||||
let selectedRowKeys = this.state.selectedRowKeys;
|
||||
if (selectedRowKeys === undefined || selectedRowKeys.length === 0) {
|
||||
message.warning('请至少选择一个文件或目录');
|
||||
}
|
||||
let result;
|
||||
if (this.state.selectedRow.isLeaf) {
|
||||
result = await request.delete(`/sessions/${this.state.sessionId}/rm?file=${this.state.selectedRow.key}`);
|
||||
|
||||
let title = '';
|
||||
if (selectedRowKeys.length === 1) {
|
||||
let file = selectedRowKeys[0].substring(selectedRowKeys[0].lastIndexOf('/') + 1, selectedRowKeys[0].length);
|
||||
title = <p>您确认要删除"{file}"吗?</p>;
|
||||
} else {
|
||||
result = await request.delete(`/sessions/${this.state.sessionId}/rmdir?dir=${this.state.selectedRow.key}`);
|
||||
title = `您确认要删除所选的${selectedRowKeys.length}项目吗?`;
|
||||
}
|
||||
if (result.code !== 1) {
|
||||
message.error(result.message);
|
||||
} else {
|
||||
message.success('删除成功');
|
||||
let path = this.state.selectedRow.key;
|
||||
let parentPath = path.substring(0, path.lastIndexOf('/'));
|
||||
let items = await this.getTreeNodes(parentPath);
|
||||
this.setState({
|
||||
treeData: this.updateTreeData(this.state.treeData, parentPath, items),
|
||||
selectedRow: {}
|
||||
confirm({
|
||||
title: title,
|
||||
icon: <ExclamationCircleOutlined/>,
|
||||
content: '所选项目将立即被删除。',
|
||||
onOk: async () => {
|
||||
for (let i = 0; i < selectedRowKeys.length; i++) {
|
||||
let rowKey = selectedRowKeys[i];
|
||||
if (rowKey === '..') {
|
||||
continue;
|
||||
}
|
||||
let result = await request.delete(`/sessions/${this.state.sessionId}/rm?key=${rowKey}`);
|
||||
if (result['code'] !== 1) {
|
||||
message.error(result['message']);
|
||||
}
|
||||
}
|
||||
await this.loadFiles(this.state.currentDirectory);
|
||||
},
|
||||
onCancel() {
|
||||
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
refresh = async () => {
|
||||
this.loadFiles(this.state.currentDirectory);
|
||||
@ -169,6 +179,34 @@ class FileSystem extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
getNodeTreeRightClickMenu = () => {
|
||||
const {pageX, pageY, visible} = {...this.state.dropdown};
|
||||
if (visible) {
|
||||
console.log(pageX, pageY)
|
||||
const tmpStyle = {
|
||||
left: `${pageX}px`,
|
||||
top: `${pageY}px`,
|
||||
};
|
||||
|
||||
let disableDownload = true;
|
||||
if (this.state.selectedRowKeys.length === 1
|
||||
&& !this.state.selectedRow['isDir']
|
||||
&& !this.state.selectedRow['isLink']) {
|
||||
disableDownload = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<ul className="popup" style={tmpStyle}>
|
||||
<li><Button type={'text'} size={'small'} icon={<CloudDownloadOutlined/>} onClick={this.download}
|
||||
disabled={disableDownload}>下载</Button></li>
|
||||
<li><Button type={'text'} size={'small'} icon={<DeleteOutlined/>} onClick={this.rmdir}>删除</Button>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const columns = [
|
||||
@ -182,17 +220,17 @@ class FileSystem extends Component {
|
||||
icon = <FolderTwoTone/>;
|
||||
} else {
|
||||
if (item['isLink']) {
|
||||
icon = <LinkOutlined/>;
|
||||
icon = <ThunderboltTwoTone/>;
|
||||
} else {
|
||||
const fileExtension = item['name'].split('.').pop().toLowerCase();
|
||||
switch (fileExtension) {
|
||||
case "doc":
|
||||
case "docx":
|
||||
icon = <FileWordTwoTone/>;
|
||||
icon = <FileWordOutlined/>;
|
||||
break;
|
||||
case "xls":
|
||||
case "xlsx":
|
||||
icon = <FileExcelTwoTone/>;
|
||||
icon = <FileExcelOutlined/>;
|
||||
break;
|
||||
case "bmp":
|
||||
case "jpg":
|
||||
@ -207,24 +245,25 @@ class FileSystem extends Component {
|
||||
case "psd":
|
||||
case "ai":
|
||||
case "webp":
|
||||
icon = <FileImageTwoTone/>;
|
||||
icon = <FileImageOutlined/>;
|
||||
break;
|
||||
case "md":
|
||||
icon = <FileMarkdownTwoTone/>;
|
||||
icon = <FileMarkdownOutlined/>;
|
||||
break;
|
||||
case "pdf":
|
||||
icon = <FilePdfTwoTone/>;
|
||||
icon = <FilePdfOutlined/>;
|
||||
break;
|
||||
case "txt":
|
||||
icon = <FileTextTwoTone/>;
|
||||
icon = <FileTextOutlined/>;
|
||||
break;
|
||||
case "zip":
|
||||
case "gz":
|
||||
case "tar":
|
||||
icon = <FileZipTwoTone/>;
|
||||
case "tgz":
|
||||
icon = <FileZipOutlined/>;
|
||||
break;
|
||||
default:
|
||||
icon = <FileTwoTone/>;
|
||||
icon = <FileOutlined/>;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -293,30 +332,28 @@ class FileSystem extends Component {
|
||||
];
|
||||
|
||||
const title = (
|
||||
<Row>
|
||||
<Row justify="space-around" align="middle" gutter={24}>
|
||||
<Col span={16} key={1}>
|
||||
{this.state.currentDirectory}
|
||||
</Col>
|
||||
<Col span={8} key={2} style={{textAlign: 'right'}}>
|
||||
<Space>
|
||||
远程文件管理
|
||||
|
||||
|
||||
<Tooltip title="创建文件夹">
|
||||
<Button type="primary" size="small" icon={<FolderAddOutlined/>}
|
||||
onClick={this.mkdir} ghost/>
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
mkdirVisible: true
|
||||
})
|
||||
}} ghost/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="上传">
|
||||
<Button type="primary" size="small" icon={<CloudUploadOutlined/>}
|
||||
onClick={this.upload} ghost/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="下载">
|
||||
<Button type="primary" size="small" icon={<CloudDownloadOutlined/>}
|
||||
disabled={isEmpty(this.state.selectedRow['key']) || this.state.selectedRow['isDir'] || this.state.selectedRow['isLink']}
|
||||
onClick={this.download} ghost/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="删除文件">
|
||||
<Button type="dashed" size="small" icon={<DeleteOutlined/>} disabled={isEmpty(this.state.selectedRow['key'])} onClick={this.rmdir}
|
||||
danger/>
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
uploadVisible: true
|
||||
})
|
||||
}} ghost/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="刷新">
|
||||
@ -324,22 +361,41 @@ class FileSystem extends Component {
|
||||
ghost/>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
const {loading, selectedRowKeys} = this.state;
|
||||
const rowSelection = {
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys) => {
|
||||
selectedRowKeys = selectedRowKeys.filter(rowKey => rowKey !== '..');
|
||||
this.setState({selectedRowKeys});
|
||||
},
|
||||
};
|
||||
const hasSelected = selectedRowKeys.length > 0;
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card title={title} bordered={true} size="small">
|
||||
|
||||
<Table columns={columns}
|
||||
rowSelection={rowSelection}
|
||||
dataSource={this.state.files}
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
|
||||
onRow={record => {
|
||||
return {
|
||||
onClick: event => {
|
||||
if (record['key'] === '..') {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
selectedRow: record
|
||||
selectedRow: record,
|
||||
selectedRowKeys: [record['key']]
|
||||
});
|
||||
}, // 点击行
|
||||
onDoubleClick: event => {
|
||||
@ -358,12 +414,44 @@ class FileSystem extends Component {
|
||||
}
|
||||
},
|
||||
onContextMenu: event => {
|
||||
event.preventDefault();
|
||||
if (record['key'] === '..') {
|
||||
return;
|
||||
}
|
||||
|
||||
let selectedRowKeys = this.state.selectedRowKeys;
|
||||
if (selectedRowKeys.length === 0) {
|
||||
selectedRowKeys = [record['key']]
|
||||
}
|
||||
this.setState({
|
||||
selectedRow: record,
|
||||
selectedRowKeys: selectedRowKeys,
|
||||
dropdown: {
|
||||
visible: true,
|
||||
pageX: event.pageX,
|
||||
pageY: event.pageY,
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.state.dropdown.visible) {
|
||||
const that = this;
|
||||
document.addEventListener(`click`, function onClickOutside() {
|
||||
that.setState({dropdown: {visible: false}});
|
||||
document.removeEventListener(`click`, onClickOutside);
|
||||
|
||||
document.querySelector('.ant-drawer-body').style.height = 'unset';
|
||||
document.querySelector('.ant-drawer-body').style['overflow-y'] = 'auto';
|
||||
});
|
||||
|
||||
document.querySelector('.ant-drawer-body').style.height = '100vh';
|
||||
document.querySelector('.ant-drawer-body').style['overflow-y'] = 'hidden';
|
||||
}
|
||||
},
|
||||
onMouseEnter: event => {
|
||||
|
||||
}, // 鼠标移入行
|
||||
onMouseLeave: event => {
|
||||
|
||||
},
|
||||
};
|
||||
}}
|
||||
@ -378,17 +466,19 @@ class FileSystem extends Component {
|
||||
title="上传文件"
|
||||
visible={this.state.uploadVisible}
|
||||
onOk={() => {
|
||||
|
||||
this.setState({
|
||||
uploadVisible: false
|
||||
})
|
||||
}}
|
||||
confirmLoading={this.state.uploadLoading}
|
||||
onCancel={()=>{
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
uploadVisible: false
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Upload
|
||||
action={server + '/sessions/' + this.state.sessionId + '/upload?X-Auth-Token=' + getToken() + '&dir=' + this.state.selectedRow.key}>
|
||||
action={server + '/sessions/' + this.state.sessionId + '/upload?X-Auth-Token=' + getToken() + '&dir=' + this.state.currentDirectory}>
|
||||
<Button icon={<UploadOutlined/>}>上传文件</Button>
|
||||
</Upload>
|
||||
</Modal>
|
||||
@ -396,12 +486,12 @@ class FileSystem extends Component {
|
||||
|
||||
<Modal
|
||||
title="创建文件夹"
|
||||
visible={this.state.confirmVisible}
|
||||
visible={this.state.mkdirVisible}
|
||||
onOk={() => {
|
||||
this.formRef.current
|
||||
this.mkdirFormRef.current
|
||||
.validateFields()
|
||||
.then(values => {
|
||||
this.formRef.current.resetFields();
|
||||
this.mkdirFormRef.current.resetFields();
|
||||
this.handleOk(values);
|
||||
})
|
||||
.catch(info => {
|
||||
@ -409,21 +499,21 @@ class FileSystem extends Component {
|
||||
});
|
||||
}}
|
||||
confirmLoading={this.state.confirmLoading}
|
||||
onCancel={()=>{
|
||||
onCancel={() => {
|
||||
this.setState({
|
||||
confirmVisible: false
|
||||
mkdirVisible: false
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Form ref={this.formRef} {...formItemLayout}>
|
||||
<Form ref={this.mkdirFormRef}>
|
||||
|
||||
<Form.Item label="文件夹名称" name='dir' rules={[{required: true, message: '请输入文件夹名称'}]}>
|
||||
<Form.Item name='dir' rules={[{required: true, message: '请输入文件夹名称'}]}>
|
||||
<Input autoComplete="off" placeholder="请输入文件夹名称"/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
|
||||
{this.getNodeTreeRightClickMenu()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -437,14 +437,6 @@ class Asset extends Component {
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
}, {
|
||||
title: '网络',
|
||||
dataIndex: 'ip',
|
||||
key: 'ip',
|
||||
render: (text, record) => {
|
||||
|
||||
return record['ip'] + ':' + record['port'];
|
||||
}
|
||||
}, {
|
||||
title: '连接协议',
|
||||
dataIndex: 'protocol',
|
||||
|
@ -220,5 +220,5 @@ export function renderSize(value) {
|
||||
let index = Math.floor(Math.log(srcSize) / Math.log(1024));
|
||||
let size = srcSize / Math.pow(1024, index);
|
||||
size = size.toFixed(2);
|
||||
return size + unitArr[index];
|
||||
return size + ' ' + unitArr[index];
|
||||
}
|
Loading…
Reference in New Issue
Block a user