Vue3 + xterm + eventSource

xterm 是一个使用 typescript 编写的前端终端组件,可以在浏览器中实现一个命令行终端应用,通常与 websocket一起使用。

一、安装

pnpm install xterm
or
yarn add xterm
or
pnpm install xterm

二、代码实现: 实现日志展示

<template><a-modal class="task-log-dialog" :title="title" :visible="visible" :footer="false" @cancel="onCancel" width="1200px" :mask-closable="false"><div class="main-box"><div class="top-box flex-row-start-center"><a-input v-model:value="grep" placeholder="Filter(regexp)..." size="small" allow-clear @input="searchLog"></a-input><a-input v-model:value="podName" placeholder="podName" size="small" allow-clear @input="searchLog"></a-input></div><div class="content-box"><div ref="terminal" id="terminal" v-loading="loading" element-loading-text="拼命加载中"></div></div><div class="bottom-box">Logs may not appear for pods that are deleted.</div></div></a-modal>
</template><script lang="ts" setup>
import { ref, watch } from 'vue'
import useSystemStore from '@/store/modules/system'
import { debounce } from '@/utils/common'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import 'xterm/css/xterm.css'type propsType = {currentTask: {projectUuid: stringname: stringpodName: stringgrep: stringfollow: boolean}
}
const props = defineProps<propsType>()
const title = ref<string>('构建日志')
const visible = ref<boolean>(false)
const grep = ref<string>('')
const podName = ref<string>('')
const showModel = () => {visible.value = true
}
defineExpose({showModel
})
const emit = defineEmits(['hide'])
const onCancel = () => {visible.value = falseeventSource.value?.close()term.value?.reset()term.value?.clear()if (terminal.value?.innerHTML) {terminal.value.innerHTML = ''terminal.value = null}emit('hide')
}const baseUrl = import.meta.env.VITE_APP_BASE_URL
const eventSource = ref<EventSource | null>(null)
const getLog = async () => {if (!props.currentTask.name) returninitTerm()createEventSource()
}
const createEventSource = () => {eventSource.value = new EventSource(`${baseUrl}/v1/projects/${useSystemStore().projectUuid}/tasks/${props.currentTask.name}/log?podName=${podName.value}&grep=${grep.value}&follow=true`)eventSource.value.onopen = event => {loading.value = falseterm.value?.clear()console.log('onopen', event)}eventSource.value.onmessage = event => {term.value?.clear()if (eventSource.value?.readyState === 1 && !JSON.parse(event.data).result?.completed) {const eventData = JSON.parse(event.data).resultloading.value = falseterm.value?.write(eventData.PodName + ': ' + eventData.Content + '\r\n')}if (eventSource.value?.readyState === 1 && JSON.parse(event.data).result?.completed) {console.log('complete')eventSource.value?.close()}}eventSource.value.onerror = event => {console.log('error', event)eventSource.value?.close()}
}const terminal = ref<HTMLElement | null>(null)
const fitAddon = new FitAddon()
const loading = ref(true)
const term = ref<null | Terminal>(null)
const initTerm = () => {if (!term.value) {term.value = new Terminal({fontSize: 14,scrollback: 999999999999,allowTransparency: true,fontFamily: 'Monaco, Menlo, Consolas, Courier New, monospace',rows: 40,disableStdin: true, //是否应禁用输入cursorStyle: 'underline',cursorBlink: false,theme: {foreground: '#fff',background: '#000',cursor: 'help'}})}setTimeout(() => {term.value?.open(terminal.value as HTMLElement)term.value?.clear()term.value?.loadAddon(fitAddon)fitAddon.fit()}, 5)
}const searchLog = debounce(() => {term.value?.clear()terminal.value = nullgetLog()
}, 1000)watch(visible, value => {if (value) {title.value = '构建日志 - ' + props.currentTask.namegetLog()} else {eventSource.value?.close()term.value?.reset()term.value?.clear()if (terminal.value?.innerHTML) {terminal.value.innerHTML = ''terminal.value = null}}
})
</script><style lang="less">
.task-log-dialog {.main-box {width: 1152px;.top-box {margin-bottom: 20px;height: 30px;.ant-input-affix-wrapper,.ant-select-selector {width: 280px;height: 30px;margin-right: 20px;}}.content-box {.content {width: 100%;}}.bottom-box {margin-top: 30px;}}
}
</style>

三、效果如下

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/709277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从 0 到 1 搭建亿级商品 ES 搜索引擎

建设并维护一个亿级的搜索引擎并非易事&#xff0c;也不存在一劳永逸的最优治理方法。本文是在实践中不断学习和总结的成果&#xff0c;介绍了如何搭建一个可支持从千万级到亿级商品量级的搜索系统&#xff0c;并实现查询总 QPS 从百级增长到千级&#xff0c;写入总 QPS 从百级…

androidapp的开发流程,王者笔记

昨天去面了一家公司&#xff0c;价值观有受到冲击。 面试官技术方面没的说&#xff0c;他可能是个完美主义的人&#xff0c;无论什么事情到了他那里好像都有解决的方案&#xff0c;我被说的无所适从&#xff0c;感觉他很厉害。 但我不能认可的是&#xff0c;面试官觉得加班是…

nextjs13如何进行服务端渲染?

目录 一、创建一个新项目 二、动态获取后端数据进行服务端渲染出现的问题 三、nextjs13如何进行服务端渲染 nextjs13是nextjs的一个重大升级&#xff0c;一些原本在next12当中使用的API在nextjs13上使用十分不便。本文将着重介绍在nextjs13及以上版本当中进行服务端渲染的方…

Linux - 基本指令

1、ls 指令 语法&#xff1a;ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含文件-l …

Docker本地部署GPT聊天机器人并实现公网远程访问

文章目录 前言1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址9. 结语 前言 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&…

Linux Shell脚本练习(一)

一、 Linux下执行Shell脚本的方式&#xff1a; 1、用shell程序执行脚本&#xff1a; a、根据你的shell脚本的类型&#xff0c;选择shell程序&#xff0c;常用的有sh&#xff0c;bash&#xff0c;tcsh等 b、程序的第一行#!/bin/bash里面指明了shell类型的&#xff0c;比如#!/…

Matlab: Introduction to Hybrid Beamforming

文章目录 来源混合波束赋形的基本概念System Setup关键函数 来源 在matlab的命令行输入 doc hybrid beamforming 混合波束赋形的基本概念 混合波束形成简介 本例介绍了混合波束形成的基本概念&#xff0c;并说明了如何模拟这种系统。 现代无线通信系统使用空间复用来提高散…

讲述微信小程序 sitemap.json 索引作用配置

做过pc端国内网址的朋友 对SEO这个词不会陌生 主要就是通过条件搜索网址 目前 我们小程序也有这样的功能提供 那么 因为我们百度seo优化的处理程度不同 被搜索出来的东西 会进行一个先后顺序的排序 那么 我们小程序的 sitemap.json 就是用来配置 我们小程序 是否允许被微信索…

mac终端操作

macOS ls 显示当前目录的所有文件夹 cd cd .. 进入jupyter notebook

java小记(1)

从java8开始&#xff0c;接口可以拥有默认的方法实现。 接口的成员(字段 方法)默认都是 public 的&#xff0c;并且不允许定义为 private 或者 protected。 一个类可以实现多个接口&#xff0c;但不能继承多个抽象类。 重写&#xff1a;指子类实现了一个与父类在方法声明上…

物联网通信协议介绍

为了方便&#xff0c;将物联网通信协议分为两大类&#xff0c;一类是接入协议&#xff0c;一类是通讯协议。接入协议一般负责子网内设备间的组网及通信&#xff1b;通讯协议主要是运行在传统互联网TCP/IP协议之上的设备通讯协议&#xff0c;负责设备通过互联网进行数据交换及通…

web前端-html自定义列表

html 自定义列表 <!--有序列表 应用范围&#xff1a;试卷、问答--> <ol><li>Java</li><li>C</li><li>Python</li><li>C</li><li>VB</li> </ol><br><!--无序列表 应用范围&#xff1a…

3DGS进化,高效高质量的GaussianPro来袭!

作者&#xff1a;小张Tt | 来源&#xff1a;3DCV 在公众号「3DCV」后台&#xff0c;回复「原论文」获取论文 添加微信&#xff1a;dddvision&#xff0c;备注&#xff1a;3D高斯&#xff0c;拉你入群。文末附行业细分群 原文链接&#xff1a;3DGS进化&#xff0c;高效高质量…

大数据界面:客户又又又要求科技感了,如何破?

如果你问客户想要什么风格&#xff0c;大部分脱口而出科技感&#xff0c;不仅要求静态页&#xff0c;而且还要求动态效果&#xff0c;炫酷动画&#xff0c;贝格前端工场结合多个项目经历&#xff0c;帮助友友们梳理如何让界面科技动感。 一、没有科技感背后的潜台词 客户说大数…

[ffmpeg] x264 配置参数解析

背景 创建 x264 编码器后&#xff0c;其有一组默认的编码器配置参数&#xff0c;也可以根据需要修改参数&#xff0c;来满足编码要求。 具体参数 可修改的参数&#xff0c;比较多&#xff0c;这边只列举一些常用的。 获取可以配置的参数 方式1 查看 ffmpeg源码 libx264.c…

如何在宝塔面板中设置FTP文件传输服务并实现远程文件管理

文章目录 1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 宝塔FTP是宝塔面板中的一项功能&#xff0c;用于设置和管理FTP服务。通过宝塔FTP&#xff0c;用户可以创建FTP账号&#xff0c;配置FTP用户权限…

Leetcode—63. 不同路径 II【中等】

2024每日刷题&#xff08;115&#xff09; Leetcode—63. 不同路径 II 动态规划算法思想 实现代码 class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m obstacleGrid.size();int n obstacleGrid[0].size();…

Eureka 入门教程

Eureka 介绍 1. 注册中心概述 什么是注册中心&#xff1f; 给客户端提供可供调用的服务列表&#xff0c;客户端在进行远程调用&#xff08;RPC&#xff09;时&#xff0c;根据服务列表选择服务提供方的服务地址进行服务调用 注册中心的核心功能 注册&#xff1a;服务提供者上…

智能双星:遥测终端机与柳林“巡检机器人“,助力智能运维新升级!

随着科技的不断发展&#xff0c;智能化、自动化的运维管理已经成为企业追求高效、稳定运营的重要方向。柳林遥测终端机、柳林e拍云平台以及巡检机器人的组合&#xff0c;为企业带来了一种全新的、前置的、无感的智能运维体验。 柳林遥测终端机&#xff0c;以其强大的数据采集和…

java 大学生社团管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 大学生社团管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5…