This commit is contained in:
Mn
2023-11-22 16:11:25 +08:00
parent 8382129a49
commit 53ac3a3a4b
13 changed files with 133 additions and 50 deletions

View File

@@ -85,7 +85,8 @@ namespace NetPanel.Bl
public void WriteLine(string line)
{
_writer.WriteLine(line);
//_writer.WriteLine(line);
_shellStream.WriteLine(line);
}

View File

@@ -27,8 +27,7 @@
<div id="terminal" style=""></div>
<div class="clearfix">
</div>
<div class="clearfix"></div>
</div>
</div>
@@ -37,12 +36,23 @@
</section>
<link href="/adminlte/plugins/xterm/xterm.css" rel="stylesheet" />
<script src="/adminlte/plugins/xterm/xterm.js"></script><
<script src="/adminlte/plugins/xterm/xterm.js"></script>
<script src="/adminlte/plugins/xterm/xterm-addon-fit.js"></script>
<script src="/adminlte/plugins/xterm/xterm-addon-web-links.js"></script>
<script src="/adminlte/plugins/xterm/xterm-addon-search.js"></script>
<script src="/adminlte/plugins/xterm/xterm-addon-webgl.js"></script>
<script src="/lib/microsoft/signalr/dist/browser/signalr.min.js"></script>
<script>
<script>
// import { FitAddon } from '.../adminlte/plugins/xterm/xterm-addon-fit.js';
// import { WebLinksAddon } from '.../adminlte/plugins/xterm/xterm-addon-web-links';
// import { SearchAddon } from '.../adminlte/plugins/xterm/xterm-addon-search';
// import { WebglAddon } from '.../adminlte/plugins/xterm/xterm-addon-webgl';
var term = new Terminal({
cursorStyle: 'underline', //光标样式
cursorBlink: true, // 光标闪烁
@@ -63,34 +73,51 @@
//cursorx 这个长度不能删除,用于ev.keyCode === 8
var cursorx = 0;
// 调整终端的尺寸。
term.resize(columns, parseInt(height / 22));
// term.resize(columns, parseInt(height / 22));
//回车输入的内容
var curr_line = '';
var curr_user = '';
//历史内容
var entries = [];
var currPos = 0;
var pos = 0;
var connectionId = '';
term.open(document.getElementById('terminal'));
term.prompt = () => {
term.write('\n\u001b[32m$ >\u001b[37m');
};
const fit = new FitAddon.FitAddon();
term.loadAddon(fit);
term.loadAddon(new WebLinksAddon.WebLinksAddon());
term.loadAddon(new SearchAddon.SearchAddon());
term.loadAddon(new WebglAddon.WebglAddon());
term.open(document.getElementById('terminal'));
fit.fit();
//通讯
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//signalR接收消息
connection.on("ReceiveMessage", function (msg) {
term.write(msg.obj);
if (entries[entries.length - 1] != msg.obj.trim()) {
term.write(msg.obj);
if (msg.code == 2 && curr_user == '') {
curr_user = msg.obj;
}
}
});
@@ -100,74 +127,77 @@
// term.prompt();
connectionId = msg.obj;
//创建 ssh 客户端
connection.invoke('CreateConnectionAsync', width, height, columns, rows).then((result) => {
connection.invoke('CreateConnectionAsync', term.element.clientWidth, term.element.clientHeight, term.cols, term.rows).then((result) => {
});
});
// 监听后端终端关闭
connection.on('WriteErrorAsync', () => {
term.write('SessionClosed');
});
term.on('key', function (key, ev) {
const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
//监听按键
term.onKey((obj) => {
var ev = obj.domEvent;
var key = obj.key;
const printable = !ev.altKey && !ev.altGraphKey && !ev.metaKey
//const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey;
if (cursorx == 0) {
cursorx = term.buffer.cursorX;
}
if (ev.keyCode === 13) { // Enter key
if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace
entries.push(curr_line);
currPos = entries.length - 1;
// term.prompt();
//发送命令
connection.invoke('WriteLineAsync', curr_line).then((result) => {
if (result.code == 1) {
// term.write('\n' + result.obj);
// term.prompt();
}
});
} else {
term.write('\n\33[2K\r\u001b[32m$ >\u001b[37m');
term.write('\n' + curr_user);
}
curr_line = '';
} else if (ev.keyCode === 8) { // Backspace
if (term.buffer.cursorX > cursorx) {
if (curr_line.length > 0) {
curr_line = curr_line.slice(0, -1);
term.write('\b \b');
}
} else if (ev.keyCode === 38) { // Up arrow
if (entries.length > 0) {
if (currPos > 0) {
currPos -= 1;
}
curr_line = entries[currPos];
term.write('\33[2K\r\u001b[32m$ >\u001b[37m' + curr_line);
const lineNumber = 1;
//删除当前行
term.write('\x1b[2K');
//运动光标到第一行
term.write('\x1b[0G');
term.write(curr_user + curr_line);
}
} else if (ev.keyCode === 40) { // Down arrow
currPos += 1;
if (currPos === entries.length || entries.length === 0) {
currPos -= 1;
curr_line = '';
term.write('\33[2K\r\u001b[32m$ >\u001b[37m');
//删除当前行
term.write('\x1b[2K');
//运动光标到第一行
term.write('\x1b[0G');
term.write(curr_user);
} else {
curr_line = entries[currPos];
term.write('\33[2K\r\u001b[32m$ >\u001b[37m' + curr_line);
//删除当前行
term.write('\x1b[2K');
//运动光标到第一行
term.write('\x1b[0G');
term.write(curr_user + curr_line);
}
} else if (printable) {

View File

@@ -0,0 +1,2 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
//# sourceMappingURL=xterm-addon-fit.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(()=>(()=>{"use strict";var e={6:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,i={}){this._terminal=e,this._regex=t,this._handler=n,this._options=i}provideLinks(e,t){const i=n.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(i))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:i}=e;this._options.hover(t,n,i)}},e)))}};class n{static computeLink(e,t,i,r){const o=new RegExp(t.source,(t.flags||"")+"g"),[s,a]=n._getWindowedLineStrings(e-1,i),c=s.join("");let d;const l=[];for(;d=o.exec(c);){const e=d[0];try{const t=new URL(e),n=decodeURI(t.toString());if(e!==n&&e+"/"!==n)continue}catch(e){continue}const[t,o]=n._mapStrIdx(i,a,0,d.index),[s,c]=n._mapStrIdx(i,t,o,e.length);if(-1===t||-1===o||-1===s||-1===c)continue;const p={start:{x:o+1,y:t+1},end:{x:c,y:s+1}};l.push({range:p,text:e,activate:r})}return l}static _getWindowedLineStrings(e,t){let n,i=e,r=e,o=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(o=0;(n=t.buffer.active.getLine(--i))&&o<2048&&(s=n.translateToString(!0),o+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),o=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&o<2048&&(s=n.translateToString(!0),o+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,i]}static _mapStrIdx(e,t,n,i){const r=e.buffer.active,o=r.getNullCell();let s=n;for(;i;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n<e.length;++n){e.getCell(n,o);const s=o.getChars();if(o.getWidth()&&(i-=s.length||1,n===e.length-1&&""===s)){const e=r.getLine(t+1);e&&e.isWrapped&&(e.getCell(0,o),2===o.getWidth()&&(i+=1))}if(i<0)return[t,n]}t++,s=0}return[t,s]}}t.LinkComputer=n}},t={};function n(i){var r=t[i];if(void 0!==r)return r.exports;var o=t[i]={exports:{}};return e[i](o,o.exports,n),o.exports}var i={};return(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/https?:[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function o(e,t){const n=window.open();if(n){try{n.opener=null}catch(e){}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=o,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,i=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,i,this._handler,n))}dispose(){var e;null===(e=this._linkProvider)||void 0===e||e.dispose()}}})(),i})()));
//# sourceMappingURL=xterm-addon-web-links.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -36,7 +36,7 @@
*/
.xterm {
font-feature-settings: "liga" 0;
cursor: text;
position: relative;
user-select: none;
-ms-user-select: none;
@@ -59,10 +59,10 @@
}
.xterm .xterm-helper-textarea {
/*
* HACK: to fix IE's blinking cursor
* Move textarea out of the screen to the far left, so that the cursor is not visible.
*/
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
@@ -125,16 +125,13 @@
line-height: normal;
}
.xterm {
cursor: text;
}
.xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}
.xterm.xterm-cursor-pointer {
.xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer;
}
@@ -152,6 +149,7 @@
right: 0;
z-index: 10;
color: transparent;
pointer-events: none;
}
.xterm .live-region {
@@ -163,9 +161,49 @@
}
.xterm-dim {
opacity: 0.5;
/* Dim should not apply to background, so the opacity of the foreground color is applied
* explicitly in the generated class and reset to 1 here */
opacity: 1 !important;
}
.xterm-underline {
text-decoration: underline;
.xterm-underline-1 { text-decoration: underline; }
.xterm-underline-2 { text-decoration: double underline; }
.xterm-underline-3 { text-decoration: wavy underline; }
.xterm-underline-4 { text-decoration: dotted underline; }
.xterm-underline-5 { text-decoration: dashed underline; }
.xterm-overline {
text-decoration: overline;
}
.xterm-overline.xterm-underline-1 { text-decoration: overline underline; }
.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; }
.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; }
.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; }
.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; }
.xterm-strikethrough {
text-decoration: line-through;
}
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}
.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer {
z-index: 7;
}
.xterm-decoration-overview-ruler {
z-index: 8;
position: absolute;
top: 0;
right: 0;
pointer-events: none;
}
.xterm-decoration-top {
z-index: 2;
position: relative;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long