This commit is contained in:
MHSanaei
2023-02-09 22:48:06 +03:30
commit b73e4173a3
133 changed files with 61908 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.interceptors.request.use(
config => {
config.data = Qs.stringify(config.data, {
arrayFormat: 'repeat'
});
return config;
},
error => Promise.reject(error)
);

84
web/assets/js/langs.js Normal file
View File

@@ -0,0 +1,84 @@
supportLangs = [
{
name : "English",
value : "en-US",
icon : "🇺🇸"
},
{
name : "Farsi",
value : "fa_IR",
icon : "🇮🇷"
},
{
name : "汉语",
value : "zh-Hans",
icon : "🇨🇳"
},
]
function getLang(){
let lang = getCookie('lang')
if (! lang){
if (window.navigator){
lang = window.navigator.language || window.navigator.userLanguage;
if (isSupportLang(lang)){
setCookie('lang' , lang , 150)
}else{
setCookie('lang' , 'en-US' , 150)
window.location.reload();
}
}else{
setCookie('lang' , 'en-US' , 150)
window.location.reload();
}
}
return lang;
}
function setLang(lang){
if (!isSupportLang(lang)){
lang = 'en-US';
}
setCookie('lang' , lang , 150)
window.location.reload();
}
function isSupportLang(lang){
for (l of supportLangs){
if (l.value === lang){
return true;
}
}
return false;
}
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
let expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

View File

@@ -0,0 +1,185 @@
class User {
constructor() {
this.username = "";
this.password = "";
}
}
class Msg {
constructor(success, msg, obj) {
this.success = false;
this.msg = "";
this.obj = null;
if (success != null) {
this.success = success;
}
if (msg != null) {
this.msg = msg;
}
if (obj != null) {
this.obj = obj;
}
}
}
class DBInbound {
constructor(data) {
this.id = 0;
this.userId = 0;
this.up = 0;
this.down = 0;
this.total = 0;
this.remark = "";
this.enable = true;
this.expiryTime = 0;
this.listen = "";
this.port = 0;
this.protocol = "";
this.settings = "";
this.streamSettings = "";
this.tag = "";
this.sniffing = "";
this.clientStats = ""
if (data == null) {
return;
}
ObjectUtil.cloneProps(this, data);
}
get totalGB() {
return toFixed(this.total / ONE_GB, 2);
}
set totalGB(gb) {
this.total = toFixed(gb * ONE_GB, 0);
}
get isVMess() {
return this.protocol === Protocols.VMESS;
}
get isVLess() {
return this.protocol === Protocols.VLESS;
}
get isTrojan() {
return this.protocol === Protocols.TROJAN;
}
get isSS() {
return this.protocol === Protocols.SHADOWSOCKS;
}
get isSocks() {
return this.protocol === Protocols.SOCKS;
}
get isHTTP() {
return this.protocol === Protocols.HTTP;
}
get address() {
let address = location.hostname;
if (!ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0") {
address = this.listen;
}
return address;
}
get _expiryTime() {
if (this.expiryTime === 0) {
return null;
}
return moment(this.expiryTime);
}
set _expiryTime(t) {
if (t == null) {
this.expiryTime = 0;
} else {
this.expiryTime = t.valueOf();
}
}
get isExpiry() {
return this.expiryTime < new Date().getTime();
}
toInbound() {
let settings = {};
if (!ObjectUtil.isEmpty(this.settings)) {
settings = JSON.parse(this.settings);
}
let streamSettings = {};
if (!ObjectUtil.isEmpty(this.streamSettings)) {
streamSettings = JSON.parse(this.streamSettings);
}
let sniffing = {};
if (!ObjectUtil.isEmpty(this.sniffing)) {
sniffing = JSON.parse(this.sniffing);
}
const config = {
port: this.port,
listen: this.listen,
protocol: this.protocol,
settings: settings,
streamSettings: streamSettings,
tag: this.tag,
sniffing: sniffing,
clientStats: this.clientStats,
};
return Inbound.fromJson(config);
}
hasLink() {
switch (this.protocol) {
case Protocols.VMESS:
case Protocols.VLESS:
case Protocols.TROJAN:
case Protocols.SHADOWSOCKS:
return true;
default:
return false;
}
}
genLink() {
const inbound = this.toInbound();
return inbound.genLink(this.address, this.remark);
}
}
class AllSetting {
constructor(data) {
this.webListen = "";
this.webPort = 54321;
this.webCertFile = "";
this.webKeyFile = "";
this.webBasePath = "/";
this.tgBotEnable = false;
this.tgBotToken = "";
this.tgBotChatId = 0;
this.tgRunTime = "";
this.xrayTemplateConfig = "";
this.timeLocation = "Asia/Shanghai";
if (data == null) {
return
}
ObjectUtil.cloneProps(this, data);
}
equals(other) {
return ObjectUtil.equals(this, other);
}
}

