This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
nezha-nezha-fronted/nezha-fronted/src/components/common/bottomBox/tabs/terminalLogMonitorTab.vue

363 lines
11 KiB
Vue
Raw Normal View History

2021-03-04 16:11:11 +08:00
<template>
<div class="replay-tab" ref="replayTab">
<div class="sub-top-tools">
<div class="sub-list-tabs">
<div class="sub-list-tab-title">ID{{obj.id}}</div>
<div class="sub-list-tab sub-list-tab-active">{{$t("config.terminallog.monitor.monitor")}}</div>
</div>
</div>
<div class="replay-container">
<div class="record-console" ref="recordConsole">
<div :id="obj.uuid" class="record-terminal"></div>
</div>
</div>
</div>
</template>
<script>
import Terminal from '../../js/Xterm';
import bus from "../../../../libs/bus";
export default {
name:"terminalLogReplayTab",
components:{
2021-03-04 16:11:11 +08:00
Terminal
},
props:{
obj:Object, //关联的实体对象
2021-03-04 16:11:11 +08:00
},
data(){
2021-03-04 16:11:11 +08:00
return {
filter:{
size:1,
uuid:""
2021-03-04 16:11:11 +08:00
},
terminal:null,
term:null,
terminalSocket:null,
recordData:[],
isNeedStop:false, // 是否需要停止
playedCount:0, // 当前已经播放完的数量
isPlaying:true, // 是否正在播放
isFinish:false, //是否已结束
isDragging:false, //是否正在拖动进度条
draggingOriginalX:0, //开始拖拽时鼠标的x
draggingOriginalProgress:0, //开始拖拽时的进度
recordTick:50, // 输出间隔时间ms默认50
playerTimer:null, // 定时器
playerCurrentTime:0, // 当前时间进度
speedTable:[ // 快进倍速选项
{speed:1,name:'×1'},
{speed:2,name:'×2'},
{speed:4,name:'×4'},
{speed:8,name:'×8'},
{speed:16,name:'×16'}
2021-03-04 16:11:11 +08:00
],
speedOffset:0, // 快进倍数index
progress:0, // 进度条进度
needSkip:true, // 是否跳过无操作时间为true时表示需要即不跳过无操作时间
timeUsed:0,
2021-03-04 16:11:11 +08:00
successBackContent:'Connecting to',
failBackContent:'Sorry',
connectFailContent:'Connection failed',
welcomeBackContent:'Welcome',
psdCont:'password: ',
}
},
methods:{
2021-03-04 16:11:11 +08:00
//创建连接
create(){
let that=this;
if(this.terminalSocket){
this.terminalSocket.close();
}
if(this.terminal){
this.terminal.off("selection");
this.terminal.off("data")
this.terminal.destroy();
}
this.terminal=new Terminal({
rows:parseInt(this.$refs.recordConsole.offsetHeight/18),
cols:parseInt(this.$refs.recordConsole.offsetWidth/11),
cursorStyle:'block', // 光标样式 null | 'block' | 'underline' | 'bar'
//bellStyle:'sound',
disableStdin:true,//是否应禁用输入
});
this.terminal.open(document.getElementById(this.obj.uuid));
2021-03-04 16:11:11 +08:00
let token=sessionStorage.getItem('nz-token');
let baseUrl=this.$axios.defaults.baseURL;
if(baseUrl.startsWith("/")){
baseUrl="ws://"+window.location.host+baseUrl;
}else{
baseUrl=baseUrl.replace("http://","ws://").replace("https://","ws://");
}
///monitor
let url=baseUrl+"/terminal/monitor.ws?"+"&token="+token+"&uuid="+this.obj.uuid;
console.info(url);
if(this.terminalSocket){//如果存在之前的链接 先断开 再链接新的
this.terminalSocket.close();
}
this.terminalSocket=new WebSocket(url);
2021-03-04 16:11:11 +08:00
//连接成功
this.terminalSocket.onopen=()=>{
};
//登录后,你输入的内容从后台服务返回
this.terminal.on("data",function(data){
console.log(data,'data')
/*
let code = data.charCodeAt(0);
if(code==13){
}else {
//that.term.write(data);
}*/
});
//返回
this.terminalSocket.onmessage=function(evt){
let backContent=evt.data;
/*
if(that.inputSecret){//当前为密码输入状态
}
if(backContent.length>1){
let pwdInput = backContent.endsWith(that.psdCont);
if(pwdInput){//输入密码
that.inputSecret = true;
2021-03-04 16:11:11 +08:00
}
}*/
2021-03-04 16:11:11 +08:00
let welComIndex=backContent.indexOf(that.welcomeBackContent);
if(welComIndex> -1){//无服务器信息只与nezha进行了连接
const connectResult={
title:'',
color:1,
};
that.$emit("refreshConsoleTitle",connectResult);//1:grey 2 green 3 red
}else{
let successContentIndex=backContent.indexOf(that.successBackContent);
if(successContentIndex> -1){
//that.conFinish = true;
let startIndex=successContentIndex+that.successBackContent.length+1;
backContent=backContent.substring(startIndex);
let endIndex=backContent.indexOf('\r\n');
let title=backContent.substring(0,endIndex);
const connectResult={
title:title,
color:2,
2021-03-04 16:11:11 +08:00
};
that.$emit("refreshConsoleTitle",connectResult);//1:grey 2 green 3 red
}else{//失败
let failContentIndex=backContent.indexOf(that.failBackContent);
let connectFailIndex=backContent.indexOf(that.connectFailContent);
if(failContentIndex> -1){
2021-03-04 16:11:11 +08:00
//that.conFinish = true;
const connectResult={
title:'',
color:3,
};
that.$emit("refreshConsoleTitle",connectResult);//1:grey 2 green 3 red
}else if(connectFailIndex> -1){
let startIndex=successContentIndex+that.successBackContent.length+1;
backContent=backContent.substring(startIndex);
let endIndex=backContent.indexOf('\r\n');
let title=backContent.substring(0,endIndex);
const connectResult={
title:'',
color:3,
2021-03-04 16:11:11 +08:00
};
that.$emit("refreshConsoleTitle",connectResult);//1:grey 2 green 3 red
}
}
}
};
//关闭
this.terminalSocket.onclose=()=>{
//报错sorry的还没来得及看信息就关闭
// this.$emit("closeConsole",this.terminal.name);//应该调用父窗口
};
2021-03-04 16:11:11 +08:00
//错误
this.terminalSocket.onerror=(e)=>{
};
//选中 复制
this.terminal.on("selection",function(){
});
this.terminal.attachCustomKeyEventHandler(function(ev){
});
2021-03-04 16:11:11 +08:00
this.terminal.attach(this.terminalSocket);
this.terminal._initialized=true;
this.terminal.fit();//自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸) 只是width
// this.$nextTick(()=>{// 解决进入全屏和退出全屏是底部隐藏
// this.setFontSize(this.fontSize);
// })
2021-03-04 16:11:11 +08:00
},
//关闭连接
closeSocket(){
if(this.terminalSocket){
this.terminalSocket.close();
}
if(this.terminal){
2021-03-04 16:11:11 +08:00
this.terminal.destroy();
}
},
// 切换tab
changeTab(tab){
this.$emit('changeTab',tab);
2021-03-04 16:11:11 +08:00
},
getRecordData(){
return new Promise(resolve=>{
this.$get("/terminal/record",this.filter).then(res=>{
if(res.code===200){
this.recordData=res.data.list;
this.timeUsed=res.data.endTime;
2021-03-04 16:11:11 +08:00
}
resolve();
});
});
},
consoleResize(){
this.terminal&&this.terminal.resize(parseInt(this.$refs.recordConsole.offsetWidth/11),parseInt(this.$refs.recordConsole.offsetHeight/18));
this.$nextTick(()=>{
this.terminal&&this.terminal.fit();
2021-03-04 16:11:11 +08:00
});
},
shutdown(){
this.$confirm(this.$t("tip.killTerm"),{
confirmButtonText:this.$t("tip.yes"),
cancelButtonText:this.$t("tip.no"),
type:'warning'
}).then(()=>{
this.$put("/terminal/kill",{uuid:this.obj.uuid}).then(res=>{
if(res.code===200){
this.$message.success(this.$t("config.terminallog.success"));
this.$emit('exit')
}else{
this.$message.error(this.$t("config.terminallog.killErrorTip"));
}
});
2021-03-04 16:11:11 +08:00
});
},
},
watch:{
2021-03-04 16:11:11 +08:00
// 入口监听terminal session的变化开始功能
obj:{
immediate:true,
deep:true,
handler(n){
if(n.uuid){
this.recordData=[];
this.filter.uuid=n.uuid;
this.playerCurrentTime=0;
if(this.playerTimer){
2021-03-04 16:11:11 +08:00
clearTimeout(this.playerTimer);
}
setTimeout(()=>{
this.create();
},200);
2021-03-04 16:11:11 +08:00
}
}
},
progress(n){
let progressController=document.getElementById("progressController");
progressController.style.left=`${n}%`;
2021-03-04 16:11:11 +08:00
}
},
computed:{
parseCurrentTime(){
let currentTime=parseInt(this.playerCurrentTime/1000);
let totalTime=parseInt(this.timeUsed/1000);
if(currentTime>totalTime){
currentTime=totalTime;
2021-03-04 16:11:11 +08:00
}
return `${currentTime} / ${totalTime}`;
}
},
created(){
window.addEventListener('resize',bus.debounce(this.consoleResize,1000));
2021-03-04 16:11:11 +08:00
},
mounted(){
},
beforeDestroy(){
window.removeEventListener('resize',bus.debounce);
2021-03-04 16:11:11 +08:00
this.closeSocket();
this.terminal.off("selection");
this.terminal.off("data")
},
}
</script>
<style lang="scss">
.replay-tab {
height: 100%;
}
2021-03-04 16:11:11 +08:00
.replay-container {
height: calc(100% - 40px);
}
2021-03-04 16:11:11 +08:00
.record-console {
padding: 10px 4px 10px 10px;
background-color: black;
height: calc(100% - 80px);
}
2021-03-04 16:11:11 +08:00
.terminal-replay-progress {
height: 20px;
padding: 3px 0;
position: relative;
width: 500px;
}
#terminal-kill {
2021-03-04 16:11:11 +08:00
margin-bottom: 5px;
}
2021-03-04 16:11:11 +08:00
.terminal-replay-progress-bar {
top: 50%;
transform: translateY(-50%);
.el-progress-bar__inner {
transition: unset;
user-select: none;
}
}
2021-03-04 16:11:11 +08:00
.replay-operate {
.nz-btn {
margin-right: 8px;
.nz-icon {
font-size: 14px;
}
}
}
2021-03-04 16:11:11 +08:00
.operate-skip {
margin: 0 12px !important;
}
2021-03-04 16:11:11 +08:00
.time-box {
border: none;
border-radius: 16px;
}
2021-03-04 16:11:11 +08:00
.progress-controller {
position: absolute;
height: 14px;
width: 14px;
border-radius: 50%;
background-color: #409eef;
top: 50%;
transform: translate(-7px, -50%);
}
2021-03-04 16:11:11 +08:00
.progress-controller:hover {
background-color: #207ecf;
}
</style>