mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-01 12:32:09 +00:00
[feature] add multi domain tls (CDN ready)
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
parent
3f2e1aede9
commit
1fa9101b40
9 changed files with 167 additions and 80 deletions
|
@ -153,9 +153,9 @@ class DBInbound {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
genLink(clientIndex) {
|
genLink(address=this.address, remark=this.remark, clientIndex=0) {
|
||||||
const inbound = this.toInbound();
|
const inbound = this.toInbound();
|
||||||
return inbound.genLink(this.address, this.remark, clientIndex);
|
return inbound.genLink(address, remark, clientIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
get genInboundLinks() {
|
get genInboundLinks() {
|
||||||
|
|
|
@ -498,8 +498,7 @@ class TlsStreamSettings extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ObjectUtil.isEmpty(json.settings)) {
|
if (!ObjectUtil.isEmpty(json.settings)) {
|
||||||
settings = new TlsStreamSettings.Settings(json.settings.allowInsecure , json.settings.fingerprint, json.settings.serverName);
|
settings = new TlsStreamSettings.Settings(json.settings.allowInsecure , json.settings.fingerprint, json.settings.serverName, json.settings.domains); }
|
||||||
}
|
|
||||||
return new TlsStreamSettings(
|
return new TlsStreamSettings(
|
||||||
json.serverName,
|
json.serverName,
|
||||||
json.minVersion,
|
json.minVersion,
|
||||||
|
@ -566,17 +565,19 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
|
||||||
};
|
};
|
||||||
|
|
||||||
TlsStreamSettings.Settings = class extends XrayCommonClass {
|
TlsStreamSettings.Settings = class extends XrayCommonClass {
|
||||||
constructor(allowInsecure = false, fingerprint = '', serverName = '') {
|
constructor(allowInsecure = false, fingerprint = '', serverName = '', domains = []) {
|
||||||
super();
|
super();
|
||||||
this.allowInsecure = allowInsecure;
|
this.allowInsecure = allowInsecure;
|
||||||
this.fingerprint = fingerprint;
|
this.fingerprint = fingerprint;
|
||||||
this.serverName = serverName;
|
this.serverName = serverName;
|
||||||
|
this.domains = domains;
|
||||||
}
|
}
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
return new TlsStreamSettings.Settings(
|
return new TlsStreamSettings.Settings(
|
||||||
json.allowInsecure,
|
json.allowInsecure,
|
||||||
json.fingerprint,
|
json.fingerprint,
|
||||||
json.servername,
|
json.serverName,
|
||||||
|
json.domains,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
toJson() {
|
toJson() {
|
||||||
|
@ -584,6 +585,7 @@ TlsStreamSettings.Settings = class extends XrayCommonClass {
|
||||||
allowInsecure: this.allowInsecure,
|
allowInsecure: this.allowInsecure,
|
||||||
fingerprint: this.fingerprint,
|
fingerprint: this.fingerprint,
|
||||||
serverName: this.serverName,
|
serverName: this.serverName,
|
||||||
|
domains: this.domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1508,24 +1510,12 @@ class Inbound extends XrayCommonClass {
|
||||||
genLink(address='', remark='', clientIndex=0) {
|
genLink(address='', remark='', clientIndex=0) {
|
||||||
switch (this.protocol) {
|
switch (this.protocol) {
|
||||||
case Protocols.VMESS:
|
case Protocols.VMESS:
|
||||||
if (this.settings.vmesses[clientIndex].email != ""){
|
|
||||||
remark += '-' + this.settings.vmesses[clientIndex].email
|
|
||||||
}
|
|
||||||
return this.genVmessLink(address, remark, clientIndex);
|
return this.genVmessLink(address, remark, clientIndex);
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
if (this.settings.vlesses[clientIndex].email != ""){
|
|
||||||
remark += '-' + this.settings.vlesses[clientIndex].email
|
|
||||||
}
|
|
||||||
return this.genVLESSLink(address, remark, clientIndex);
|
return this.genVLESSLink(address, remark, clientIndex);
|
||||||
case Protocols.SHADOWSOCKS:
|
case Protocols.SHADOWSOCKS:
|
||||||
if (this.settings.shadowsockses[clientIndex].email != ""){
|
|
||||||
remark = this.settings.shadowsockses[clientIndex].email
|
|
||||||
}
|
|
||||||
return this.genSSLink(address, remark, clientIndex);
|
return this.genSSLink(address, remark, clientIndex);
|
||||||
case Protocols.TROJAN:
|
case Protocols.TROJAN:
|
||||||
if (this.settings.trojans[clientIndex].email != ""){
|
|
||||||
remark += '-' + this.settings.trojans[clientIndex].email
|
|
||||||
}
|
|
||||||
return this.genTrojanLink(address, remark, clientIndex);
|
return this.genTrojanLink(address, remark, clientIndex);
|
||||||
default: return '';
|
default: return '';
|
||||||
}
|
}
|
||||||
|
@ -1537,12 +1527,17 @@ class Inbound extends XrayCommonClass {
|
||||||
case Protocols.VMESS:
|
case Protocols.VMESS:
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
case Protocols.TROJAN:
|
case Protocols.TROJAN:
|
||||||
JSON.parse(this.settings).clients.forEach((_,index) => {
|
case Protocols.SHADOWSOCKS:
|
||||||
link += this.genLink(address, remark, index) + '\r\n';
|
JSON.parse(this.settings).clients.forEach((client,index) => {
|
||||||
|
if(this.tls && !ObjectUtil.isArrEmpty(this.stream.tls.settings.domains)){
|
||||||
|
this.stream.tls.settings.domains.forEach((domain) => {
|
||||||
|
link += this.genLink(domain.domain, remark + '-' + client.email + '-' + domain.remark, index) + '\r\n';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
link += this.genLink(address, remark + '-' + client.email, index) + '\r\n';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return link;
|
return link;
|
||||||
case Protocols.SHADOWSOCKS:
|
|
||||||
return (this.genSSLink(address, remark) + '\r\n');
|
|
||||||
default: return '';
|
default: return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,11 +146,18 @@ func (a *InboundController) getClientIps(c *gin.Context) {
|
||||||
|
|
||||||
ips, err := a.inboundService.GetInboundClientIps(email)
|
ips, err := a.inboundService.GetInboundClientIps(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
jsonObj(c, "Failed to get client IPs", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ips == "" {
|
||||||
jsonObj(c, "No IP Record", nil)
|
jsonObj(c, "No IP Record", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonObj(c, ips, nil)
|
jsonObj(c, ips, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *InboundController) clearClientIps(c *gin.Context) {
|
func (a *InboundController) clearClientIps(c *gin.Context) {
|
||||||
email := c.Param("email")
|
email := c.Param("email")
|
||||||
|
|
||||||
|
|
|
@ -7,47 +7,53 @@
|
||||||
<a-tag color="green" style="margin-bottom: 10px;display: block;text-align: center;">
|
<a-tag color="green" style="margin-bottom: 10px;display: block;text-align: center;">
|
||||||
{{ i18n "pages.inbounds.clickOnQRcode" }}
|
{{ i18n "pages.inbounds.clickOnQRcode" }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="qrModal.clientName" color="orange" style="margin-bottom: 10px;display: block;text-align: center;">
|
<template v-if="app.subSettings.enable && qrModal.subId">
|
||||||
{{ i18n "pages.inbounds.email" }}: "[[ qrModal.clientName ]]"
|
<a-divider>Subscription</a-divider>
|
||||||
</a-tag>
|
<canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas>
|
||||||
<canvas @click="copyToClipboard()" id="qrCode" style="width: 100%; height: 100%; margin-top: 10px;"></canvas>
|
</template>
|
||||||
|
<a-divider>{{ i18n "pages.inbounds.client" }}</a-divider>
|
||||||
|
<template v-for="(row, index) in qrModal.qrcodes">
|
||||||
|
<a-tag color="orange" style="margin-top: 10px;display: block;text-align: center;">[[ row.remark ]]</a-tag>
|
||||||
|
<canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas>
|
||||||
|
</template>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const qrModal = {
|
const qrModal = {
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
clientIndex: 0,
|
||||||
inbound: new Inbound(),
|
inbound: new Inbound(),
|
||||||
dbInbound: new DBInbound(),
|
dbInbound: new DBInbound(),
|
||||||
copyText: '',
|
client: null,
|
||||||
clientName: null,
|
qrcodes: [],
|
||||||
qrcode: null,
|
|
||||||
clipboard: null,
|
clipboard: null,
|
||||||
visible: false,
|
visible: false,
|
||||||
show: function (title = '', content = '', dbInbound = new DBInbound(), copyText = '', clientName = null) {
|
subId: '',
|
||||||
|
show: function (title = '', dbInbound = new DBInbound(), clientIndex = 0) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.content = content;
|
this.clientIndex = clientIndex;
|
||||||
this.dbInbound = dbInbound;
|
this.dbInbound = dbInbound;
|
||||||
this.inbound = dbInbound.toInbound();
|
this.inbound = dbInbound.toInbound();
|
||||||
this.clientName = clientName;
|
settings = JSON.parse(this.inbound.settings);
|
||||||
if (ObjectUtil.isEmpty(copyText)) {
|
this.client = settings.clients[clientIndex];
|
||||||
this.copyText = content;
|
remark = this.dbInbound.remark + "-" + this.client.email;
|
||||||
|
address = this.dbInbound.address;
|
||||||
|
this.qrcodes = [];
|
||||||
|
if (this.inbound.tls && !ObjectUtil.isArrEmpty(this.inbound.stream.tls.settings.domains)) {
|
||||||
|
this.inbound.stream.tls.settings.domains.forEach((domain) => {
|
||||||
|
this.qrcodes.push({
|
||||||
|
remark: remark + "-" + domain.remark,
|
||||||
|
link: this.inbound.genLink(domain.domain, remark + "-" + domain.remark, clientIndex)
|
||||||
|
});
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.copyText = copyText;
|
this.qrcodes.push({
|
||||||
|
remark: remark,
|
||||||
|
link: this.inbound.genLink(address, remark, clientIndex)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
qrModalApp.$nextTick(() => {
|
|
||||||
if (this.qrcode === null) {
|
|
||||||
this.qrcode = new QRious({
|
|
||||||
element: document.querySelector('#qrCode'),
|
|
||||||
size: 260,
|
|
||||||
value: content,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.qrcode.value = content;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
close: function () {
|
close: function () {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
|
@ -61,16 +67,40 @@
|
||||||
qrModal: qrModal,
|
qrModal: qrModal,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
copyToClipboard() {
|
copyToClipboard(elmentId,content) {
|
||||||
this.qrModal.clipboard = new ClipboardJS('#qrCode', {
|
this.qrModal.clipboard = new ClipboardJS('#'+elmentId, {
|
||||||
text: () => this.qrModal.copyText,
|
text: () => content,
|
||||||
});
|
});
|
||||||
this.qrModal.clipboard.on('success', () => {
|
this.qrModal.clipboard.on('success', () => {
|
||||||
app.$message.success('{{ i18n "copied" }}')
|
app.$message.success('{{ i18n "copied" }}')
|
||||||
this.qrModal.clipboard.destroy();
|
this.qrModal.clipboard.destroy();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
setQrCode(elmentId,content) {
|
||||||
|
new QRious({
|
||||||
|
element: document.querySelector('#'+elmentId),
|
||||||
|
size: 260,
|
||||||
|
value: content,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
genSubLink(subID) {
|
||||||
|
protocol = app.subSettings.tls ? "https://" : "http://";
|
||||||
|
hostName = app.subSettings.domain === "" ? window.location.hostname : app.subSettings.domain;
|
||||||
|
subPort = app.subSettings.port;
|
||||||
|
port = (subPort === 443 && app.subSettings.tls) || (subPort === 80 && !app.subSettings.tls) ? "" : ":" + String(subPort);
|
||||||
|
subPath = app.subSettings.path;
|
||||||
|
return protocol + hostName + port + subPath + subID;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updated() {
|
||||||
|
if (qrModal.client.subId){
|
||||||
|
qrModal.subId = qrModal.client.subId;
|
||||||
|
this.setQrCode("qrCode-sub",this.genSubLink(this.subId));
|
||||||
|
}
|
||||||
|
qrModal.qrcodes.forEach((element,index) => {
|
||||||
|
this.setQrCode("qrCode-"+index, element.link);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -33,7 +33,21 @@
|
||||||
|
|
||||||
<!-- tls settings -->
|
<!-- tls settings -->
|
||||||
<a-form v-if="inbound.tls" layout="inline">
|
<a-form v-if="inbound.tls" layout="inline">
|
||||||
<a-form-item label='{{ i18n "domainName" }}'>
|
<a-form-item label='Multi Domain'>
|
||||||
|
<a-switch v-model="multiDomain"></a-switch>
|
||||||
|
<a-button v-if="multiDomain" size="small" @click="inbound.stream.tls.settings.domains.push({remark: '', domain: ''})">+</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="multiDomain" label='Domains'>
|
||||||
|
<a-input-group v-for="(row, index) in inbound.stream.tls.settings.domains">
|
||||||
|
<a-input style="width: 40%" v-model.trim="row.remark" addon-before='{{ i18n "remark" }}'></a-input>
|
||||||
|
<a-input style="width: 60%" v-model.trim="row.domain" addon-before='{{ i18n "host" }}'>
|
||||||
|
<template slot="addonAfter">
|
||||||
|
<a-button size="small" style="margin: 0px" @click="inbound.stream.tls.settings.domains.splice(index, 1)">-</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-else label='{{ i18n "domainName" }}'>
|
||||||
<a-input v-model.trim="inbound.stream.tls.server" style="width: 250px"></a-input>
|
<a-input v-model.trim="inbound.stream.tls.server" style="width: 250px"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="CipherSuites">
|
<a-form-item label="CipherSuites">
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<a-tag v-if="!isClientEnabled(record, client.email)" color="red">{{ i18n "depleted" }}</a-tag>
|
<a-tag v-if="!isClientEnabled(record, client.email)" color="red">{{ i18n "depleted" }}</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template slot="traffic" slot-scope="text, client">
|
<template slot="traffic" slot-scope="text, client">
|
||||||
<a-tag :color="statsColor(record, client.email)" @click="alert(usageColor(0,1024,512))">[[ sizeFormat(getUpStats(record, client.email)) ]] / [[ sizeFormat(getDownStats(record, client.email)) ]]</a-tag>
|
<a-tag :color="statsColor(record, client.email)">[[ sizeFormat(getUpStats(record, client.email)) ]] / [[ sizeFormat(getDownStats(record, client.email)) ]]</a-tag>
|
||||||
<template v-if="client._totalGB > 0">
|
<template v-if="client._totalGB > 0">
|
||||||
<a-tag :color="statsColor(record, client.email)">[[client._totalGB]]GB</a-tag>
|
<a-tag :color="statsColor(record, client.email)">[[client._totalGB]]GB</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -59,10 +59,9 @@
|
||||||
</td>
|
</td>
|
||||||
<td v-else-if="inbound.reality">
|
<td v-else-if="inbound.reality">
|
||||||
reality: <a-tag color="green">{{ i18n "enabled" }}</a-tag><br />
|
reality: <a-tag color="green">{{ i18n "enabled" }}</a-tag><br />
|
||||||
reality {{ i18n "domainName" }}: <a-tag :color="inbound.serverName ? 'green' : 'orange'">[[ inbound.serverName ? inbound.serverName : '' ]]</a-tag>
|
reality Destination: <a-tag :color="inbound.stream.reality.dest ? 'green' : 'orange'">[[ inbound.stream.reality.dest ]]</a-tag>
|
||||||
</td>
|
</td>
|
||||||
<td v-else>
|
<td v-else>tls: <a-tag color="red">{{ i18n "disabled" }}</a-tag>
|
||||||
tls: <a-tag color="red">{{ i18n "disabled" }}</a-tag>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -110,17 +109,16 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<table v-if="infoModal.clientSettings.subId + infoModal.clientSettings.tgId" style="margin-bottom: 10px;">
|
<template v-if="app.subSettings.enable && infoModal.clientSettings.subId">
|
||||||
<tr v-if="infoModal.clientSettings.subId">
|
<a-divider>Subscription link</a-divider>
|
||||||
<td>Subscription link</td>
|
<a :href="[[ infoModal.subLink ]]" target="_blank">[[ infoModal.subLink ]]</a>
|
||||||
<td><a :href="[[ subBase + infoModal.clientSettings.subId ]]" target="_blank">[[ subBase + infoModal.clientSettings.subId ]]</a></td>
|
<a-icon id="copy-sub-link" type="snippets" @click="copyToClipboard('copy-sub-link', infoModal.subLink)"></a-icon>
|
||||||
<td><a-icon id="copy-sub-link" type="snippets" @click="copyToClipboard('copy-sub-link', subBase + infoModal.clientSettings.subId)"></a-icon></td>
|
</template>
|
||||||
</tr>
|
<template v-if="app.tgBotEnable && infoModal.clientSettings.tgId">
|
||||||
<tr v-if="infoModal.clientSettings.tgId">
|
<a-divider>Telegram Username</a-divider>
|
||||||
<td>Telegram ID</td>
|
<a :href="[[ infoModal.tgLink ]]" target="_blank">@[[ infoModal.clientSettings.tgId ]]</a>
|
||||||
<td><a :href="[[ tgBase + infoModal.clientSettings.tgId ]]" target="_blank">@[[ infoModal.clientSettings.tgId ]]</a></td>
|
<a-icon id="copy-tg-link" type="snippets" @click="copyToClipboard('copy-tg-link', '@' + infoModal.clientSettings.tgId)"></a-icon>
|
||||||
</tr>
|
</template>
|
||||||
</table>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-divider></a-divider>
|
<a-divider></a-divider>
|
||||||
|
@ -190,8 +188,14 @@
|
||||||
</template>
|
</template>
|
||||||
<div v-if="dbInbound.hasLink()">
|
<div v-if="dbInbound.hasLink()">
|
||||||
<a-divider>URL</a-divider>
|
<a-divider>URL</a-divider>
|
||||||
<p>[[ infoModal.link ]]</p>
|
<a-row v-for="(link,index) in infoModal.links">
|
||||||
<button class="ant-btn ant-btn-primary" id="copy-url-link" @click="copyToClipboard('copy-url-link', infoModal.link)"><a-icon type="snippets"></a-icon>{{ i18n "copy" }}</button>
|
<a-col :span="21"><a-tag color="cyan">[[ link.remark ]]</a-tag><br />[[ link.link ]]</a-col>
|
||||||
|
<a-col :span="3" style="text-align: right;">
|
||||||
|
<button class="ant-btn ant-btn-primary" :id="'copy-url-link-'+index" @click="copyToClipboard('copy-url-link-'+index, link.link)">
|
||||||
|
<a-icon type="snippets"></a-icon>{{ i18n "copy" }}
|
||||||
|
</button>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<script>
|
<script>
|
||||||
|
@ -206,23 +210,56 @@
|
||||||
upStats: 0,
|
upStats: 0,
|
||||||
downStats: 0,
|
downStats: 0,
|
||||||
clipboard: null,
|
clipboard: null,
|
||||||
link: null,
|
links: [],
|
||||||
index: null,
|
index: null,
|
||||||
isExpired: false,
|
isExpired: false,
|
||||||
|
subLink: '',
|
||||||
|
tgLink: '',
|
||||||
show(dbInbound, index) {
|
show(dbInbound, index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.inbound = dbInbound.toInbound();
|
this.inbound = dbInbound.toInbound();
|
||||||
this.dbInbound = new DBInbound(dbInbound);
|
this.dbInbound = new DBInbound(dbInbound);
|
||||||
this.link = dbInbound.genLink(index);
|
|
||||||
this.settings = JSON.parse(this.inbound.settings);
|
this.settings = JSON.parse(this.inbound.settings);
|
||||||
this.clientSettings = this.settings.clients ? Object.values(this.settings.clients)[index] : null;
|
this.clientSettings = this.settings.clients ? Object.values(this.settings.clients)[index] : null;
|
||||||
this.isExpired = this.inbound.isExpiry(index);
|
this.isExpired = this.inbound.isExpiry(index);
|
||||||
this.clientStats = this.settings.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
|
this.clientStats = this.settings.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
|
||||||
|
remark = this.dbInbound.remark + "-" + this.clientSettings.email;
|
||||||
|
address = this.dbInbound.address;
|
||||||
|
this.links = [];
|
||||||
|
if (this.inbound.tls && !ObjectUtil.isArrEmpty(this.inbound.stream.tls.settings.domains)) {
|
||||||
|
this.inbound.stream.tls.settings.domains.forEach((domain) => {
|
||||||
|
this.links.push({
|
||||||
|
remark: remark + "-" + domain.remark,
|
||||||
|
link: this.inbound.genLink(domain.domain, remark + "-" + domain.remark, index)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.links.push({
|
||||||
|
remark: remark,
|
||||||
|
link: this.inbound.genLink(address, remark, index)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.clientSettings) {
|
||||||
|
if (this.clientSettings.subId) {
|
||||||
|
this.subLink = this.genSubLink(this.clientSettings.subId);
|
||||||
|
}
|
||||||
|
if (this.clientSettings.tgId) {
|
||||||
|
this.tgLink = "https://t.me/" + this.clientSettings.tgId;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
infoModal.visible = false;
|
infoModal.visible = false;
|
||||||
},
|
},
|
||||||
|
genSubLink(subID) {
|
||||||
|
protocol = app.subSettings.tls ? "https://" : "http://";
|
||||||
|
hostName = app.subSettings.domain === "" ? window.location.hostname : app.subSettings.domain;
|
||||||
|
subPort = app.subSettings.port;
|
||||||
|
port = (subPort === 443 && app.subSettings.tls) || (subPort === 80 && !app.subSettings.tls) ? "" : ":" + String(subPort);
|
||||||
|
subPath = app.subSettings.path;
|
||||||
|
return protocol + hostName + port + subPath + subID;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const infoModalApp = new Vue({
|
const infoModalApp = new Vue({
|
||||||
|
@ -248,12 +285,6 @@
|
||||||
}
|
}
|
||||||
return infoModal.dbInbound.isEnable;
|
return infoModal.dbInbound.isEnable;
|
||||||
},
|
},
|
||||||
get subBase() {
|
|
||||||
return window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "") + basePath + "sub/";
|
|
||||||
},
|
|
||||||
get tgBase() {
|
|
||||||
return "https://t.me/"
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
copyToClipboard(elmentId, content) {
|
copyToClipboard(elmentId, content) {
|
||||||
|
|
|
@ -90,6 +90,18 @@
|
||||||
set delayedExpireDays(days) {
|
set delayedExpireDays(days) {
|
||||||
this.client.expiryTime = -86400000 * days;
|
this.client.expiryTime = -86400000 * days;
|
||||||
},
|
},
|
||||||
|
get multiDomain() {
|
||||||
|
return this.inbound.stream.tls.settings.domains.length > 0;
|
||||||
|
},
|
||||||
|
set multiDomain(value) {
|
||||||
|
if (value) {
|
||||||
|
inModal.inbound.stream.tls.server = "";
|
||||||
|
inModal.inbound.stream.tls.settings.domains = [{remark: "", domain: window.location.host.split(":")[0]}];
|
||||||
|
} else {
|
||||||
|
inModal.inbound.stream.tls.server = "";
|
||||||
|
inModal.inbound.stream.tls.settings.domains = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
streamNetworkChange() {
|
streamNetworkChange() {
|
||||||
|
|
|
@ -746,9 +746,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showQrcode(dbInbound, clientIndex) {
|
showQrcode(dbInbound, clientIndex) {
|
||||||
const clientName = JSON.parse(dbInbound.settings).clients[clientIndex].email;
|
qrModal.show('{{ i18n "qrCode"}}', dbInbound, clientIndex);
|
||||||
const link = dbInbound.genLink(clientIndex);
|
|
||||||
qrModal.show('{{ i18n "qrCode"}}', link, dbInbound, '', clientName);
|
|
||||||
},
|
},
|
||||||
showInfo(dbInbound, index) {
|
showInfo(dbInbound, index) {
|
||||||
infoModal.show(dbInbound, index);
|
infoModal.show(dbInbound, index);
|
||||||
|
|
Loading…
Reference in a new issue