当前位置:首页 » 《资源分享》 » 正文

前端Vue中使用Guacamole进行远程桌面的前端部分

14 人参与  2024年09月27日 12:40  分类 : 《资源分享》  评论

点击全文阅读


最近公司有个项目要求远程虚拟机,最后选择使用了Guacamole进行实现,网上搜了一下感觉资料不是很多,对guacamole-common.js里的API介绍也没查到(捂脸),可能是我的问题。网上的教程都是教后端怎么搭建远程桌面系统。对web端使用的资料很少,可能大佬们觉着不需要(╥╯^╰╥)。下面我把在项目中用到的一下方法,总结一下,万一有人也需要呐。哈哈

下载guacamole-common或者直接引入guacamole-common.js文件;在项目中的引用
初始化Guacamoleconst initGuacamole = () => {//XXXXX 后端提供的连接地址      guacamole.tunnel = new Guacamole.WebSocketTunnel('XXXXX')      if (guacamole.client) {        guacamole.display.scale(0)        uninstallKeyboard()      }      guacamole.client = new Guacamole.Client(guacamole.tunnel)      guacamole.tunnel.onerror = error => {        // console.error(`Tunnel failed ${JSON.stringify(error)}`)        // 这里是断开重连的机智 当code值是下面这些时会进行重连5次,        if (error.code === 512 || error.code === 514 || error.code === 515 || error.code === 769 || error.code === 776) {          if (guacamole.curRetryCount === 0) {            guacamole.retryTask = setInterval(() => {              if (guacamole.curRetryCount < guacamole.maxRetryCount) {                uninstallKeyboard()                nextTick(() => {                  initGuacamole('error')                })                guacamole.curRetryCount++              } else if (guacamole.curRetryCount >= guacamole.maxRetryCount) {                guacamole.loading = false                guacamole.loadingText = ''                uninstallKeyboard()                clearInterval(guacamole.retryTask)                guacamole.retryTask = null              }            }, 3000)          }        }else {          if (!guacamole.retryTask) {            guacamole.loading = false            guacamole.loadingText = ''          }        }      }      guacamole.tunnel.onstatechange = state => {        // console.log('tunnel.onstatechange',Guacamole.Tunnel.State,state);        switch (state) {          case Guacamole.Tunnel.State.CONNECTING:            guacamole.connectionState = TUNNEL_STATES.CONNECTING            break;            // Connection is established / no longer unstable          case Guacamole.Tunnel.State.OPEN:            guacamole.connectionState = TUNNEL_STATES.CONNECTED            break;            // Connection is established but misbehaving          case Guacamole.Tunnel.State.UNSTABLE:            // TODO            guacamole.connectionState = '不稳定'              // this.$message.error("不稳定")            break;            // Connection has closed          case Guacamole.Tunnel.State.CLOSED:            guacamole.connectionState = TUNNEL_STATES.DISCONNECTED            break;        }      }      guacamole.client.onstatechange = clientState => {        // console.log('clientState', clientState,  TUNNEL_STATES);        switch (clientState) {          case 0:            guacamole.connectionState = TUNNEL_STATES.IDLE            break          case 1:            // connecting ignored for some reason?            break          case 2:            guacamole.connectionState = TUNNEL_STATES.WAITING            break          case 3:            guacamole.connectionState = TUNNEL_STATES.CONNECTED            // 取消加载            guacamole.loading = false            guacamole.loadingText = ''            // 重连清空定时器和次数            guacamole.curRetryCount = 0            clearInterval(guacamole.retryTask)            guacamole.retryTask = null//监听视图变化,并发送最新的宽高给Guacamole进行重新绘制            window.addEventListener('resize', resize)          case 4:          case 5:            // disconnected, disconnecting            break        }      }      guacamole.client.onerror = error => {        guacamole.client.disconnect()        console.error(`Client error ${JSON.stringify(error)}`)      }      guacamole.display = guacamole.client.getDisplay()      display.value.appendChild(guacamole.display.getElement())      display.value.addEventListener('contextmenu', e => {        e.stopPropagation();        if (e.preventDefault) {          e.preventDefault();        }        e.returnValue = false;      })  // 后端需要的参数      let param = {      userName: '',      password: '',      type: 'VNC/RDP'      }      guacamole.client.connect(param);      // 视图大小发生变化时触发(rdp和VNC同时连接时rdp可以动态设置分辨率,但是VNC不可以,所以前端可以通过onresize拿到rdp连接后,VNC通道拿到流的宽高进行等比缩放)      guacamole.display.onresize = function(width, height) {        const resizeScale = Math.min(          viewport.value.clientWidth / Math.max(guacamole.display.getWidth(), 1),           viewport.value.clientHeight / Math.max(guacamole.display.getHeight(), 1)        )        guacamole.display.scale(resizeScale)      }      window.onunload = () => guacamole.client.disconnect();      // 解决连接多个虚拟机时有的虚拟机不能查看z-index: -1      guacamole.client.getDisplay().scale(1)      display.value.onclick = () => {        display.value.focus()      }      display.value.onfocus = () => {        display.value.className = 'focus'      }      display.value.onblur = () => {        display.value.className = ''      }      guacamole.keyboard = new Guacamole.Keyboard(display.value);      installKeyboard()      // Mouse 参数最好使用guacamole.client.getDisplay().getElement(),之前写的是父级元素,会导致出现两个鼠标的问题      guacamole.mouse = new Guacamole.Mouse(guacamole.client.getDisplay().getElement());      // 鼠标离开显示器时隐藏软件光标      guacamole.mouse.onmouseout = () => {        if (!guacamole.display) return;        guacamole.display.showCursor(false);      }      guacamole.mouse.onmousedown = guacamole.mouse.onmouseup = guacamole.mouse.onmousemove = handleMouseState      setTimeout(() => {        resize()        display.value.focus()      }, 1000);//居中显示(当返回的流宽高小于屏幕宽高时)      guacamole.client.getDisplay().getElement().style.setProperty('margin', 'auto')    }
缩放方法
const resize = () => {      const elm = viewport.value;      if (!elm || !elm.offsetWidth) {        return      }      // let pixelDensity = window.devicePixelRatio || 1  (pixelDensity 获取当前电脑的分辨率百分比)      let pixelDensity = 1      const width = elm.clientWidth * pixelDensity      const height = elm.clientHeight * pixelDensity      if (guacamole.display.getWidth() !== width || guacamole.display.getHeight() !== height) {        guacamole.client.sendSize(width, height)      }      // setting timeout so display has time to get the correct size      setTimeout(() => {      // 计算缩放比例        const scale = Math.min(            elm.clientWidth / Math.max(guacamole.display.getWidth(), 1),            elm.clientHeight / Math.max(guacamole.display.getHeight(), 1)        )        // guacamole.display.scale(1)        if (props.websocketUrl === '/webSocket') {          guacamole.display.scale(1)        }else {          guacamole.display.scale(scale)        }      }, 1000)    }
html
<div ref="display" class="display" tabindex="0"/>

以上就是我在项目中的使用情况
1、连接Tunnel
guacamole.tunnel = new Guacamole.WebSocketTunnel(props.websocketUrl)
2、把流放到视图中
guacamole.client = new Guacamole.Client(guacamole.tunnel)
3、监听tunnel和client 的值进行状态判断
4、把流添加到视图中
guacamole.client.getDisplay().appendChild(guacamole.display.getElement())
5、给后端传参
let param = {userName: ’ ',password: ’ '}
guacamole.client.connect(param);
6、断开虚拟机连接
guacamole.client.disconnect();
7、键盘事件
// display.value div元素
new Guacamole.Keyboard(display.value)
8、鼠标事件
new Guacamole.Mouse(guacamole.client.getDisplay().getElement());


点击全文阅读


本文链接:http://zhangshiyu.com/post/165318.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1