1819
web/assets/js/model/xray.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
const ONE_KB = 1024;
const ONE_MB = ONE_KB * 1024;
const ONE_GB = ONE_MB * 1024;
const ONE_TB = ONE_GB * 1024;
const ONE_PB = ONE_TB * 1024;
function sizeFormat(size) {
if (size < ONE_KB) {
return size.toFixed(0) + " B";
} else if (size < ONE_MB) {
return (size / ONE_KB).toFixed(2) + " KB";
} else if (size < ONE_GB) {
return (size / ONE_MB).toFixed(2) + " MB";
} else if (size < ONE_TB) {
return (size / ONE_GB).toFixed(2) + " GB";
} else if (size < ONE_PB) {
return (size / ONE_TB).toFixed(2) + " TB";
} else {
return (size / ONE_PB).toFixed(2) + " PB";
}
}
function base64(str) {
return Base64.encode(str);
}
function safeBase64(str) {
return base64(str)
.replace(/\+/g, '-')
.replace(/=/g, '')
.replace(/\//g, '_');
}
function formatSecond(second) {
if (second < 60) {
return second.toFixed(0) + ' s';
} else if (second < 3600) {
return (second / 60).toFixed(0) + ' m';
} else if (second < 3600 * 24) {
return (second / 3600).toFixed(0) + ' h';
} else {
return (second / 3600 / 24).toFixed(0) + ' d';
}
}
function addZero(num) {
if (num < 10) {
return "0" + num;
} else {
return num;
}
}
function toFixed(num, n) {
n = Math.pow(10, n);
return Math.round(num * n) / n;
}

View File

@@ -0,0 +1,147 @@
const oneMinute = 1000 * 60; // 一分钟的毫秒数
const oneHour = oneMinute * 60; // 一小时的毫秒数
const oneDay = oneHour * 24; // 一天的毫秒数
const oneWeek = oneDay * 7; // 一星期的毫秒数
const oneMonth = oneDay * 30; // 一个月的毫秒数
/**
* 按天数减少
*
* @param days 要减少的天数
*/
Date.prototype.minusDays = function (days) {
return this.minusMillis(oneDay * days);
};
/**
* 按天数增加
*
* @param days 要增加的天数
*/
Date.prototype.plusDays = function (days) {
return this.plusMillis(oneDay * days);
};
/**
* 按小时减少
*
* @param hours 要减少的小时数
*/
Date.prototype.minusHours = function (hours) {
return this.minusMillis(oneHour * hours);
};
/**
* 按小时增加
*
* @param hours 要增加的小时数
*/
Date.prototype.plusHours = function (hours) {
return this.plusMillis(oneHour * hours);
};
/**
* 按分钟减少
*
* @param minutes 要减少的分钟数
*/
Date.prototype.minusMinutes = function (minutes) {
return this.minusMillis(oneMinute * minutes);
};
/**
* 按分钟增加
*
* @param minutes 要增加的分钟数
*/
Date.prototype.plusMinutes = function (minutes) {
return this.plusMillis(oneMinute * minutes);
};
/**
* 按毫秒减少
*
* @param millis 要减少的毫秒数
*/
Date.prototype.minusMillis = function(millis) {
let time = this.getTime() - millis;
let newDate = new Date();
newDate.setTime(time);
return newDate;
};
/**
* 按毫秒增加
*
* @param millis 要增加的毫秒数
*/
Date.prototype.plusMillis = function(millis) {
let time = this.getTime() + millis;
let newDate = new Date();
newDate.setTime(time);
return newDate;
};
/**
* 设置时间为当天的 00:00:00.000
*/
Date.prototype.setMinTime = function () {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
this.setMilliseconds(0);
return this;
};
/**
* 设置时间为当天的 23:59:59.999
*/
Date.prototype.setMaxTime = function () {
this.setHours(23);
this.setMinutes(59);
this.setSeconds(59);
this.setMilliseconds(999);
return this;
};
/**
* 格式化日期
*/
Date.prototype.formatDate = function () {
return this.getFullYear() + "-" + addZero(this.getMonth() + 1) + "-" + addZero(this.getDate());
};
/**
* 格式化时间
*/
Date.prototype.formatTime = function () {
return addZero(this.getHours()) + ":" + addZero(this.getMinutes()) + ":" + addZero(this.getSeconds());
};
/**
* 格式化日期加时间
*
* @param split 日期和时间之间的分隔符,默认是一个空格
*/
Date.prototype.formatDateTime = function (split = ' ') {
return this.formatDate() + split + this.formatTime();
};
class DateUtil {
// 字符串转 Date 对象
static parseDate(str) {
return new Date(str.replace(/-/g, '/'));
}
static formatMillis(millis) {
return moment(millis).format('YYYY-M-D H:m:s')
}
static firstDayOfMonth() {
const date = new Date();
date.setDate(1);
date.setMinTime();
return date;
}
}

291
web/assets/js/util/utils.js Normal file
View File

@@ -0,0 +1,291 @@
class HttpUtil {
static _handleMsg(msg) {
if (!(msg instanceof Msg)) {
return;
}
if (msg.msg === "") {
return;
}
if (msg.success) {
Vue.prototype.$message.success(msg.msg);
} else {
Vue.prototype.$message.error(msg.msg);
}
}
static _respToMsg(resp) {
const data = resp.data;
if (data == null) {
return new Msg(true);
} else if (typeof data === 'object') {
if (data.hasOwnProperty('success')) {
return new Msg(data.success, data.msg, data.obj);
} else {
return data;
}
} else {
return new Msg(false, 'unknown data:', data);
}
}
static async get(url, data, options) {
let msg;
try {
const resp = await axios.get(url, data, options);
msg = this._respToMsg(resp);
} catch (e) {
msg = new Msg(false, e.toString());
}
this._handleMsg(msg);
return msg;
}
static async post(url, data, options) {
let msg;
try {
const resp = await axios.post(url, data, options);
msg = this._respToMsg(resp);
} catch (e) {
msg = new Msg(false, e.toString());
}
this._handleMsg(msg);
return msg;
}
static async postWithModal(url, data, modal) {
if (modal) {
modal.loading(true);
}
const msg = await this.post(url, data);
if (modal) {
modal.loading(false);
if (msg instanceof Msg && msg.success) {
modal.close();
}
}
return msg;
}
}
class PromiseUtil {
static async sleep(timeout) {
await new Promise(resolve => {
setTimeout(resolve, timeout)
});
}
}
const seq = [
'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
];
class RandomUtil {
static randomIntRange(min, max) {
return parseInt(Math.random() * (max - min) + min, 10);
}
static randomInt(n) {
return this.randomIntRange(0, n);
}
static randomSeq(count) {
let str = '';
for (let i = 0; i < count; ++i) {
str += seq[this.randomInt(62)];
}
return str;
}
static randomLowerAndNum(count) {
let str = '';
for (let i = 0; i < count; ++i) {
str += seq[this.randomInt(36)];
}
return str;
}
static randomMTSecret() {
let str = '';
for (let i = 0; i < 32; ++i) {
let index = this.randomInt(16);
if (index <= 9) {
str += index;
} else {
str += seq[index - 10];
}
}
return str;
}
static randomUUID() {
let d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
});
}
}
class ObjectUtil {
static getPropIgnoreCase(obj, prop) {
for (const name in obj) {
if (!obj.hasOwnProperty(name)) {
continue;
}
if (name.toLowerCase() === prop.toLowerCase()) {
return obj[name];
}
}
return undefined;
}
static deepSearch(obj, key) {
if (obj instanceof Array) {
for (let i = 0; i < obj.length; ++i) {
if (this.deepSearch(obj[i], key)) {
return true;
}
}
} else if (obj instanceof Object) {
for (let name in obj) {
if (!obj.hasOwnProperty(name)) {
continue;
}
if (this.deepSearch(obj[name], key)) {
return true;
}
}
} else {
return obj.toString().indexOf(key) >= 0;
}
return false;
}
static isEmpty(obj) {
return obj === null || obj === undefined || obj === '';
}
static isArrEmpty(arr) {
return !this.isEmpty(arr) && arr.length === 0;
}
static copyArr(dest, src) {
dest.splice(0);
for (const item of src) {
dest.push(item);
}
}
static clone(obj) {
let newObj;
if (obj instanceof Array) {
newObj = [];
this.copyArr(newObj, obj);
} else if (obj instanceof Object) {
newObj = {};
for (const key of Object.keys(obj)) {
newObj[key] = obj[key];
}
} else {
newObj = obj;
}
return newObj;
}
static deepClone(obj) {
let newObj;
if (obj instanceof Array) {
newObj = [];
for (const item of obj) {
newObj.push(this.deepClone(item));
}
} else if (obj instanceof Object) {
newObj = {};
for (const key of Object.keys(obj)) {
newObj[key] = this.deepClone(obj[key]);
}
} else {
newObj = obj;
}
return newObj;
}
static cloneProps(dest, src, ...ignoreProps) {
if (dest == null || src == null) {
return;
}
const ignoreEmpty = this.isArrEmpty(ignoreProps);
for (const key of Object.keys(src)) {
if (!src.hasOwnProperty(key)) {
continue;
} else if (!dest.hasOwnProperty(key)) {
continue;
} else if (src[key] === undefined) {
continue;
}
if (ignoreEmpty) {
dest[key] = src[key];
} else {
let ignore = false;
for (let i = 0; i < ignoreProps.length; ++i) {
if (key === ignoreProps[i]) {
ignore = true;
break;
}
}
if (!ignore) {
dest[key] = src[key];
}
}
}
}
static delProps(obj, ...props) {
for (const prop of props) {
if (prop in obj) {
delete obj[prop];
}
}
}
static execute(func, ...args) {
if (!this.isEmpty(func) && typeof func === 'function') {
func(...args);
}
}
static orDefault(obj, defaultValue) {
if (obj == null) {
return defaultValue;
}
return obj;
}
static equals(a, b) {
for (const key in a) {
if (!a.hasOwnProperty(key)) {
continue;
}
if (!b.hasOwnProperty(key)) {
return false;
} else if (a[key] !== b[key]) {
return false;
}
}
return true;
}
}