123655
This commit is contained in:
@@ -85,7 +85,8 @@ namespace NetPanel.Bl
|
||||
|
||||
public void WriteLine(string line)
|
||||
{
|
||||
_writer.WriteLine(line);
|
||||
//_writer.WriteLine(line);
|
||||
_shellStream.WriteLine(line);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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, // 光标闪烁
|
||||
@@ -66,31 +76,48 @@
|
||||
|
||||
|
||||
// 调整终端的尺寸。
|
||||
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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
1
NetPanel/wwwroot/AdminLTE/plugins/xterm/xterm.js.map
Normal file
1
NetPanel/wwwroot/AdminLTE/plugins/xterm/xterm.js.map
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user