123655
This commit is contained in:
@@ -85,7 +85,8 @@ namespace NetPanel.Bl
|
|||||||
|
|
||||||
public void WriteLine(string line)
|
public void WriteLine(string line)
|
||||||
{
|
{
|
||||||
_writer.WriteLine(line);
|
//_writer.WriteLine(line);
|
||||||
|
_shellStream.WriteLine(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@
|
|||||||
|
|
||||||
<div id="terminal" style=""></div>
|
<div id="terminal" style=""></div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix"></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -37,12 +36,23 @@
|
|||||||
|
|
||||||
</section>
|
</section>
|
||||||
<link href="/adminlte/plugins/xterm/xterm.css" rel="stylesheet" />
|
<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 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({
|
var term = new Terminal({
|
||||||
cursorStyle: 'underline', //光标样式
|
cursorStyle: 'underline', //光标样式
|
||||||
cursorBlink: true, // 光标闪烁
|
cursorBlink: true, // 光标闪烁
|
||||||
@@ -66,31 +76,48 @@
|
|||||||
|
|
||||||
|
|
||||||
// 调整终端的尺寸。
|
// 调整终端的尺寸。
|
||||||
term.resize(columns, parseInt(height / 22));
|
// term.resize(columns, parseInt(height / 22));
|
||||||
|
|
||||||
//回车输入的内容
|
//回车输入的内容
|
||||||
var curr_line = '';
|
var curr_line = '';
|
||||||
|
|
||||||
|
var curr_user = '';
|
||||||
//历史内容
|
//历史内容
|
||||||
var entries = [];
|
var entries = [];
|
||||||
var currPos = 0;
|
var currPos = 0;
|
||||||
var pos = 0;
|
var pos = 0;
|
||||||
var connectionId = '';
|
var connectionId = '';
|
||||||
|
|
||||||
term.open(document.getElementById('terminal'));
|
|
||||||
|
|
||||||
|
|
||||||
term.prompt = () => {
|
term.prompt = () => {
|
||||||
term.write('\n\u001b[32m$ >\u001b[37m');
|
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();
|
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
|
||||||
|
|
||||||
|
|
||||||
//signalR接收消息
|
//signalR接收消息
|
||||||
connection.on("ReceiveMessage", function (msg) {
|
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();
|
// term.prompt();
|
||||||
connectionId = msg.obj;
|
connectionId = msg.obj;
|
||||||
//创建 ssh 客户端
|
//创建 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', () => {
|
connection.on('WriteErrorAsync', () => {
|
||||||
|
|
||||||
term.write('SessionClosed');
|
term.write('SessionClosed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//监听按键
|
||||||
|
term.onKey((obj) => {
|
||||||
|
var ev = obj.domEvent;
|
||||||
term.on('key', function (key, ev) {
|
var key = obj.key;
|
||||||
|
const printable = !ev.altKey && !ev.altGraphKey && !ev.metaKey
|
||||||
|
|
||||||
const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
|
|
||||||
//const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.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 (ev.keyCode === 13) { // Enter key
|
||||||
if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace
|
if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace
|
||||||
entries.push(curr_line);
|
entries.push(curr_line);
|
||||||
currPos = entries.length - 1;
|
currPos = entries.length - 1;
|
||||||
// term.prompt();
|
// term.prompt();
|
||||||
|
|
||||||
|
//发送命令
|
||||||
connection.invoke('WriteLineAsync', curr_line).then((result) => {
|
connection.invoke('WriteLineAsync', curr_line).then((result) => {
|
||||||
if (result.code == 1) {
|
|
||||||
|
|
||||||
// term.write('\n' + result.obj);
|
|
||||||
// term.prompt();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
term.write('\n\33[2K\r\u001b[32m$ >\u001b[37m');
|
term.write('\n' + curr_user);
|
||||||
}
|
}
|
||||||
curr_line = '';
|
curr_line = '';
|
||||||
} else if (ev.keyCode === 8) { // Backspace
|
} else if (ev.keyCode === 8) { // Backspace
|
||||||
if (term.buffer.cursorX > cursorx) {
|
if (curr_line.length > 0) {
|
||||||
curr_line = curr_line.slice(0, -1);
|
curr_line = curr_line.slice(0, -1);
|
||||||
term.write('\b \b');
|
term.write('\b \b');
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ev.keyCode === 38) { // Up arrow
|
} else if (ev.keyCode === 38) { // Up arrow
|
||||||
if (entries.length > 0) {
|
if (entries.length > 0) {
|
||||||
if (currPos > 0) {
|
if (currPos > 0) {
|
||||||
currPos -= 1;
|
currPos -= 1;
|
||||||
}
|
}
|
||||||
curr_line = entries[currPos];
|
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
|
} else if (ev.keyCode === 40) { // Down arrow
|
||||||
currPos += 1;
|
currPos += 1;
|
||||||
if (currPos === entries.length || entries.length === 0) {
|
if (currPos === entries.length || entries.length === 0) {
|
||||||
currPos -= 1;
|
currPos -= 1;
|
||||||
curr_line = '';
|
curr_line = '';
|
||||||
term.write('\33[2K\r\u001b[32m$ >\u001b[37m');
|
//删除当前行
|
||||||
|
term.write('\x1b[2K');
|
||||||
|
//运动光标到第一行
|
||||||
|
term.write('\x1b[0G');
|
||||||
|
term.write(curr_user);
|
||||||
} else {
|
} else {
|
||||||
curr_line = entries[currPos];
|
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) {
|
} 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 {
|
.xterm {
|
||||||
font-feature-settings: "liga" 0;
|
cursor: text;
|
||||||
position: relative;
|
position: relative;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
@@ -59,10 +59,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.xterm .xterm-helper-textarea {
|
.xterm .xterm-helper-textarea {
|
||||||
/*
|
padding: 0;
|
||||||
* HACK: to fix IE's blinking cursor
|
border: 0;
|
||||||
* Move textarea out of the screen to the far left, so that the cursor is not visible.
|
margin: 0;
|
||||||
*/
|
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
left: -9999em;
|
left: -9999em;
|
||||||
@@ -125,16 +125,13 @@
|
|||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xterm {
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xterm.enable-mouse-events {
|
.xterm.enable-mouse-events {
|
||||||
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xterm.xterm-cursor-pointer {
|
.xterm.xterm-cursor-pointer,
|
||||||
|
.xterm .xterm-cursor-pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +149,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xterm .live-region {
|
.xterm .live-region {
|
||||||
@@ -163,9 +161,49 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.xterm-dim {
|
.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 {
|
.xterm-underline-1 { text-decoration: underline; }
|
||||||
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