From 248815538dc6e8d7f20292e891d012f9cc4459c4 Mon Sep 17 00:00:00 2001 From: dushixiang <798148596@qq.com> Date: Thu, 4 Feb 2021 19:50:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E5=AE=8C=E5=96=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/api/routes.go | 8 +- pkg/api/session.go | 61 +++++-- web/src/components/access/Access.js | 21 ++- web/src/components/access/FileSystem.css | 32 ++-- web/src/components/access/FileSystem.js | 219 ++++++++++++++++------- web/src/utils/utils.js | 4 + 6 files changed, 233 insertions(+), 112 deletions(-) diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 4fda0fb..1fb9c66 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -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") diff --git a/pkg/api/session.go b/pkg/api/session.go index 02063cb..0c145ee 100644 --- a/pkg/api/session.go +++ b/pkg/api/session.go @@ -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, - }) -} diff --git a/web/src/components/access/Access.js b/web/src/components/access/Access.js index 85ed821..9a39a08 100644 --- a/web/src/components/access/Access.js +++ b/web/src/components/access/Access.js @@ -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; diff --git a/web/src/components/access/FileSystem.css b/web/src/components/access/FileSystem.css index ef5dc17..59d0e07 100644 --- a/web/src/components/access/FileSystem.css +++ b/web/src/components/access/FileSystem.css @@ -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; diff --git a/web/src/components/access/FileSystem.js b/web/src/components/access/FileSystem.js index 1f6f6fc..04c3d41 100644 --- a/web/src/components/access/FileSystem.js +++ b/web/src/components/access/FileSystem.js @@ -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 =
您确认要删除"{file}"吗?
; } 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 (