mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-10-22 19:59:23 +08:00
小功能增加
This commit is contained in:
21
main.go
21
main.go
@@ -6,9 +6,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
. "github.com/langhuihui/monibuca/monica"
|
|
||||||
"github.com/langhuihui/monibuca/monica/util"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -19,6 +16,10 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
. "github.com/langhuihui/monibuca/monica"
|
||||||
|
"github.com/langhuihui/monibuca/monica/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstanceDesc struct {
|
type InstanceDesc struct {
|
||||||
@@ -110,6 +111,7 @@ func initInstance(w http.ResponseWriter, r *http.Request) {
|
|||||||
instanceDesc := new(InstanceDesc)
|
instanceDesc := new(InstanceDesc)
|
||||||
sse := util.NewSSE(w, r.Context())
|
sse := util.NewSSE(w, r.Context())
|
||||||
err := json.Unmarshal([]byte(r.URL.Query().Get("info")), instanceDesc)
|
err := json.Unmarshal([]byte(r.URL.Query().Get("info")), instanceDesc)
|
||||||
|
clearDir := r.URL.Query().Get("clear") != ""
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sse.WriteEvent("exception", []byte(err.Error()))
|
sse.WriteEvent("exception", []byte(err.Error()))
|
||||||
@@ -121,7 +123,7 @@ func initInstance(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
sse.WriteEvent("step", []byte("1:参数解析成功!"))
|
sse.WriteEvent("step", []byte("1:参数解析成功!"))
|
||||||
err = instanceDesc.createDir(sse)
|
err = instanceDesc.createDir(sse, clearDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -164,7 +166,10 @@ func (p *InstanceDesc) writeExecSSE(sse *util.SSE, cmd *exec.Cmd) error {
|
|||||||
cmd.Dir = p.Path
|
cmd.Dir = p.Path
|
||||||
return sse.WriteExec(cmd)
|
return sse.WriteExec(cmd)
|
||||||
}
|
}
|
||||||
func (p *InstanceDesc) createDir(sse *util.SSE) (err error) {
|
func (p *InstanceDesc) createDir(sse *util.SSE, clearDir bool) (err error) {
|
||||||
|
if clearDir {
|
||||||
|
os.RemoveAll(p.Path)
|
||||||
|
}
|
||||||
err = os.MkdirAll(p.Path, 0666)
|
err = os.MkdirAll(p.Path, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -206,8 +211,10 @@ func main(){
|
|||||||
}
|
}
|
||||||
sse.WriteEvent("step", []byte("5:go build 成功!"))
|
sse.WriteEvent("step", []byte("5:go build 成功!"))
|
||||||
build.Reset()
|
build.Reset()
|
||||||
build.WriteString("kill -9 `cat pid`\nnohup .")
|
build.WriteString("kill -9 `cat pid`\nnohup ./")
|
||||||
build.WriteString(path.Dir(path.Join(p.Path, "main.go")))
|
binFile := strings.TrimSuffix(p.Path, "/")
|
||||||
|
_, binFile = path.Split(binFile)
|
||||||
|
build.WriteString(binFile)
|
||||||
build.WriteString(" > log.txt & echo $! > pid\n")
|
build.WriteString(" > log.txt & echo $! > pid\n")
|
||||||
err = ioutil.WriteFile(path.Join(p.Path, "restart.sh"), build.Bytes(), 0777)
|
err = ioutil.WriteFile(path.Join(p.Path, "restart.sh"), build.Bytes(), 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
BIN
monibuca.exe~
BIN
monibuca.exe~
Binary file not shown.
@@ -9,10 +9,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var ConfigRaw []byte
|
var ConfigRaw []byte
|
||||||
var Version = "0.1.2"
|
var Version = "0.2.1"
|
||||||
|
|
||||||
func Run(configFile string) (err error) {
|
func Run(configFile string) (err error) {
|
||||||
|
log.Printf("start monibuca version:%s", Version)
|
||||||
if ConfigRaw, err = ioutil.ReadFile(configFile); err != nil {
|
if ConfigRaw, err = ioutil.ReadFile(configFile); err != nil {
|
||||||
|
log.Printf("read config file error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go Summary.StartSummary()
|
go Summary.StartSummary()
|
||||||
@@ -31,6 +33,8 @@ func Run(configFile string) (err error) {
|
|||||||
go config.Run()
|
go config.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("decode config file error: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
package gateway
|
package gateway
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/langhuihui/monibuca/monica"
|
"encoding/json"
|
||||||
. "github.com/langhuihui/monibuca/monica/util"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -10,6 +9,9 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
. "github.com/langhuihui/monibuca/monica"
|
||||||
|
. "github.com/langhuihui/monibuca/monica/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -30,6 +32,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
func run() {
|
func run() {
|
||||||
|
http.HandleFunc("/api/sysInfo", sysInfo)
|
||||||
http.HandleFunc("/api/stop", stopPublish)
|
http.HandleFunc("/api/stop", stopPublish)
|
||||||
http.HandleFunc("/api/summary", summary)
|
http.HandleFunc("/api/summary", summary)
|
||||||
http.HandleFunc("/api/logs", watchLogs)
|
http.HandleFunc("/api/logs", watchLogs)
|
||||||
@@ -95,3 +98,9 @@ func summary(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func sysInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
|
bytes, err := json.Marshal(&struct{ Version string }{Version: Version})
|
||||||
|
if err == nil {
|
||||||
|
_, err = w.Write(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
535
pm/dist/ajax.js
vendored
Normal file
535
pm/dist/ajax.js
vendored
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
// a simple ajax
|
||||||
|
!(function () {
|
||||||
|
|
||||||
|
var jsonType = 'application/json';
|
||||||
|
var htmlType = 'text/html';
|
||||||
|
var xmlTypeRE = /^(?:text|application)\/xml/i;
|
||||||
|
var blankRE = /^\s*$/; // \s
|
||||||
|
|
||||||
|
/*
|
||||||
|
* default setting
|
||||||
|
* */
|
||||||
|
var _settings = {
|
||||||
|
|
||||||
|
type: "GET",
|
||||||
|
|
||||||
|
beforeSend: noop,
|
||||||
|
|
||||||
|
success: noop,
|
||||||
|
|
||||||
|
error: noop,
|
||||||
|
|
||||||
|
complete: noop,
|
||||||
|
|
||||||
|
context: null,
|
||||||
|
|
||||||
|
xhr: function () {
|
||||||
|
return new window.XMLHttpRequest();
|
||||||
|
},
|
||||||
|
|
||||||
|
accepts: {
|
||||||
|
json: jsonType,
|
||||||
|
xml: 'application/xml, text/xml',
|
||||||
|
html: htmlType,
|
||||||
|
text: 'text/plain'
|
||||||
|
},
|
||||||
|
|
||||||
|
crossDomain: false,
|
||||||
|
|
||||||
|
timeout: 0,
|
||||||
|
|
||||||
|
username: null,
|
||||||
|
|
||||||
|
password: null,
|
||||||
|
|
||||||
|
processData: true,
|
||||||
|
|
||||||
|
promise: noop
|
||||||
|
};
|
||||||
|
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
var ajax = function (options) {
|
||||||
|
|
||||||
|
//
|
||||||
|
var settings = extend({}, options || {});
|
||||||
|
|
||||||
|
//
|
||||||
|
for (var key in _settings) {
|
||||||
|
if (settings[key] === undefined) {
|
||||||
|
settings[key] = _settings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
var q = {};
|
||||||
|
var promise = new Promise(function (resolve, reject) {
|
||||||
|
q.resolve = resolve;
|
||||||
|
q.reject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.resolve = q.resolve;
|
||||||
|
promise.reject = q.reject;
|
||||||
|
|
||||||
|
settings.promise = promise;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
//
|
||||||
|
settings.promise = {
|
||||||
|
resolve: noop,
|
||||||
|
reject: noop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
if (!settings.crossDomain) {
|
||||||
|
settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) && RegExp.$2 !== window.location.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataType = settings.dataType;
|
||||||
|
// jsonp
|
||||||
|
if (dataType === 'jsonp') {
|
||||||
|
//
|
||||||
|
var hasPlaceholder = /=\?/.test(settings.url);
|
||||||
|
if (!hasPlaceholder) {
|
||||||
|
var jsonpCallback = (settings.jsonp || 'callback') + '=?';
|
||||||
|
|
||||||
|
settings.url = appendQuery(settings.url, jsonpCallback)
|
||||||
|
}
|
||||||
|
return JSONP(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// url
|
||||||
|
if (!settings.url) {
|
||||||
|
settings.url = window.location.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
serializeData(settings);
|
||||||
|
|
||||||
|
var mime = settings.accepts[dataType]; // mime
|
||||||
|
var baseHeader = {}; // header
|
||||||
|
var protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol; // protocol
|
||||||
|
var xhr = _settings.xhr();
|
||||||
|
var abortTimeout;
|
||||||
|
|
||||||
|
// X-Requested-With header
|
||||||
|
// For cross-domain requests, seeing as conditions for a preflight are
|
||||||
|
// akin to a jigsaw puzzle, we simply never set it to be sure.
|
||||||
|
// (it can always be set on a per-request basis or even using ajaxSetup)
|
||||||
|
// For same-domain requests, won't change header if already provided.
|
||||||
|
if (!settings.crossDomain && !baseHeader['X-Requested-With']) {
|
||||||
|
baseHeader['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
|
}
|
||||||
|
|
||||||
|
// mime
|
||||||
|
if (mime) {
|
||||||
|
//
|
||||||
|
baseHeader['Accept'] = mime;
|
||||||
|
|
||||||
|
if (mime.indexOf(',') > -1) {
|
||||||
|
mime = mime.split(',', 2)[0]
|
||||||
|
}
|
||||||
|
//
|
||||||
|
xhr.overrideMimeType && xhr.overrideMimeType(mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// contentType
|
||||||
|
if (settings.contentType || (settings.data && settings.type.toUpperCase() !== 'GET')) {
|
||||||
|
baseHeader['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// headers
|
||||||
|
settings.headers = extend(baseHeader, settings.headers || {});
|
||||||
|
|
||||||
|
// on ready state change
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
// readystate
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
clearTimeout(abortTimeout);
|
||||||
|
var result;
|
||||||
|
var error = false;
|
||||||
|
//
|
||||||
|
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
|
||||||
|
dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type'));
|
||||||
|
result = xhr.responseText;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// xml
|
||||||
|
if (dataType === 'xml') {
|
||||||
|
result = xhr.responseXML;
|
||||||
|
}
|
||||||
|
// json
|
||||||
|
else if (dataType === 'json') {
|
||||||
|
result = blankRE.test(result) ? null : JSON.parse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
ajaxError(error, 'parseerror', xhr, settings);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ajaxSuccess(result, xhr, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ajaxError(null, 'error', xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// async
|
||||||
|
var async = 'async' in settings ? settings.async : true;
|
||||||
|
|
||||||
|
// open
|
||||||
|
xhr.open(settings.type, settings.url, async, settings.username, settings.password);
|
||||||
|
|
||||||
|
// xhrFields
|
||||||
|
if (settings.xhrFields) {
|
||||||
|
for (var name in settings.xhrFields) {
|
||||||
|
xhr[name] = settings.xhrFields[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override mime type if needed
|
||||||
|
if (settings.mimeType && xhr.overrideMimeType) {
|
||||||
|
xhr.overrideMimeType(settings.mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set request header
|
||||||
|
for (var name in settings.headers) {
|
||||||
|
// Support: IE<9
|
||||||
|
// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
|
||||||
|
// request header to a null-value.
|
||||||
|
//
|
||||||
|
// To keep consistent with other XHR implementations, cast the value
|
||||||
|
// to string and ignore `undefined`.
|
||||||
|
if (settings.headers[name] !== undefined) {
|
||||||
|
xhr.setRequestHeader(name, settings.headers[name] + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// before send
|
||||||
|
if (ajaxBeforeSend(xhr, settings) === false) {
|
||||||
|
xhr.abort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeout
|
||||||
|
if (settings.timeout > 0) {
|
||||||
|
abortTimeout = window.setTimeout(function () {
|
||||||
|
xhr.onreadystatechange = noop;
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError(null, 'timeout', xhr, settings);
|
||||||
|
}, settings.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
xhr.send(settings.data ? settings.data : null);
|
||||||
|
|
||||||
|
return settings.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method get
|
||||||
|
* */
|
||||||
|
ajax.get = function (url, data, success, dataType) {
|
||||||
|
if (isFunction(data)) {
|
||||||
|
dataType = dataType || success;
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ajax({
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: dataType
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method post
|
||||||
|
*
|
||||||
|
* dataType:
|
||||||
|
* */
|
||||||
|
ajax.post = function (url, data, success, dataType) {
|
||||||
|
if (isFunction(data)) {
|
||||||
|
dataType = dataType || success;
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
return ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: dataType
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method getJSON
|
||||||
|
* */
|
||||||
|
ajax.getJSON = function (url, data, success) {
|
||||||
|
|
||||||
|
if (isFunction(data)) {
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ajax({
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: 'json'
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method ajaxSetup
|
||||||
|
* */
|
||||||
|
ajax.ajaxSetup = function (target, settings) {
|
||||||
|
return settings ? extend(extend(target, _settings), settings) : extend(_settings, target);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* utils
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
// triggers and extra global event ajaxBeforeSend that's like ajaxSend but cancelable
|
||||||
|
function ajaxBeforeSend(xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
//
|
||||||
|
if (settings.beforeSend.call(context, xhr, settings) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ajax success
|
||||||
|
function ajaxSuccess(data, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
var status = 'success';
|
||||||
|
settings.success.call(context, data, status, xhr);
|
||||||
|
settings.promise.resolve(data, status, xhr);
|
||||||
|
ajaxComplete(status, xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
|
||||||
|
function ajaxComplete(status, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
settings.complete.call(context, xhr, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// type: "timeout", "error", "abort", "parsererror"
|
||||||
|
function ajaxError(error, type, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
settings.error.call(context, xhr, type, error);
|
||||||
|
settings.promise.reject(xhr, type, error);
|
||||||
|
ajaxComplete(type, xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// jsonp
|
||||||
|
/*
|
||||||
|
* tks: https://www.cnblogs.com/rubylouvre/archive/2011/02/13/1953087.html
|
||||||
|
* */
|
||||||
|
function JSONP(options) {
|
||||||
|
//
|
||||||
|
var callbackName = options.jsonpCallback || 'jsonp' + (new Date().getTime());
|
||||||
|
|
||||||
|
var script = window.document.createElement('script');
|
||||||
|
|
||||||
|
var abort = function () {
|
||||||
|
// 设置 window.xxx = noop
|
||||||
|
if (callbackName in window) {
|
||||||
|
window[callbackName] = noop;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var xhr = {abort: abort};
|
||||||
|
var abortTimeout;
|
||||||
|
|
||||||
|
var head = window.document.getElementsByTagName('head')[0] || window.document.documentElement;
|
||||||
|
|
||||||
|
// ie8+
|
||||||
|
script.onerror = function (error) {
|
||||||
|
_error(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
function _error(error) {
|
||||||
|
window.clearTimeout(abortTimeout);
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError(error.type, xhr, error.type, options);
|
||||||
|
_removeScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
window[callbackName] = function (data) {
|
||||||
|
window.clearTimeout(abortTimeout);
|
||||||
|
ajaxSuccess(data, xhr, options);
|
||||||
|
_removeScript();
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
serializeData(options);
|
||||||
|
|
||||||
|
script.src = options.url.replace(/=\?/, '=' + callbackName);
|
||||||
|
//
|
||||||
|
script.src = appendQuery(script.src, '_=' + (new Date()).getTime());
|
||||||
|
//
|
||||||
|
script.async = true;
|
||||||
|
|
||||||
|
// script charset
|
||||||
|
if (options.scriptCharset) {
|
||||||
|
script.charset = options.scriptCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
head.insertBefore(script, head.firstChild);
|
||||||
|
|
||||||
|
//
|
||||||
|
if (options.timeout > 0) {
|
||||||
|
abortTimeout = window.setTimeout(function () {
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError('timeout', xhr, 'timeout', options);
|
||||||
|
_removeScript();
|
||||||
|
}, options.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove script
|
||||||
|
function _removeScript() {
|
||||||
|
if (script.clearAttributes) {
|
||||||
|
script.clearAttributes();
|
||||||
|
} else {
|
||||||
|
script.onload = script.onreadystatechange = script.onerror = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.parentNode) {
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
script = null;
|
||||||
|
|
||||||
|
delete window[callbackName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mime to data type
|
||||||
|
function mimeToDataType(mime) {
|
||||||
|
return mime && (mime === htmlType ? 'html' : mime === jsonType ? 'json' : xmlTypeRE.test(mime) && 'xml') || 'text'
|
||||||
|
}
|
||||||
|
|
||||||
|
// append query
|
||||||
|
function appendQuery(url, query) {
|
||||||
|
return (url + '&' + query).replace(/[&?]{1,2}/, '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize data
|
||||||
|
function serializeData(options) {
|
||||||
|
// formData
|
||||||
|
if (isObject(options) && !isFormData(options.data) && options.processData) {
|
||||||
|
options.data = param(options.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.data && (!options.type || options.type.toUpperCase() === 'GET')) {
|
||||||
|
options.url = appendQuery(options.url, options.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize
|
||||||
|
function serialize(params, obj, traditional, scope) {
|
||||||
|
var _isArray = isArray(obj);
|
||||||
|
|
||||||
|
for (var key in obj) {
|
||||||
|
var value = obj[key];
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
key = traditional ? scope : scope + '[' + (_isArray ? '' : key) + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle data in serializeArray format
|
||||||
|
if (!scope && _isArray) {
|
||||||
|
params.add(value.name, value.value);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (traditional ? _isArray(value) : isObject(value)) {
|
||||||
|
serialize(params, value, traditional, key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// param
|
||||||
|
function param(obj, traditional) {
|
||||||
|
var params = [];
|
||||||
|
//
|
||||||
|
params.add = function (k, v) {
|
||||||
|
this.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
|
||||||
|
};
|
||||||
|
serialize(params, obj, traditional);
|
||||||
|
return params.join('&').replace('%20', '+');
|
||||||
|
}
|
||||||
|
|
||||||
|
// extend
|
||||||
|
function extend(target) {
|
||||||
|
var slice = Array.prototype.slice;
|
||||||
|
var args = slice.call(arguments, 1);
|
||||||
|
//
|
||||||
|
for (var i = 0, length = args.length; i < length; i++) {
|
||||||
|
var source = args[i] || {};
|
||||||
|
for (var key in source) {
|
||||||
|
if (source.hasOwnProperty(key) && source[key] !== undefined) {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is object
|
||||||
|
function isObject(obj) {
|
||||||
|
var type = typeof obj;
|
||||||
|
return type === 'function' || type === 'object' && !!obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is formData
|
||||||
|
function isFormData(obj) {
|
||||||
|
return obj instanceof FormData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is array
|
||||||
|
function isArray(value) {
|
||||||
|
return Object.prototype.toString.call(value) === "[object Array]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// is function
|
||||||
|
function isFunction(value) {
|
||||||
|
return typeof value === "function";
|
||||||
|
}
|
||||||
|
|
||||||
|
// browser
|
||||||
|
window.ajax = ajax;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2
pm/dist/index.html
vendored
2
pm/dist/index.html
vendored
@@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>pm</title><link href=/css/app.74a1e2f4.css rel=preload as=style><link href=/css/chunk-vendors.22ebf426.css rel=preload as=style><link href=/js/app.4b08c1d1.js rel=preload as=script><link href=/js/chunk-vendors.6b87e1b5.js rel=preload as=script><link href=/css/chunk-vendors.22ebf426.css rel=stylesheet><link href=/css/app.74a1e2f4.css rel=stylesheet></head><body><noscript><strong>We're sorry but pm doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.6b87e1b5.js></script><script src=/js/app.4b08c1d1.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>Monibuca Instance Manager</title><script src=ajax.js></script><link href=/css/app.200d2f8f.css rel=preload as=style><link href=/css/chunk-vendors.22ebf426.css rel=preload as=style><link href=/js/app.fd72a180.js rel=preload as=script><link href=/js/chunk-vendors.6b87e1b5.js rel=preload as=script><link href=/css/chunk-vendors.22ebf426.css rel=stylesheet><link href=/css/app.200d2f8f.css rel=stylesheet></head><body><noscript><strong>We're sorry but pm doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.6b87e1b5.js></script><script src=/js/app.fd72a180.js></script></body></html>
|
2
pm/dist/js/app.4b08c1d1.js
vendored
2
pm/dist/js/app.4b08c1d1.js
vendored
File diff suppressed because one or more lines are too long
1
pm/dist/js/app.4b08c1d1.js.map
vendored
1
pm/dist/js/app.4b08c1d1.js.map
vendored
File diff suppressed because one or more lines are too long
2
pm/dist/js/app.fd72a180.js
vendored
Normal file
2
pm/dist/js/app.fd72a180.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
pm/dist/js/app.fd72a180.js.map
vendored
Normal file
1
pm/dist/js/app.fd72a180.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
535
pm/public/ajax.js
Normal file
535
pm/public/ajax.js
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
// a simple ajax
|
||||||
|
!(function () {
|
||||||
|
|
||||||
|
var jsonType = 'application/json';
|
||||||
|
var htmlType = 'text/html';
|
||||||
|
var xmlTypeRE = /^(?:text|application)\/xml/i;
|
||||||
|
var blankRE = /^\s*$/; // \s
|
||||||
|
|
||||||
|
/*
|
||||||
|
* default setting
|
||||||
|
* */
|
||||||
|
var _settings = {
|
||||||
|
|
||||||
|
type: "GET",
|
||||||
|
|
||||||
|
beforeSend: noop,
|
||||||
|
|
||||||
|
success: noop,
|
||||||
|
|
||||||
|
error: noop,
|
||||||
|
|
||||||
|
complete: noop,
|
||||||
|
|
||||||
|
context: null,
|
||||||
|
|
||||||
|
xhr: function () {
|
||||||
|
return new window.XMLHttpRequest();
|
||||||
|
},
|
||||||
|
|
||||||
|
accepts: {
|
||||||
|
json: jsonType,
|
||||||
|
xml: 'application/xml, text/xml',
|
||||||
|
html: htmlType,
|
||||||
|
text: 'text/plain'
|
||||||
|
},
|
||||||
|
|
||||||
|
crossDomain: false,
|
||||||
|
|
||||||
|
timeout: 0,
|
||||||
|
|
||||||
|
username: null,
|
||||||
|
|
||||||
|
password: null,
|
||||||
|
|
||||||
|
processData: true,
|
||||||
|
|
||||||
|
promise: noop
|
||||||
|
};
|
||||||
|
|
||||||
|
function noop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
var ajax = function (options) {
|
||||||
|
|
||||||
|
//
|
||||||
|
var settings = extend({}, options || {});
|
||||||
|
|
||||||
|
//
|
||||||
|
for (var key in _settings) {
|
||||||
|
if (settings[key] === undefined) {
|
||||||
|
settings[key] = _settings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
var q = {};
|
||||||
|
var promise = new Promise(function (resolve, reject) {
|
||||||
|
q.resolve = resolve;
|
||||||
|
q.reject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.resolve = q.resolve;
|
||||||
|
promise.reject = q.reject;
|
||||||
|
|
||||||
|
settings.promise = promise;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
//
|
||||||
|
settings.promise = {
|
||||||
|
resolve: noop,
|
||||||
|
reject: noop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
if (!settings.crossDomain) {
|
||||||
|
settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) && RegExp.$2 !== window.location.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataType = settings.dataType;
|
||||||
|
// jsonp
|
||||||
|
if (dataType === 'jsonp') {
|
||||||
|
//
|
||||||
|
var hasPlaceholder = /=\?/.test(settings.url);
|
||||||
|
if (!hasPlaceholder) {
|
||||||
|
var jsonpCallback = (settings.jsonp || 'callback') + '=?';
|
||||||
|
|
||||||
|
settings.url = appendQuery(settings.url, jsonpCallback)
|
||||||
|
}
|
||||||
|
return JSONP(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// url
|
||||||
|
if (!settings.url) {
|
||||||
|
settings.url = window.location.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
serializeData(settings);
|
||||||
|
|
||||||
|
var mime = settings.accepts[dataType]; // mime
|
||||||
|
var baseHeader = {}; // header
|
||||||
|
var protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol; // protocol
|
||||||
|
var xhr = _settings.xhr();
|
||||||
|
var abortTimeout;
|
||||||
|
|
||||||
|
// X-Requested-With header
|
||||||
|
// For cross-domain requests, seeing as conditions for a preflight are
|
||||||
|
// akin to a jigsaw puzzle, we simply never set it to be sure.
|
||||||
|
// (it can always be set on a per-request basis or even using ajaxSetup)
|
||||||
|
// For same-domain requests, won't change header if already provided.
|
||||||
|
if (!settings.crossDomain && !baseHeader['X-Requested-With']) {
|
||||||
|
baseHeader['X-Requested-With'] = 'XMLHttpRequest';
|
||||||
|
}
|
||||||
|
|
||||||
|
// mime
|
||||||
|
if (mime) {
|
||||||
|
//
|
||||||
|
baseHeader['Accept'] = mime;
|
||||||
|
|
||||||
|
if (mime.indexOf(',') > -1) {
|
||||||
|
mime = mime.split(',', 2)[0]
|
||||||
|
}
|
||||||
|
//
|
||||||
|
xhr.overrideMimeType && xhr.overrideMimeType(mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// contentType
|
||||||
|
if (settings.contentType || (settings.data && settings.type.toUpperCase() !== 'GET')) {
|
||||||
|
baseHeader['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
// headers
|
||||||
|
settings.headers = extend(baseHeader, settings.headers || {});
|
||||||
|
|
||||||
|
// on ready state change
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
// readystate
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
clearTimeout(abortTimeout);
|
||||||
|
var result;
|
||||||
|
var error = false;
|
||||||
|
//
|
||||||
|
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
|
||||||
|
dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type'));
|
||||||
|
result = xhr.responseText;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// xml
|
||||||
|
if (dataType === 'xml') {
|
||||||
|
result = xhr.responseXML;
|
||||||
|
}
|
||||||
|
// json
|
||||||
|
else if (dataType === 'json') {
|
||||||
|
result = blankRE.test(result) ? null : JSON.parse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
ajaxError(error, 'parseerror', xhr, settings);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ajaxSuccess(result, xhr, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ajaxError(null, 'error', xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// async
|
||||||
|
var async = 'async' in settings ? settings.async : true;
|
||||||
|
|
||||||
|
// open
|
||||||
|
xhr.open(settings.type, settings.url, async, settings.username, settings.password);
|
||||||
|
|
||||||
|
// xhrFields
|
||||||
|
if (settings.xhrFields) {
|
||||||
|
for (var name in settings.xhrFields) {
|
||||||
|
xhr[name] = settings.xhrFields[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override mime type if needed
|
||||||
|
if (settings.mimeType && xhr.overrideMimeType) {
|
||||||
|
xhr.overrideMimeType(settings.mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set request header
|
||||||
|
for (var name in settings.headers) {
|
||||||
|
// Support: IE<9
|
||||||
|
// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
|
||||||
|
// request header to a null-value.
|
||||||
|
//
|
||||||
|
// To keep consistent with other XHR implementations, cast the value
|
||||||
|
// to string and ignore `undefined`.
|
||||||
|
if (settings.headers[name] !== undefined) {
|
||||||
|
xhr.setRequestHeader(name, settings.headers[name] + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// before send
|
||||||
|
if (ajaxBeforeSend(xhr, settings) === false) {
|
||||||
|
xhr.abort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeout
|
||||||
|
if (settings.timeout > 0) {
|
||||||
|
abortTimeout = window.setTimeout(function () {
|
||||||
|
xhr.onreadystatechange = noop;
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError(null, 'timeout', xhr, settings);
|
||||||
|
}, settings.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
xhr.send(settings.data ? settings.data : null);
|
||||||
|
|
||||||
|
return settings.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method get
|
||||||
|
* */
|
||||||
|
ajax.get = function (url, data, success, dataType) {
|
||||||
|
if (isFunction(data)) {
|
||||||
|
dataType = dataType || success;
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ajax({
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: dataType
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method post
|
||||||
|
*
|
||||||
|
* dataType:
|
||||||
|
* */
|
||||||
|
ajax.post = function (url, data, success, dataType) {
|
||||||
|
if (isFunction(data)) {
|
||||||
|
dataType = dataType || success;
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
return ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: dataType
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method getJSON
|
||||||
|
* */
|
||||||
|
ajax.getJSON = function (url, data, success) {
|
||||||
|
|
||||||
|
if (isFunction(data)) {
|
||||||
|
success = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ajax({
|
||||||
|
url: url,
|
||||||
|
data: data,
|
||||||
|
success: success,
|
||||||
|
dataType: 'json'
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* method ajaxSetup
|
||||||
|
* */
|
||||||
|
ajax.ajaxSetup = function (target, settings) {
|
||||||
|
return settings ? extend(extend(target, _settings), settings) : extend(_settings, target);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* utils
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
// triggers and extra global event ajaxBeforeSend that's like ajaxSend but cancelable
|
||||||
|
function ajaxBeforeSend(xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
//
|
||||||
|
if (settings.beforeSend.call(context, xhr, settings) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ajax success
|
||||||
|
function ajaxSuccess(data, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
var status = 'success';
|
||||||
|
settings.success.call(context, data, status, xhr);
|
||||||
|
settings.promise.resolve(data, status, xhr);
|
||||||
|
ajaxComplete(status, xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
|
||||||
|
function ajaxComplete(status, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
settings.complete.call(context, xhr, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// type: "timeout", "error", "abort", "parsererror"
|
||||||
|
function ajaxError(error, type, xhr, settings) {
|
||||||
|
var context = settings.context;
|
||||||
|
settings.error.call(context, xhr, type, error);
|
||||||
|
settings.promise.reject(xhr, type, error);
|
||||||
|
ajaxComplete(type, xhr, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// jsonp
|
||||||
|
/*
|
||||||
|
* tks: https://www.cnblogs.com/rubylouvre/archive/2011/02/13/1953087.html
|
||||||
|
* */
|
||||||
|
function JSONP(options) {
|
||||||
|
//
|
||||||
|
var callbackName = options.jsonpCallback || 'jsonp' + (new Date().getTime());
|
||||||
|
|
||||||
|
var script = window.document.createElement('script');
|
||||||
|
|
||||||
|
var abort = function () {
|
||||||
|
// 设置 window.xxx = noop
|
||||||
|
if (callbackName in window) {
|
||||||
|
window[callbackName] = noop;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var xhr = {abort: abort};
|
||||||
|
var abortTimeout;
|
||||||
|
|
||||||
|
var head = window.document.getElementsByTagName('head')[0] || window.document.documentElement;
|
||||||
|
|
||||||
|
// ie8+
|
||||||
|
script.onerror = function (error) {
|
||||||
|
_error(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
function _error(error) {
|
||||||
|
window.clearTimeout(abortTimeout);
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError(error.type, xhr, error.type, options);
|
||||||
|
_removeScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
window[callbackName] = function (data) {
|
||||||
|
window.clearTimeout(abortTimeout);
|
||||||
|
ajaxSuccess(data, xhr, options);
|
||||||
|
_removeScript();
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
serializeData(options);
|
||||||
|
|
||||||
|
script.src = options.url.replace(/=\?/, '=' + callbackName);
|
||||||
|
//
|
||||||
|
script.src = appendQuery(script.src, '_=' + (new Date()).getTime());
|
||||||
|
//
|
||||||
|
script.async = true;
|
||||||
|
|
||||||
|
// script charset
|
||||||
|
if (options.scriptCharset) {
|
||||||
|
script.charset = options.scriptCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
head.insertBefore(script, head.firstChild);
|
||||||
|
|
||||||
|
//
|
||||||
|
if (options.timeout > 0) {
|
||||||
|
abortTimeout = window.setTimeout(function () {
|
||||||
|
xhr.abort();
|
||||||
|
ajaxError('timeout', xhr, 'timeout', options);
|
||||||
|
_removeScript();
|
||||||
|
}, options.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove script
|
||||||
|
function _removeScript() {
|
||||||
|
if (script.clearAttributes) {
|
||||||
|
script.clearAttributes();
|
||||||
|
} else {
|
||||||
|
script.onload = script.onreadystatechange = script.onerror = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.parentNode) {
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
script = null;
|
||||||
|
|
||||||
|
delete window[callbackName];
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mime to data type
|
||||||
|
function mimeToDataType(mime) {
|
||||||
|
return mime && (mime === htmlType ? 'html' : mime === jsonType ? 'json' : xmlTypeRE.test(mime) && 'xml') || 'text'
|
||||||
|
}
|
||||||
|
|
||||||
|
// append query
|
||||||
|
function appendQuery(url, query) {
|
||||||
|
return (url + '&' + query).replace(/[&?]{1,2}/, '?');
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize data
|
||||||
|
function serializeData(options) {
|
||||||
|
// formData
|
||||||
|
if (isObject(options) && !isFormData(options.data) && options.processData) {
|
||||||
|
options.data = param(options.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.data && (!options.type || options.type.toUpperCase() === 'GET')) {
|
||||||
|
options.url = appendQuery(options.url, options.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize
|
||||||
|
function serialize(params, obj, traditional, scope) {
|
||||||
|
var _isArray = isArray(obj);
|
||||||
|
|
||||||
|
for (var key in obj) {
|
||||||
|
var value = obj[key];
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
key = traditional ? scope : scope + '[' + (_isArray ? '' : key) + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle data in serializeArray format
|
||||||
|
if (!scope && _isArray) {
|
||||||
|
params.add(value.name, value.value);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (traditional ? _isArray(value) : isObject(value)) {
|
||||||
|
serialize(params, value, traditional, key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// param
|
||||||
|
function param(obj, traditional) {
|
||||||
|
var params = [];
|
||||||
|
//
|
||||||
|
params.add = function (k, v) {
|
||||||
|
this.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
|
||||||
|
};
|
||||||
|
serialize(params, obj, traditional);
|
||||||
|
return params.join('&').replace('%20', '+');
|
||||||
|
}
|
||||||
|
|
||||||
|
// extend
|
||||||
|
function extend(target) {
|
||||||
|
var slice = Array.prototype.slice;
|
||||||
|
var args = slice.call(arguments, 1);
|
||||||
|
//
|
||||||
|
for (var i = 0, length = args.length; i < length; i++) {
|
||||||
|
var source = args[i] || {};
|
||||||
|
for (var key in source) {
|
||||||
|
if (source.hasOwnProperty(key) && source[key] !== undefined) {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is object
|
||||||
|
function isObject(obj) {
|
||||||
|
var type = typeof obj;
|
||||||
|
return type === 'function' || type === 'object' && !!obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is formData
|
||||||
|
function isFormData(obj) {
|
||||||
|
return obj instanceof FormData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is array
|
||||||
|
function isArray(value) {
|
||||||
|
return Object.prototype.toString.call(value) === "[object Array]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// is function
|
||||||
|
function isFunction(value) {
|
||||||
|
return typeof value === "function";
|
||||||
|
}
|
||||||
|
|
||||||
|
// browser
|
||||||
|
window.ajax = ajax;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -5,7 +5,8 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title>pm</title>
|
<title>Monibuca Instance Manager</title>
|
||||||
|
<script src="ajax.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
@@ -12,46 +12,54 @@
|
|||||||
<div>
|
<div>
|
||||||
<pre>{{log}}</pre>
|
<pre>{{log}}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
<div slot="footer">
|
||||||
|
<Checkbox v-model="clearDir">安装前清空目录</Checkbox>
|
||||||
|
<Button type="primary" @click="start">开始</Button>
|
||||||
|
<Button type="success" @click="close" v-if="status=='finish'">完成</Button>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let eventSource = null
|
let eventSource = null;
|
||||||
export default {
|
export default {
|
||||||
name: "CreateInstance",
|
name: "CreateInstance",
|
||||||
props: {
|
props: {
|
||||||
info: Object,
|
info: Object
|
||||||
},
|
},
|
||||||
watch: {
|
methods:{
|
||||||
info(v) {
|
start(){
|
||||||
if (v) {
|
eventSource = new EventSource(
|
||||||
eventSource = new EventSource("/create?info="+JSON.stringify(v))
|
"/create?info=" + JSON.stringify(this.info)+(this.clearDir?"&clear=true":"")
|
||||||
eventSource.onmessage = evt => {
|
);
|
||||||
this.log += evt.data + "\n"
|
eventSource.onopen = () => (this.log = "");
|
||||||
if (evt.data == "success") {
|
eventSource.onmessage = evt => {
|
||||||
this.status = "finish"
|
this.log += evt.data + "\n";
|
||||||
eventSource.close()
|
if (evt.data == "success") {
|
||||||
}
|
this.status = "finish";
|
||||||
|
eventSource.close();
|
||||||
}
|
}
|
||||||
eventSource.addEventListener("exception", evt => {
|
};
|
||||||
this.log += evt.data + "\n"
|
eventSource.addEventListener("exception", evt => {
|
||||||
this.status = "error"
|
this.log += evt.data + "\n";
|
||||||
eventSource.close()
|
this.status = "error";
|
||||||
})
|
eventSource.close();
|
||||||
eventSource.addEventListener("step", evt => {
|
});
|
||||||
let [step,msg] = evt.data.split(":")
|
eventSource.addEventListener("step", evt => {
|
||||||
this.currentStep = step|0
|
let [step, msg] = evt.data.split(":");
|
||||||
this.log+=msg+"\n"
|
this.currentStep = step | 0;
|
||||||
})
|
this.log += msg + "\n";
|
||||||
}
|
});
|
||||||
}
|
},close(){
|
||||||
},
|
this.$Modal.remove()
|
||||||
data() {
|
|
||||||
return {currentStep: 0, log: "", status: "process"}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return { clearDir: true, currentStep: 0, log: "", status: "process" };
|
||||||
}
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
</style>
|
</style>
|
@@ -26,15 +26,17 @@
|
|||||||
{{item.Config}}
|
{{item.Config}}
|
||||||
<template slot="action">
|
<template slot="action">
|
||||||
<li @click="removePlugin(name)">
|
<li @click="removePlugin(name)">
|
||||||
<Icon type="ios-trash"/>
|
<Icon type="ios-trash" />移除
|
||||||
移除
|
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<h3>实例名称:</h3>
|
<h3>实例名称:</h3>
|
||||||
<i-input v-model="instanceName" :placeholder="createPath.split('/').pop()"></i-input>
|
<i-input
|
||||||
|
v-model="instanceName"
|
||||||
|
:placeholder="createPath.split('/').pop()"
|
||||||
|
></i-input>
|
||||||
<h4>安装路径:</h4>
|
<h4>安装路径:</h4>
|
||||||
<div>
|
<div>
|
||||||
<pre>{{createPath}}</pre>
|
<pre>{{createPath}}</pre>
|
||||||
@@ -49,23 +51,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ButtonGroup style="display:table;margin:50px auto;">
|
<ButtonGroup style="display:table;margin:50px auto;">
|
||||||
<Button size="large" type="primary" @click="createStep--" v-if="createStep!=0">
|
<Button
|
||||||
<Icon type="ios-arrow-back"></Icon>
|
size="large"
|
||||||
上一步
|
type="primary"
|
||||||
|
@click="createStep--"
|
||||||
|
v-if="createStep!=0"
|
||||||
|
>
|
||||||
|
<Icon type="ios-arrow-back"></Icon>上一步
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="large" type="success" @click="showAddPlugin=true" v-if="createStep==1">+
|
<Button
|
||||||
|
size="large"
|
||||||
|
type="success"
|
||||||
|
@click="showAddPlugin=true"
|
||||||
|
v-if="createStep==1"
|
||||||
|
>
|
||||||
|
+
|
||||||
添加插件
|
添加插件
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="large" type="primary" @click="createStep++" v-if="createStep!=2">下一步
|
<Button
|
||||||
|
size="large"
|
||||||
|
type="primary"
|
||||||
|
@click="createStep++"
|
||||||
|
v-if="createStep!=2"
|
||||||
|
>
|
||||||
|
下一步
|
||||||
<Icon type="ios-arrow-forward"></Icon>
|
<Icon type="ios-arrow-forward"></Icon>
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="large" type="success" @click="createInstance" v-else>开始创建</Button>
|
<Button size="large" type="success" @click="createInstance" v-else>开始创建</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane label="导入" name="name3">
|
<TabPane label="导入" name="name3"></TabPane>
|
||||||
|
|
||||||
</TabPane>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Content>
|
</Content>
|
||||||
<Modal v-model="showAddPlugin" title="添加Plugin" @on-ok="addPlugin">
|
<Modal v-model="showAddPlugin" title="添加Plugin" @on-ok="addPlugin">
|
||||||
@@ -78,7 +94,10 @@
|
|||||||
<Button slot="append" @click="showBuiltinPlugin=true">内置插件</Button>
|
<Button slot="append" @click="showBuiltinPlugin=true">内置插件</Button>
|
||||||
</i-input>
|
</i-input>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<Alert type="show-icon" v-if="!Object.values(builtinPlugins).includes(formPlugin.Path)">
|
<Alert
|
||||||
|
type="show-icon"
|
||||||
|
v-if="!Object.values(builtinPlugins).includes(formPlugin.Path)"
|
||||||
|
>
|
||||||
如果该插件是私有仓库,请到服务器上输入:echo "machine {{privateHost}} login 用户名 password 密码" >> ~/.netrc
|
如果该插件是私有仓库,请到服务器上输入:echo "machine {{privateHost}} login 用户名 password 密码" >> ~/.netrc
|
||||||
并且添加环境变量GOPRIVATE={{privateHost}}
|
并且添加环境变量GOPRIVATE={{privateHost}}
|
||||||
</Alert>
|
</Alert>
|
||||||
@@ -93,8 +112,7 @@
|
|||||||
<ListItemMeta :title="name" :description="item"></ListItemMeta>
|
<ListItemMeta :title="name" :description="item"></ListItemMeta>
|
||||||
<template slot="action">
|
<template slot="action">
|
||||||
<li @click="addBuiltin(name,item)">
|
<li @click="addBuiltin(name,item)">
|
||||||
<Icon type="ios-add"/>
|
<Icon type="ios-add" />添加
|
||||||
添加
|
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
@@ -105,102 +123,116 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CreateInstance from "../components/CreateInstance"
|
import CreateInstance from "../components/CreateInstance";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CreateInstance
|
CreateInstance
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
instanceName: "",
|
instanceName: "",
|
||||||
createStep: 0,
|
createStep: 0,
|
||||||
showCreate: false,
|
showCreate: false,
|
||||||
createInfo: null,
|
createInfo: null,
|
||||||
createPath: "/opt/monibuca",
|
createPath: "/opt/monibuca",
|
||||||
instances: [],
|
instances: {},
|
||||||
plugins: {},
|
plugins: {},
|
||||||
showAddPlugin: false,
|
showAddPlugin: false,
|
||||||
formPlugin: {},
|
formPlugin: {},
|
||||||
showBuiltinPlugin: false,
|
showBuiltinPlugin: false,
|
||||||
builtinPlugins: {
|
builtinPlugins: {
|
||||||
Auth: "github.com/langhuihui/monibuca/plugins/auth",
|
Auth: "github.com/langhuihui/monibuca/plugins/auth",
|
||||||
Cluster: "github.com/langhuihui/monibuca/plugins/cluster",
|
Cluster: "github.com/langhuihui/monibuca/plugins/cluster",
|
||||||
GateWay: "github.com/langhuihui/monibuca/plugins/gateway",
|
GateWay: "github.com/langhuihui/monibuca/plugins/gateway",
|
||||||
HDL: "github.com/langhuihui/monibuca/plugins/HDL",
|
HDL: "github.com/langhuihui/monibuca/plugins/HDL",
|
||||||
Jessica: "github.com/langhuihui/monibuca/plugins/jessica",
|
Jessica: "github.com/langhuihui/monibuca/plugins/jessica",
|
||||||
QoS: "github.com/langhuihui/monibuca/plugins/QoS",
|
QoS: "github.com/langhuihui/monibuca/plugins/QoS",
|
||||||
RecordFlv: "github.com/langhuihui/monibuca/plugins/record",
|
RecordFlv: "github.com/langhuihui/monibuca/plugins/record",
|
||||||
RTMP: "github.com/langhuihui/monibuca/plugins/rtmp"
|
RTMP: "github.com/langhuihui/monibuca/plugins/rtmp"
|
||||||
},
|
},
|
||||||
defaultConfig: {
|
defaultConfig: {
|
||||||
Auth: 'Key = "www.monibuca.com"',
|
Auth: 'Key = "www.monibuca.com"',
|
||||||
RecordFlv: 'Path="./resource"',
|
RecordFlv: 'Path="./resource"',
|
||||||
QoS: 'Suffix = ["high","medium","low"]',
|
QoS: 'Suffix = ["high","medium","low"]',
|
||||||
Cluster: 'Master = "localhost:2019"\nListenAddr = ":2019"',
|
Cluster: 'Master = "localhost:2019"\nListenAddr = ":2019"',
|
||||||
GateWay: 'ListenAddr = ":8081"',
|
GateWay: 'ListenAddr = ":8081"',
|
||||||
RTMP: 'ListenAddr = ":1935"',
|
RTMP: 'ListenAddr = ":1935"',
|
||||||
Jessica: 'ListenAddr = ":8080"',
|
Jessica: 'ListenAddr = ":8080"',
|
||||||
HDL: 'ListenAddr = ":2020"',
|
HDL: 'ListenAddr = ":2020"'
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
pluginStr() {
|
||||||
|
return Object.values(this.plugins)
|
||||||
|
.map(x => x.Path)
|
||||||
|
.join("\n");
|
||||||
},
|
},
|
||||||
computed: {
|
configStr() {
|
||||||
pluginStr() {
|
return Object.values(this.plugins)
|
||||||
return Object.values(this.plugins).map(x => x.Path).join("\n")
|
.map(
|
||||||
},
|
x => `[Plugins.${x.Name}]
|
||||||
configStr() {
|
${x.Config || ""}`
|
||||||
return Object.values(this.plugins).map(x => `[Plugins.${x.Name}]
|
)
|
||||||
${x.Config || ""}`).join("\n")
|
.join("\n");
|
||||||
},
|
|
||||||
privateHost(){
|
|
||||||
return (this.formPlugin.Path && this.formPlugin.Path.split("/")[0])||"仓库域名"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
privateHost() {
|
||||||
goUp() {
|
return (
|
||||||
let paths = this.createPath.split("/")
|
(this.formPlugin.Path && this.formPlugin.Path.split("/")[0]) ||
|
||||||
paths.pop()
|
"仓库域名"
|
||||||
this.createPath = paths.join("/")
|
);
|
||||||
},
|
}
|
||||||
createInstance() {
|
},
|
||||||
this.showCreate = true
|
mounted() {
|
||||||
this.createInfo = {
|
window.ajax.getJSON("/list").then(x => {
|
||||||
Name: this.instanceName || this.createPath.split('/').pop(),
|
this.instances = x;
|
||||||
Path: this.createPath,
|
});
|
||||||
Plugins: Object.values(this.plugins).map(x => x.Path),
|
},
|
||||||
Config: this.configStr
|
methods: {
|
||||||
}
|
goUp() {
|
||||||
},
|
let paths = this.createPath.split("/");
|
||||||
addPlugin() {
|
paths.pop();
|
||||||
this.plugins[this.formPlugin.Name] = this.formPlugin
|
this.createPath = paths.join("/");
|
||||||
this.formPlugin = {}
|
},
|
||||||
},
|
createInstance() {
|
||||||
removePlugin(name) {
|
this.showCreate = true;
|
||||||
delete this.plugins[name]
|
this.createInfo = {
|
||||||
this.$forceUpdate()
|
Name: this.instanceName || this.createPath.split("/").pop(),
|
||||||
},
|
Path: this.createPath,
|
||||||
addBuiltin(name, item) {
|
Plugins: Object.values(this.plugins).map(x => x.Path),
|
||||||
this.formPlugin.Name = name
|
Config: this.configStr
|
||||||
this.formPlugin.Path = item
|
};
|
||||||
this.formPlugin.Config = this.defaultConfig[name]
|
},
|
||||||
this.showBuiltinPlugin = false
|
addPlugin() {
|
||||||
}
|
this.plugins[this.formPlugin.Name] = this.formPlugin;
|
||||||
|
this.formPlugin = {};
|
||||||
|
},
|
||||||
|
removePlugin(name) {
|
||||||
|
delete this.plugins[name];
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
addBuiltin(name, item) {
|
||||||
|
this.formPlugin.Name = name;
|
||||||
|
this.formPlugin.Path = item;
|
||||||
|
this.formPlugin.Config = this.defaultConfig[name];
|
||||||
|
this.showBuiltinPlugin = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.content {
|
.content {
|
||||||
background: white
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ivu-tabs .ivu-tabs-tabpane {
|
.ivu-tabs .ivu-tabs-tabpane {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Reference in New Issue
Block a user