增加回车提交事件,Terminal前端增加文件拖动解析
This commit is contained in:
parent
0f765649a7
commit
1020bbb2ac
@ -13,7 +13,7 @@ Gin + gorm
|
||||
|
||||
## 更新日志
|
||||
2020/12/14 修复无操作自动断开、修复网络延迟造成的js加载延迟问题
|
||||
|
||||
2020/12/16 前端新增文件/文件夹拖动到Terminal的自动解析功能(SFTP需要),修改layer弹出窗口逻辑,增加回车提交事件
|
||||
## 开发计划
|
||||
✔ ssh功能
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"io"
|
||||
"log"
|
||||
@ -47,6 +48,7 @@ type SshConn struct {
|
||||
// Write() be called to receive data from ssh server
|
||||
ComboOutput *wsBufferWriter
|
||||
Session *ssh.Session
|
||||
SftpClient *sftp.Client
|
||||
}
|
||||
|
||||
//flushComboOutput flush ssh.session combine output into websocket response
|
||||
@ -96,14 +98,20 @@ func NewSshConn(cols, rows int, sshClient *ssh.Client) (*SshConn, error) {
|
||||
if err := sshSession.Shell(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
|
||||
sftpclient, err := sftp.NewClient(sshClient) //创建一个sftp客户端
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession, SftpClient: sftpclient}, nil
|
||||
}
|
||||
|
||||
func (s *SshConn) Close() {
|
||||
if s.Session != nil {
|
||||
s.Session.Close()
|
||||
}
|
||||
|
||||
if s.SftpClient != nil{
|
||||
s.SftpClient.Close()
|
||||
}
|
||||
}
|
||||
|
||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||
|
||||
@ -110,13 +110,11 @@ func WsSsh(c *gin.Context) {
|
||||
}
|
||||
defer client.Close()
|
||||
//startTime := time.Now()
|
||||
ssConn, err := core.NewSshConn(cols, rows, client)
|
||||
|
||||
ssConn, err := core.NewSshConn(cols, rows, client) //加入sftp客户端
|
||||
if core.WshandleError(wsConn, err) {
|
||||
return
|
||||
}
|
||||
defer ssConn.Close()
|
||||
|
||||
quitChan := make(chan bool, 3)
|
||||
|
||||
// most messages are ssh output, not webSocket input
|
||||
|
||||
@ -54,10 +54,12 @@ editpass = function () {
|
||||
obj.password = obj.desc
|
||||
delete obj.setpass; //不提交用户的加密密码
|
||||
console.log(obj)
|
||||
parent.open_repass_index = 0;
|
||||
http_send("/repass", obj)
|
||||
}
|
||||
|
||||
add_callback = function (result) {
|
||||
parent.open_add_index = 0;
|
||||
parent.getinfo();
|
||||
parent.layer.closeAll('iframe');
|
||||
}
|
||||
|
||||
@ -12,20 +12,25 @@ setnickname = function (data) {
|
||||
username: data.Username
|
||||
})
|
||||
}
|
||||
|
||||
var open_repass_index = 0;
|
||||
openpass = function (ID) {
|
||||
//console.log(ID)
|
||||
layer.open({
|
||||
maxmin : true,
|
||||
if(open_repass_index > 0){
|
||||
return false
|
||||
}
|
||||
open_repass_index = layer.open({
|
||||
type: 2,
|
||||
maxmin : true,
|
||||
title: '重置加密密码',
|
||||
shadeClose: true,
|
||||
shade: 0.4,
|
||||
mask: true,
|
||||
//maxmin: true, //开启最大化最小化按钮
|
||||
area: ['30vw', '50vh'],
|
||||
content: '/setpass?id=' + ID
|
||||
content: '/setpass?id=' + ID,
|
||||
shadeClose: false,
|
||||
cancel: function(){
|
||||
open_repass_index = 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -142,18 +147,24 @@ search = function () {
|
||||
, data: data.data.List
|
||||
});
|
||||
}
|
||||
|
||||
var open_add_index = 0;
|
||||
add = function () {
|
||||
layer.open({
|
||||
if(open_add_index > 0){
|
||||
return false
|
||||
}
|
||||
open_add_index = layer.open({
|
||||
maxmin : true,
|
||||
type: 2,
|
||||
title: '添加SSH服务器',
|
||||
shadeClose: true,
|
||||
shade: 0.4,
|
||||
mask: true,
|
||||
//maxmin: true, //开启最大化最小化按钮
|
||||
area: ['30vw', '50vh'],
|
||||
content: '/add'
|
||||
content: '/add',
|
||||
shadeClose: false,
|
||||
cancel: function(){
|
||||
open_add_index = 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -166,16 +177,23 @@ del_callbacl = function (result) {
|
||||
getinfo()
|
||||
}
|
||||
|
||||
open_terminal_index = 0;
|
||||
open_terminal = function (ID, sername) {
|
||||
layer.open({
|
||||
if(open_terminal_index > 0){
|
||||
return false
|
||||
}
|
||||
open_terminal_index = layer.open({
|
||||
maxmin : true,
|
||||
type: 2,
|
||||
title: '打开SSH终端:' + sername,
|
||||
shadeClose: true,
|
||||
shade: 0.4,
|
||||
mask: true,
|
||||
//maxmin: true, //开启最大化最小化按钮
|
||||
area: ['30vw', '30vh'],
|
||||
content: '/openterm?id=' + ID + "&sername=" + encodeURI(sername)
|
||||
content: '/openterm?id=' + ID + "&sername=" + encodeURI(sername),
|
||||
shadeClose: false,
|
||||
cancel: function(){
|
||||
open_terminal_index = 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
177
static/js/fileupload.js
Normal file
177
static/js/fileupload.js
Normal file
@ -0,0 +1,177 @@
|
||||
let dropbox = document.getElementById("terms"); //要监听拖动上传的节点
|
||||
|
||||
let fileDrop = {
|
||||
startTime: 0,
|
||||
endTime: 0,
|
||||
uploadLength: 0, //上传数量
|
||||
//splitSize: 1024 * 1024 * 2, //文件上传分片大小
|
||||
filesList: [], // 文件列表数组
|
||||
errorLength: 0, //上传失败文件数量
|
||||
isUpload: true, //上传状态,是否可以上传
|
||||
//uploadSuspend:[], //上传暂停参数
|
||||
isUploadNumber: 800,//限制单次上传数量
|
||||
uploadAllSize: 0, // 上传文件总大小
|
||||
uploadedSize: 0, // 已上传文件大小
|
||||
topUploadedSize: 0, // 上一次文件上传大小
|
||||
uploadExpectTime: 0, // 预计上传时间
|
||||
//initTimer:0, // 初始化计时
|
||||
speedInterval: null, //平局速度定时器
|
||||
timerSpeed: 0, //速度
|
||||
uploading: false,
|
||||
cancel: false,
|
||||
}
|
||||
|
||||
dropbox.addEventListener("dragleave", function (e) {
|
||||
//e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
|
||||
dropbox.addEventListener("dragenter", function (e) {
|
||||
//e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
|
||||
dropbox.addEventListener("dragover", function (e) {
|
||||
//e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
|
||||
dropbox.addEventListener("drop", changes, false);
|
||||
|
||||
function changes(e) {
|
||||
if(!is_login){
|
||||
layer.msg("请等待服务器连接!")
|
||||
}
|
||||
e.preventDefault();
|
||||
let items = e.dataTransfer.items, time, num = 0
|
||||
if (fileDrop.uploading) {
|
||||
layer.msg("已有文件队列上传中")
|
||||
return false
|
||||
}
|
||||
if (items && items.length && items[0].webkitGetAsEntry != null) {
|
||||
if (items[0].kind != 'file') return false;
|
||||
}
|
||||
if (fileDrop.filesList == null) fileDrop.filesList = []
|
||||
for (let i = fileDrop.filesList.length - 1; i >= 0; i--) {
|
||||
if (fileDrop.filesList[i].is_upload) fileDrop.filesList.splice(-i, 1)
|
||||
}
|
||||
|
||||
function update_sync(s) {
|
||||
s.getFilesAndDirectories().then(function (subFilesAndDirs) {
|
||||
return iterateFilesAndDirs(subFilesAndDirs, s.path);
|
||||
});
|
||||
}
|
||||
|
||||
let iterateFilesAndDirs = function (filesAndDirs, path) {
|
||||
for (let i = 0; i < filesAndDirs.length; i++) {
|
||||
if (typeof (filesAndDirs[i].getFilesAndDirectories) == 'function') {
|
||||
update_sync(filesAndDirs[i])
|
||||
} else {
|
||||
if (num > 100) {
|
||||
//fileDrop.isUpload = false;
|
||||
layer.msg(' '+ fileDrop.isUploadNumber +'份,无法上传,请压缩后上传!。',{icon:2,area:'405px'});
|
||||
//clearTimeout(time);
|
||||
return false;
|
||||
}
|
||||
fileDrop.filesList.push({
|
||||
file: filesAndDirs[i],
|
||||
path: path,
|
||||
name: filesAndDirs[i].name.replace('//', '/'),
|
||||
local: (path == "/" ? "" : path) + "/" + filesAndDirs[i].name.replace('//', '/'),
|
||||
size: to_size(filesAndDirs[i].size),
|
||||
upload: 0, //上传状态,未上传:0、上传中:1,已上传:2,上传失败:-1
|
||||
is_upload: false
|
||||
});
|
||||
fileDrop.uploadAllSize += filesAndDirs[i].size
|
||||
fileDrop.uploadLength++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ('getFilesAndDirectories' in e.dataTransfer) {
|
||||
e.dataTransfer.getFilesAndDirectories().then(function (filesAndDirs) {
|
||||
return iterateFilesAndDirs(filesAndDirs, '/');
|
||||
});
|
||||
}
|
||||
//console.log(fileDrop.filesList)
|
||||
layer.load(1, {
|
||||
shade: [0.1,'#fff'] //0.1透明度的白色背景
|
||||
});
|
||||
setTimeout(function () {
|
||||
layer.closeAll('loading')
|
||||
open_upload_window()
|
||||
},3000)
|
||||
|
||||
}
|
||||
|
||||
function open_upload_window() {
|
||||
|
||||
let template = `
|
||||
<table class="layui-table" lay-even="" lay-skin="row" id="file_upload" style="table-layout: fixed;padding-top: 0">
|
||||
<colgroup>
|
||||
<col width="250">
|
||||
<col width="150">
|
||||
<col width="150">
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>文件路径</th>
|
||||
<th>文件大小</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody align="center">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
`
|
||||
layer.open({
|
||||
type: 1,
|
||||
closeBtn: 1,
|
||||
maxmin: true,
|
||||
area: ['550px', '455px'],
|
||||
btn: ['开始上传', '取消上传'],
|
||||
title: '上传文件',
|
||||
skin: 'file_dir_uploads',
|
||||
shade: 0.4,
|
||||
shadeClose: false,
|
||||
content: template,
|
||||
success: function () {
|
||||
for (let i = 0; i < fileDrop.filesList.length; i++) {
|
||||
$("#file_upload tbody").append(create_row(i, fileDrop.filesList[i]));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function create_row(index, file) {
|
||||
console.log(file)
|
||||
return "<tr id='" + index + "'><td title='" + file.local + "' style=\"white-space:nowrap;overflow:hidden;text-overflow: ellipsis;\">" + file.local + "</td> <td>" + file.size + "</td> <td>" + getstatu(file.upload) + "</td></tr>"
|
||||
}
|
||||
|
||||
function getstatu(statu) {
|
||||
//上传状态,未上传:0、上传中:1,已上传:2,上传失败:-1
|
||||
if (statu == -1) {
|
||||
return "<font color='red'>上传失败</font>"
|
||||
} else {
|
||||
if (statu == 0) {
|
||||
return "<font color='black'>未上传</font>"
|
||||
} else if (statu == 1) {
|
||||
return "<font color='#808080'>上传中</font>"
|
||||
} else {
|
||||
return "<font color='green'>已上传</font>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function to_size(a) {
|
||||
var d = [" B", " KB", " MB", " GB", " TB", " PB"];
|
||||
var e = 1024;
|
||||
for (var b = 0; b < d.length; b += 1) {
|
||||
if (a < e) {
|
||||
var num = (b === 0 ? a : a.toFixed(2)) + d[b];
|
||||
return (!isNaN((b === 0 ? a : a.toFixed(2))) && typeof num != 'undefined') ? num : '0B';
|
||||
}
|
||||
a /= e
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,9 @@
|
||||
$("#key").keydown(function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
openterm();
|
||||
return false
|
||||
}
|
||||
});
|
||||
openterm = function () {
|
||||
var pass_info = $('form').serializeArray();
|
||||
var obj = {}; //声明一个对象
|
||||
@ -10,6 +16,7 @@ openterm = function () {
|
||||
|
||||
openterm_callback = function (result) {
|
||||
parent.layer.closeAll('iframe');
|
||||
parent.open_terminal_index = 0;
|
||||
parent.getinfo();
|
||||
var getData = GetRequest();
|
||||
if (top) {
|
||||
|
||||
324
static/js/polyfill.js
Normal file
324
static/js/polyfill.js
Normal file
@ -0,0 +1,324 @@
|
||||
/**********************************
|
||||
Directory Upload Proposal Polyfill
|
||||
Author: Ali Alabbas (Microsoft)
|
||||
**********************************/
|
||||
(function() {
|
||||
// Do not proceed with the polyfill if Directory interface is already natively available,
|
||||
// or if webkitdirectory is not supported (i.e. not Chrome, since the polyfill only works in Chrome)
|
||||
if (window.Directory || !('webkitdirectory' in document.createElement('input') && 'webkitGetAsEntry' in DataTransferItem.prototype)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var allowdirsAttr = 'allowdirs',
|
||||
getFilesMethod = 'getFilesAndDirectories',
|
||||
isSupportedProp = 'isFilesAndDirectoriesSupported',
|
||||
chooseDirMethod = 'chooseDirectory';
|
||||
|
||||
var separator = '/';
|
||||
|
||||
var Directory = function() {
|
||||
this.name = '';
|
||||
this.path = separator;
|
||||
this._children = {};
|
||||
this._items = false;
|
||||
};
|
||||
|
||||
Directory.prototype[getFilesMethod] = function() {
|
||||
var that = this;
|
||||
|
||||
// from drag and drop and file input drag and drop (webkitEntries)
|
||||
if (this._items) {
|
||||
var getItem = function(entry) {
|
||||
if (entry.isDirectory) {
|
||||
var dir = new Directory();
|
||||
dir.name = entry.name;
|
||||
dir.path = entry.fullPath;
|
||||
dir._items = entry;
|
||||
|
||||
return dir;
|
||||
} else {
|
||||
return new Promise(function(resolve, reject) {
|
||||
entry.file(function(file) {
|
||||
resolve(file);
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (this.path === separator) {
|
||||
var promises = [];
|
||||
|
||||
for (var i = 0; i < this._items.length; i++) {
|
||||
var entry;
|
||||
|
||||
// from file input drag and drop (webkitEntries)
|
||||
if (this._items[i].isDirectory || this._items[i].isFile) {
|
||||
entry = this._items[i];
|
||||
} else {
|
||||
entry = this._items[i].webkitGetAsEntry();
|
||||
}
|
||||
|
||||
promises.push(getItem(entry));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
} else {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var dirReader = that._items.createReader();
|
||||
var promises = [];
|
||||
|
||||
var readEntries = function() {
|
||||
dirReader.readEntries(function(entries) {
|
||||
if (!entries.length) {
|
||||
resolve(Promise.all(promises));
|
||||
} else {
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
promises.push(getItem(entries[i]));
|
||||
}
|
||||
|
||||
readEntries();
|
||||
}
|
||||
}, reject);
|
||||
};
|
||||
|
||||
readEntries();
|
||||
});
|
||||
}
|
||||
// from file input manual selection
|
||||
} else {
|
||||
var arr = [];
|
||||
|
||||
for (var child in this._children) {
|
||||
arr.push(this._children[child]);
|
||||
}
|
||||
|
||||
return Promise.resolve(arr);
|
||||
}
|
||||
};
|
||||
|
||||
// set blank as default for all inputs
|
||||
HTMLInputElement.prototype[getFilesMethod] = function() {
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
// if OS is Mac, the combined directory and file picker is supported
|
||||
HTMLInputElement.prototype[isSupportedProp] = navigator.appVersion.indexOf("Mac") !== -1;
|
||||
|
||||
HTMLInputElement.prototype[allowdirsAttr] = undefined;
|
||||
HTMLInputElement.prototype[chooseDirMethod] = undefined;
|
||||
|
||||
// expose Directory interface to window
|
||||
window.Directory = Directory;
|
||||
|
||||
/********************
|
||||
**** File Input ****
|
||||
********************/
|
||||
var convertInputs = function(nodes) {
|
||||
var recurse = function(dir, path, fullPath, file) {
|
||||
var pathPieces = path.split(separator);
|
||||
var dirName = pathPieces.shift();
|
||||
|
||||
if (pathPieces.length > 0) {
|
||||
var subDir = new Directory();
|
||||
subDir.name = dirName;
|
||||
subDir.path = separator + fullPath;
|
||||
|
||||
if (!dir._children[subDir.name]) {
|
||||
dir._children[subDir.name] = subDir;
|
||||
}
|
||||
|
||||
recurse(dir._children[subDir.name], pathPieces.join(separator), fullPath, file);
|
||||
} else {
|
||||
dir._children[file.name] = file;
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
|
||||
if (node.tagName === 'INPUT' && node.type === 'file') {
|
||||
var getFiles = function() {
|
||||
var files = node.files;
|
||||
|
||||
if (draggedAndDropped) {
|
||||
files = node.webkitEntries;
|
||||
draggedAndDropped = false;
|
||||
} else {
|
||||
if (files.length === 0) {
|
||||
files = node.shadowRoot.querySelector('#input1').files;
|
||||
|
||||
if (files.length === 0) {
|
||||
files = node.shadowRoot.querySelector('#input2').files;
|
||||
|
||||
if (files.length === 0) {
|
||||
files = node.webkitEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
};
|
||||
|
||||
var draggedAndDropped = false;
|
||||
|
||||
node.addEventListener('drop', function(e) {
|
||||
draggedAndDropped = true;
|
||||
}, false);
|
||||
|
||||
if (node.hasAttribute(allowdirsAttr)) {
|
||||
// force multiple selection for default behavior
|
||||
if (!node.hasAttribute('multiple')) {
|
||||
node.setAttribute('multiple', '');
|
||||
}
|
||||
|
||||
var shadow = node.createShadowRoot();
|
||||
|
||||
node[chooseDirMethod] = function() {
|
||||
// can't do this without an actual click
|
||||
console.log('This is unsupported. For security reasons the dialog cannot be triggered unless it is a response to some user triggered event such as a click on some other element.');
|
||||
};
|
||||
|
||||
shadow.innerHTML = '<div style="border: 1px solid #999; padding: 3px; width: 235px; box-sizing: content-box; font-size: 14px; height: 21px;">'
|
||||
+ '<div id="fileButtons" style="box-sizing: content-box;">'
|
||||
+ '<button id="button1" style="width: 100px; box-sizing: content-box;">Choose file(s)...</button>'
|
||||
+ '<button id="button2" style="width: 100px; box-sizing: content-box; margin-left: 3px;">Choose folder...</button>'
|
||||
+ '</div>'
|
||||
+ '<div id="filesChosen" style="padding: 3px; display: none; box-sizing: content-box;"><span id="filesChosenText">files selected...</span>'
|
||||
+ '<a id="clear" title="Clear selection" href="javascript:;" style="text-decoration: none; float: right; margin: -3px -1px 0 0; padding: 3px; font-weight: bold; font-size: 16px; color:#999; box-sizing: content-box;">×</a>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<input id="input1" type="file" multiple style="display: none;">'
|
||||
+ '<input id="input2" type="file" webkitdirectory style="display: none;">'
|
||||
+ '</div>';
|
||||
|
||||
shadow.querySelector('#button1').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
shadow.querySelector('#input1').click();
|
||||
};
|
||||
|
||||
shadow.querySelector('#button2').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
shadow.querySelector('#input2').click();
|
||||
};
|
||||
|
||||
var toggleView = function(defaultView, filesLength) {
|
||||
shadow.querySelector('#fileButtons').style.display = defaultView ? 'block' : 'none';
|
||||
shadow.querySelector('#filesChosen').style.display = defaultView ? 'none' : 'block';
|
||||
|
||||
if (!defaultView) {
|
||||
shadow.querySelector('#filesChosenText').innerText = filesLength + ' file' + (filesLength > 1 ? 's' : '') + ' selected...';
|
||||
}
|
||||
};
|
||||
|
||||
var changeHandler = function(e) {
|
||||
node.dispatchEvent(new Event('change'));
|
||||
|
||||
toggleView(false, getFiles().length);
|
||||
};
|
||||
|
||||
shadow.querySelector('#input1').onchange = shadow.querySelector('#input2').onchange = changeHandler;
|
||||
|
||||
var clear = function (e) {
|
||||
toggleView(true);
|
||||
|
||||
var form = document.createElement('form');
|
||||
node.parentNode.insertBefore(form, node);
|
||||
node.parentNode.removeChild(node);
|
||||
form.appendChild(node);
|
||||
form.reset();
|
||||
|
||||
form.parentNode.insertBefore(node, form);
|
||||
form.parentNode.removeChild(form);
|
||||
|
||||
// reset does not instantly occur, need to give it some time
|
||||
setTimeout(function() {
|
||||
node.dispatchEvent(new Event('change'));
|
||||
}, 1);
|
||||
};
|
||||
|
||||
shadow.querySelector('#clear').onclick = clear;
|
||||
}
|
||||
|
||||
node.addEventListener('change', function() {
|
||||
var dir = new Directory();
|
||||
|
||||
var files = getFiles();
|
||||
|
||||
if (files.length > 0) {
|
||||
if (node.hasAttribute(allowdirsAttr)) {
|
||||
toggleView(false, files.length);
|
||||
}
|
||||
|
||||
// from file input drag and drop (webkitEntries)
|
||||
if (files[0].isFile || files[0].isDirectory) {
|
||||
dir._items = files;
|
||||
} else {
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
var path = file.webkitRelativePath;
|
||||
var fullPath = path.substring(0, path.lastIndexOf(separator));
|
||||
|
||||
recurse(dir, path, fullPath, file);
|
||||
}
|
||||
}
|
||||
} else if (node.hasAttribute(allowdirsAttr)) {
|
||||
toggleView(true, files.length);
|
||||
}
|
||||
|
||||
this[getFilesMethod] = function() {
|
||||
return dir[getFilesMethod]();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// polyfill file inputs when the DOM loads
|
||||
document.addEventListener('DOMContentLoaded', function(event) {
|
||||
convertInputs(document.getElementsByTagName('input'));
|
||||
});
|
||||
|
||||
// polyfill file inputs that are created dynamically and inserted into the body
|
||||
var observer = new MutationObserver(function(mutations, observer) {
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
if (mutations[i].addedNodes.length > 0) {
|
||||
convertInputs(mutations[i].addedNodes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {childList: true, subtree: true});
|
||||
|
||||
/***********************
|
||||
**** Drag and drop ****
|
||||
***********************/
|
||||
// keep a reference to the original method
|
||||
var _addEventListener = EventTarget.prototype.addEventListener;
|
||||
|
||||
DataTransfer.prototype[getFilesMethod] = function() {
|
||||
return Promise.resolve([]);
|
||||
};
|
||||
|
||||
EventTarget.prototype.addEventListener = function(type, listener, useCapture) {
|
||||
if (type === 'drop') {
|
||||
var _listener = listener;
|
||||
|
||||
listener = function(e) {
|
||||
var dir = new Directory();
|
||||
dir._items = e.dataTransfer.items;
|
||||
|
||||
e.dataTransfer[getFilesMethod] = function() {
|
||||
return dir[getFilesMethod]();
|
||||
};
|
||||
|
||||
_listener(e);
|
||||
};
|
||||
}
|
||||
|
||||
// call the original method
|
||||
return _addEventListener.apply(this, arguments);
|
||||
};
|
||||
}());
|
||||
@ -1,33 +1,33 @@
|
||||
var protocol = document.location.protocol.split(':')[0];
|
||||
var is_login = false;
|
||||
const protocol = document.location.protocol.split(':')[0];
|
||||
var ws_p = "ws";
|
||||
if (protocol == "https") {
|
||||
ws_p = "wss";
|
||||
}
|
||||
var socket = new WebSocket(ws_p + '://' + window.location.host + '/v1/term/' + GetQueryString("sid"));
|
||||
var term = new Terminal({cols: 180, rows: 50, screenKeys: true, cursorBlink: true, cursorStyle: "block"});
|
||||
term.open(document.getElementById('terms'));
|
||||
window.onresize = function () {
|
||||
fit.fit(term);
|
||||
};
|
||||
socket.onopen = function () {
|
||||
var token = window.localStorage.getItem("token")
|
||||
const token = window.localStorage.getItem("token")
|
||||
if (token == "") {
|
||||
if (window != top) {
|
||||
top.location.href = "/login";
|
||||
}
|
||||
window.location.href = "/login";
|
||||
return
|
||||
}
|
||||
var auth = {
|
||||
const auth = {
|
||||
type: "auth",
|
||||
token: token,
|
||||
}
|
||||
const socket = new WebSocket(ws_p + '://' + window.location.host + '/v1/term/' + GetQueryString("sid"));
|
||||
const term = new Terminal({cols: 180, rows: 50, screenKeys: true, cursorBlink: true, cursorStyle: "block"});
|
||||
term.open(document.getElementById('terms'));
|
||||
window.onresize = function () {
|
||||
fit.fit(term);
|
||||
};
|
||||
socket.onopen = function () {
|
||||
socket.send(JSON.stringify(auth)); //验证权限
|
||||
term.write("正在验证\r\n");
|
||||
term.toggleFullscreen(true);
|
||||
fit.fit(term);
|
||||
term.on('data', function (data) {
|
||||
var sdata = {
|
||||
let sdata = {
|
||||
type: "cmd",
|
||||
cmd: data,
|
||||
}
|
||||
@ -36,7 +36,7 @@ socket.onopen = function () {
|
||||
|
||||
term.on('resize', size => {
|
||||
//console.log('resize', [size.cols, size.rows]);
|
||||
var sdata = {
|
||||
let sdata = {
|
||||
type: "resize",
|
||||
cols: size.cols,
|
||||
rows: size.rows,
|
||||
@ -45,13 +45,18 @@ socket.onopen = function () {
|
||||
});
|
||||
|
||||
socket.onmessage = function (msg) {
|
||||
if(!is_login){
|
||||
is_login = true
|
||||
}
|
||||
term.write(msg.data);
|
||||
};
|
||||
socket.onerror = function (e) {
|
||||
is_login = false
|
||||
console.log(e);
|
||||
};
|
||||
|
||||
socket.onclose = function (e) {
|
||||
is_login = false
|
||||
console.log(e);
|
||||
term.write("连接已断开:" + e.reason + "\r\n");
|
||||
//term.destroy();
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js"></script>
|
||||
<script src="/static/js/net.js"></script>
|
||||
<script src="/static/js/aes.js?v=1.0"></script>
|
||||
<script src="/static/js/add.js?v=1.93"></script>
|
||||
<script src="/static/js/add.js?v=1.95"></script>
|
||||
<script>
|
||||
var index = layer.load(0, {shade: [0.1,'#fff']});
|
||||
document.onreadystatechange = completeLoading;
|
||||
@ -86,6 +86,11 @@
|
||||
layer.close(index);
|
||||
}
|
||||
}
|
||||
$(document).keyup(function(event){
|
||||
if(event.keyCode ==13){
|
||||
addser();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -38,7 +38,7 @@
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/aes.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js"></script>
|
||||
<script src="/static/js/net.js?v=0.1"></script>
|
||||
<script src="/static/js/openterm.js?v=0.91"></script>
|
||||
<script src="/static/js/openterm.js?v=0.99.1"></script>
|
||||
<script>
|
||||
var index = layer.load(0, {shade: [0.1,'#fff']});
|
||||
document.onreadystatechange = completeLoading;
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.18.0/js/md5.min.js"></script>
|
||||
<script src="/static/js/net.js?v=1.0"></script>
|
||||
<script src="/static/js/aes.js?v=1.6"></script>
|
||||
<script src="/static/js/add.js?v=1.95"></script>
|
||||
<script src="/static/js/add.js?v=1.96"></script>
|
||||
<script>
|
||||
var index = layer.load(0, {shade: [0.1,'#fff']});
|
||||
document.onreadystatechange = completeLoading;
|
||||
@ -62,6 +62,11 @@
|
||||
layer.close(index);
|
||||
}
|
||||
}
|
||||
$(document).keyup(function(event){
|
||||
if(event.keyCode ==13){
|
||||
editpass();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -44,7 +44,7 @@
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<script src="/static/assets/layui.all.js?v=1"></script>
|
||||
<script src="/static/js/net.js?v=1.3"></script>
|
||||
<script src="/static/js/console.js?v=1.93"></script>
|
||||
<script src="/static/js/console.js?v=1.99.1"></script>
|
||||
<script>
|
||||
var index = layer.load(0, {shade: [0.1,'#fff']});
|
||||
document.onreadystatechange = completeLoading;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
|
||||
<link href="https://cdn.bootcdn.net/ajax/libs/xterm/3.9.2/xterm.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/assets/css/layui.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/static/css/fullscreen.min.css" rel="stylesheet" type="text/css"/>
|
||||
<style>
|
||||
html{
|
||||
@ -27,14 +28,17 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="terms" style="height: 100vh;width: 100vw"></div>
|
||||
</body>
|
||||
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<script src="https://cdn.bootcdn.net/ajax/libs/layer/3.1.1/layer.min.js"></script>
|
||||
<script src="/static/assets/layui.all.js?v=1"></script>
|
||||
<script src="/static/xterm/xterm.min.js"></script>
|
||||
<script src="/static/xterm/fullscreen.min.js"></script>
|
||||
<script src="/static/xterm/fit.min.js"></script>
|
||||
<script src="/static/xterm/search.min.js"></script>
|
||||
<script src="/static/js/net.js?v=1.9"></script>
|
||||
<script src="/static/xterm/main.js?v=0.6"></script>
|
||||
<script src="/static/xterm/main.js?v=0.62"></script>
|
||||
<script src="/static/js/polyfill.js"></script>
|
||||
<script src="/static/js/fileupload.js?v=0.30"></script>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user