继续完善文件管理

This commit is contained in:
dushixiang 2021-02-04 19:50:16 +08:00
parent 1444891d96
commit 248815538d
6 changed files with 233 additions and 112 deletions

View File

@ -107,14 +107,14 @@ func SetupRoutes() *echo.Echo {
sessions.POST("/:id/connect", SessionConnectEndpoint)
sessions.POST("/:id/disconnect", Admin(SessionDisconnectEndpoint))
sessions.POST("/:id/resize", SessionResizeEndpoint)
sessions.POST("/:id/upload", SessionUploadEndpoint)
sessions.GET("/:id/download", SessionDownloadEndpoint)
sessions.GET("/:id/ls", SessionLsEndpoint)
sessions.GET("/:id/download", SessionDownloadEndpoint)
sessions.POST("/:id/upload", SessionUploadEndpoint)
sessions.POST("/:id/mkdir", SessionMkDirEndpoint)
sessions.DELETE("/:id/rm", SessionRmEndpoint)
sessions.POST("/:id/rm", SessionRmEndpoint)
sessions.POST("/:id/rename", SessionRenameEndpoint)
sessions.DELETE("/:id", SessionDeleteEndpoint)
sessions.GET("/:id/recording", SessionRecordingEndpoint)
sessions.GET("/:id/status", SessionGetStatusEndpoint)
}
resourceSharers := e.Group("/resource-sharers")

View File

