import{ Terminal } from "xterm"import{ FitAddon } from 'xterm-addon-fit'import"xterm/css/xterm.css"import WSTerm from '@/ws/term' //WebSocket的封装,具体代码见下
1
2
3
4
5
6
使用
constFWHFCLI=()=>{const CLIEl = React.createRef();const termClass =useRef()const fitAddon =useRef()const curLineText =useRef()constinitCLI=()=>{
curLineText.current =''let termContainer = document.getElementsByClassName('fwhf-cli')[0]
termClass.current =newTerminal({rendererType:"canvas",//渲染类型rows: Math.ceil(termContainer.offsetHeight /16-9),cols:parseInt(termContainer.offsetWidth /14),convertEol:true,//启用时,光标将设置为下一行的开头// scrollback: 50, //终端中的回滚量disableStdin:false,//是否应禁用输入// cursorStyle: "underline", //光标样式cursorBlink:true,//光标闪烁theme:{foreground:"#ECECEC",//字体background:"#000000",//背景色cursor:"help",//设置光标}})let term = termClass.current
// 创建terminal实例
term.open(CLIEl.current)// 换行并输入起始符
term.prompt=_=>{
term.write("\r\n>>> ")}// canvas背景全屏
fitAddon.current =newFitAddon()
term.loadAddon(fitAddon.current)
fitAddon.current.fit()
window.addEventListener("resize", resizeScreen)runFakeTerminal()}constresizeScreen=()=>{
fitAddon.current.fit()}construnFakeTerminal=()=>{let term = termClass.current
if(term._initialized)return// 初始化
term._initialized =true// 添加事件监听器,支持输入方法
term.onData((key)=>{if(key.charCodeAt(0)==13){// 回车if(curLineText.current ==='clear'){
term.clear()}if(curLineText.current.trim().length ===0){
term.prompt()}else{// 保存命令let commands = localStorage.getItem('commands')?JSON.parse(localStorage.getItem('commands')):[]
commands.push(curLineText.current)
localStorage.setItem('commands',JSON.stringify(commands))
localStorage.setItem('index', commands.length)}//发送请求。。。
WSTermClass.current.sendData(curLineText.current)
curLineText.current =''}elseif(key ==='\u001b[A'){// 向上方向let commands = localStorage.getItem('commands')?JSON.parse(localStorage.getItem('commands')):[]let index = localStorage.getItem('index')? localStorage.getItem('index'): commands.length
index =parseInt(index)if(commands.length && index < commands.length +1&& index >0){// 删除现有命令for(let i =0; i < curLineText.current.length; i++){if(term._core.buffer.x >4){
term.write('\b \b')}}
curLineText.current = commands[index -1]
term.write(curLineText.current)
localStorage.setItem('index', index -1)}}elseif(key ==='\u001b[B'){// 向下方向let commands = localStorage.getItem('commands')?JSON.parse(localStorage.getItem('commands')):[]let index = localStorage.getItem('index')? localStorage.getItem('index'): commands.length
index =parseInt(index)if(commands.length && index < commands.length -1&& index >-1){// 删除现有命令for(let i =0; i < curLineText.current.length; i++){if(term._core.buffer.x >4){
term.write('\b \b')}}
curLineText.current = commands[index +1]
term.write(curLineText.current)
localStorage.setItem('index', index +1)}}elseif(key.charCodeAt(0)===127){if(term._core.buffer.x >4){
term.write('\b \b')
curLineText.current = curLineText.current.substr(0, curLineText.current.length -1)}}else{if(!curLineText.current){
curLineText.current =''}
curLineText.current += key
term.write(key)}// if (key.charCodeAt(0) === 9) { // tab键// let params = {// cmd: curLineText.current// }// tab补全// xxx(params).then((res) => {// if (res.code === 200) {// if (res.data.length) {// for (let i = 0; i < curLineText.current.length; i++) {// term.write('\b \b')// }// let data = res.data.join('\r\n')// curLineText.current = res.data[res.data.length - 1]// if (res.data.length > 1) {// term.write('\r\n')// term.write(data)// term.prompt()// term.write(res.data[res.data.length - 1])// } else {// term.write(that.command)// }// }// }// })// }})}const WSTermClass =useRef()useEffect(()=>{
WSTermClass.current =newWSTerm({openCb:()=>{initCLI()},messageCb:(data)=>{
termClass.current.write(data)}})return()=>{
WSTermClass.current.close()
window.removeEventListener("resize", resizeScreen)}},[])return<div className={"fwhf-cli"}><div ref={CLIEl}></div></div>}exportdefaultFWHFCLI