@ -442,7 +442,7 @@ func SessionLsEndpoint(c echo.Context) error {
return Success(c, files)
}
return err
return errors.New("当前协议不支持此操作")
}
func SessionMkDirEndpoint(c echo.Context) error {
@ -473,7 +473,7 @@ func SessionMkDirEndpoint(c echo.Context) error {
return Success(c, nil)
}
return nil
return errors.New("当前协议不支持此操作")
}
func SessionRmEndpoint(c echo.Context) error {
@ -497,22 +497,22 @@ func SessionRmEndpoint(c echo.Context) error {
}
if stat.IsDir() {
fileInfos, err := tun.Subject.SftpClient.ReadDir(key)
fileInfos, err := 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 {
if err := sftpClient.Remove(path.Join(key, fileInfos[i].Name())); err != nil {
return err
}
}
if err := tun.Subject.SftpClient.RemoveDirectory(key); err != nil {
if err := sftpClient.RemoveDirectory(key); err != nil {
return err
}
} else {
if err := tun.Subject.SftpClient.Remove(key); err != nil {
if err := sftpClient.Remove(key); err != nil {
return err
}
}
@ -531,7 +531,43 @@ func SessionRmEndpoint(c echo.Context) error {
return Success(c, nil)
}
return nil
return errors.New("当前协议不支持此操作")
}
func SessionRenameEndpoint(c echo.Context) error {
sessionId := c.Param("id")
session, err := model.FindSessionById(sessionId)
if err != nil {
return err
}
oldName := c.QueryParam("oldName")
newName := c.QueryParam("newName")
if "ssh" == session.Protocol {
tun, ok := global.Store.Get(sessionId)
if !ok {
return errors.New("获取sftp客户端失败")
}
sftpClient := tun.Subject.SftpClient
if err := sftpClient.Rename(oldName, newName); 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.Rename(path.Join(drivePath, oldName), path.Join(drivePath, newName)); err != nil {
return err
}
return Success(c, nil)
}
return errors.New("当前协议不支持此操作")
}
func SessionRecordingEndpoint(c echo.Context) error {
@ -551,14 +587,3 @@ func SessionRecordingEndpoint(c echo.Context) error {
logrus.Debugf("读取录屏文件:%v,是否存在: %v, 是否为文件: %v", recording, utils.FileExists(recording), utils.IsFile(recording))
return c.File(recording)
}
func SessionGetStatusEndpoint(c echo.Context) error {
sessionId := c.Param("id")
session, err := model.FindSessionById(sessionId)
if err != nil {
return err
}
return Success(c, H{
"status": session.Status,
})
}

View File

@ -106,11 +106,11 @@ class Access extends Component {
})
if (this.state.protocol === 'ssh') {
if (data.data && data.data.length > 0) {
message.info('您输入的内容已复制到远程服务器上,使用右键将自动粘贴。');
// message.info('您输入的内容已复制到远程服务器上,使用右键将自动粘贴。');
}
} else {
if (data.data && data.data.length > 0) {
message.info('您输入的内容已复制到远程服务器上');
// message.info('您输入的内容已复制到远程服务器上');
}
}
@ -282,9 +282,13 @@ class Access extends Component {
// Set clipboard contents once stream is finished
reader.onend = async () => {
message.info('您选择的内容已复制到您的粘贴板中,在右侧的输入框中可同时查看到。');
// message.info('您选择的内容已复制到您的粘贴板中,在右侧的输入框中可同时查看到。');
this.setState({
clipboardText: data
}, () => {
// 选中粘贴板文本框中的内容
// 调用API粘贴进
});
if (navigator.clipboard) {
@ -306,9 +310,9 @@ class Access extends Component {
};
onKeyDown = (keysym) => {
if (this.state.clipboardVisible || this.state.fileSystemVisible) {
return true;
}
// if (this.state.clipboardVisible || this.state.fileSystemVisible) {
// return true;
// }
this.state.client.sendKeyEvent(1, keysym);
if (keysym === 65288) {
return false;
@ -416,8 +420,11 @@ class Access extends Component {
}
};
const sink = new Guacamole.InputSink();
display.appendChild(sink.getElement());
// Keyboard
const keyboard = new Guacamole.Keyboard(document);
const keyboard = new Guacamole.Keyboard(sink.getElement());
keyboard.onkeydown = this.onKeyDown;
keyboard.onkeyup = this.onKeyUp;

View File

@ -5,28 +5,28 @@
-ms-user-select: none;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
0% {
transform: translateY(-25%);
from {
opacity: 0;
}
50%{
transform: translateY(4%);
}
65%{
transform: translateY(-2%);
}
80%{
transform: translateY(2%);
}
95%{
transform: translateY(-1%);
}
100% {
transform: translateY(0%);
to {
opacity: 1;
}
}
.popup {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
animation-duration: 0.4s;
background-clip: padding-box;

View File

@ -4,6 +4,7 @@ import {
CloudDownloadOutlined,
CloudUploadOutlined,
DeleteOutlined,
EditOutlined,
ExclamationCircleOutlined,
FileExcelOutlined,
FileImageOutlined,
@ -23,18 +24,15 @@ import qs from "qs";
import request from "../../common/request";
import {server} from "../../common/constants";
import Upload from "antd/es/upload";
import {download, getToken, isEmpty, renderSize} from "../../utils/utils";
import {download, getFileName, getToken, isEmpty, renderSize} from "../../utils/utils";
import './FileSystem.css'
const formItemLayout = {
labelCol: {span: 6},
wrapperCol: {span: 14},
};
const {confirm} = Modal;
class FileSystem extends Component {
mkdirFormRef = React.createRef();
renameFormRef = React.createRef();
state = {
sessionId: undefined,
@ -57,36 +55,6 @@ class FileSystem extends Component {
});
}
handleOk = async (values) => {
let params = {
'dir': this.state.selectedRow.key + '/' + values['dir']
}
let paramStr = qs.stringify(params);
this.setState({
confirmLoading: true
})
let result = await request.post(`/sessions/${this.state.sessionId}/mkdir?${paramStr}`);
if (result.code === 1) {
message.success('创建成功');
this.loadFiles(this.state.currentDirectory);
} else {
message.error(result.message);
}
this.setState({
confirmLoading: false,
confirmVisible: false
})
}
upload = () => {
this.setState({
uploadVisible: true
})
}
download = () => {
download(`${server}/sessions/${this.state.sessionId}/download?file=${this.state.selectedRow.key}`);
}
@ -97,9 +65,9 @@ class FileSystem extends Component {
message.warning('请至少选择一个文件或目录');
}
let title = '';
let title;
if (selectedRowKeys.length === 1) {
let file = selectedRowKeys[0].substring(selectedRowKeys[0].lastIndexOf('/') + 1, selectedRowKeys[0].length);
let file = getFileName(selectedRowKeys[0]);
title = <p>您确认要删除"{file}"</p>;
} else {
title = `您确认要删除所选的${selectedRowKeys.length}项目吗?`;
@ -114,7 +82,7 @@ class FileSystem extends Component {
if (rowKey === '..') {
continue;
}
let result = await request.delete(`/sessions/${this.state.sessionId}/rm?key=${rowKey}`);
let result = await request.post(`/sessions/${this.state.sessionId}/rm?key=${rowKey}`);
if (result['code'] !== 1) {
message.error(result['message']);
}
@ -158,7 +126,8 @@ class FileSystem extends Component {
this.setState({
files: items,
currentDirectory: key,
selectedRow: {}
selectedRow: {},
selectedRowKeys: []
})
} finally {
this.setState({
@ -182,7 +151,6 @@ 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`,
@ -195,10 +163,24 @@ class FileSystem extends Component {
disableDownload = false;
}
let disableRename = true;
if (this.state.selectedRowKeys.length === 1) {
disableRename = 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={<EditOutlined/>} disabled={disableRename}
onClick={() => {
this.setState({
renameVisible: true
})
}}
>重命名</Button></li>
<li><Button type={'text'} size={'small'} icon={<DeleteOutlined/>} onClick={this.rmdir}>删除</Button>
</li>
</ul>
@ -365,7 +347,7 @@ class FileSystem extends Component {
</Row>
);
const {loading, selectedRowKeys} = this.state;
const {selectedRowKeys} = this.state;
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
@ -465,10 +447,12 @@ class FileSystem extends Component {
<Modal
title="上传文件"
visible={this.state.uploadVisible}
centered={true}
onOk={() => {
this.setState({
uploadVisible: false
})
this.loadFiles(this.state.currentDirectory);
}}
confirmLoading={this.state.uploadLoading}
onCancel={() => {
@ -484,34 +468,135 @@ class FileSystem extends Component {
</Modal>
<Modal
title="创建文件夹"
visible={this.state.mkdirVisible}
onOk={() => {
this.mkdirFormRef.current
.validateFields()
.then(values => {
this.mkdirFormRef.current.resetFields();
this.handleOk(values);
})
.catch(info => {
{
this.state.mkdirVisible ?
<Modal
title="创建文件夹"
visible={this.state.mkdirVisible}
centered={true}
onOk={() => {
this.mkdirFormRef.current
.validateFields()
.then(async values => {
this.mkdirFormRef.current.resetFields();
let params = {
'dir': this.state.currentDirectory + '/' + values['dir']
}
let paramStr = qs.stringify(params);
});
}}
confirmLoading={this.state.confirmLoading}
onCancel={() => {
this.setState({
mkdirVisible: false
})
}}
>
<Form ref={this.mkdirFormRef}>
this.setState({
confirmLoading: true
})
let result = await request.post(`/sessions/${this.state.sessionId}/mkdir?${paramStr}`);
if (result.code === 1) {
message.success('创建成功');
this.loadFiles(this.state.currentDirectory);
} else {
message.error(result.message);
}
this.setState({
confirmLoading: false,
mkdirVisible: false
})
})
.catch(info => {
});
}}
confirmLoading={this.state.confirmLoading}
onCancel={() => {
this.setState({
mkdirVisible: false
})
}}
>
<Form ref={this.mkdirFormRef}>
<Form.Item name='dir' rules={[{required: true, message: '请输入文件夹名称'}]}>
<Input autoComplete="off" placeholder="请输入文件夹名称"/>
</Form.Item>
</Form>
</Modal> : undefined
}
{
this.state.renameVisible ?
<Modal
title="重命名"
visible={this.state.renameVisible}
centered={true}
onOk={() => {
this.renameFormRef.current
.validateFields()
.then(async values => {
this.renameFormRef.current.resetFields();
try {
let currentDirectory = this.state.currentDirectory;
if (!currentDirectory.endsWith("/")) {
currentDirectory += '/';
}
let params = {
'oldName': this.state.selectedRowKeys[0],
'newName': currentDirectory + values['newName'],
}
if (params['oldName'] === params['newName']) {
message.success('重命名成功');
return;
}
let paramStr = qs.stringify(params);
this.setState({
confirmLoading: true
})
let result = await request.post(`/sessions/${this.state.sessionId}/rename?${paramStr}`);
if (result['code'] === 1) {
message.success('重命名成功');
let files = this.state.files;
for (let i = 0; i < files.length; i++) {
if (files['key'] === params['oldName']) {
files[i].path = params['newName'];
files[i].key = params['newName'];
files[i].name = getFileName(params['newName']);
break;
}
}
this.setState({
files: files
})
} else {
message.error(result.message);
}
} finally {
this.setState({
confirmLoading: false,
renameVisible: false
})
}
})
.catch(info => {
});
}}
confirmLoading={this.state.confirmLoading}
onCancel={() => {
this.setState({
renameVisible: false
})
}}
>
<Form ref={this.renameFormRef}
initialValues={{newName: getFileName(this.state.selectedRowKeys[0])}}>
<Form.Item name='newName' rules={[{required: true, message: '请输入新的名称'}]}>
<Input autoComplete="off" placeholder="新的名称"/>
</Form.Item>
</Form>
</Modal> : undefined
}
<Form.Item name='dir' rules={[{required: true, message: '请输入文件夹名称'}]}>
<Input autoComplete="off" placeholder="请输入文件夹名称"/>
</Form.Item>
</Form>
</Modal>
{this.getNodeTreeRightClickMenu()}
</div>

View File

@ -221,4 +221,8 @@ export function renderSize(value) {
let size = srcSize / Math.pow(1024, index);
size = size.toFixed(2);
return size + ' ' + unitArr[index];
}
export function getFileName(fullFileName){
return fullFileName.substring(fullFileName.lastIndexOf('/') + 1, fullFileName.length);
}